詞雲簡介

“詞雲”由美國西北大學新聞學副教授、新媒體專業主任裡奇·戈登(Rich Gordon)於2006年最先使用,是通過形成“關鍵詞雲層”或“關鍵詞渲染”,對文字中出現頻率較高的“關鍵詞”的視覺上的突出

網上大部分文章介紹的是使用Python的jieba、wordcloud的庫生成詞雲圖,本文則介紹在C#中如何使用jieba.NET、WordCloudSharp庫生成詞雲圖,後者是前者的.NET實現。

準備工作

建立一個C#的控制檯專案,通過NuGet新增引用對jieba.NETWordCloudSharp的引用,使用方法可以參考以下連結:

安裝之後,在packages\jieba.NET目錄下找到Resources目錄,將整個Resources目錄拷貝到程式集所在目錄,這裡面是jieba.NET執行所需的詞典及其它資料檔案。

基本演算法

演算法主要步驟如下:

  • 提取關鍵詞:基於TF-IDF演算法、TextRank演算法提取文字的關鍵詞,按權重大小選取部分關鍵詞。
  • 統計關鍵詞詞頻:先將文字分詞,統計每個詞的詞頻,再篩選出關鍵詞的詞頻。
  • 生成詞雲圖:根據關鍵詞及其詞頻資訊在蒙版圖片的基礎上生成詞圖。

注:本文採用TF-IDF演算法提取關鍵詞,蒙版圖目前只支援黑白圖片

TF-IDF(詞頻-逆文件頻率)演算法是一種統計方法,用以評估一字詞對於一個檔案集或一個語料庫中的其中一份檔案的重要程度。字詞的重要性隨著它在檔案中出現的次數成正比增加,但同時會隨著它在語料庫中出現的頻率成反比下降

演算法實現

使用JiebaNet.Analyser.TfidfExtractor.ExtractTagsWithWeight(string text, int count = 20, IEnumerable allowPos = null)從指定文字中抽取關鍵詞的同時得到其權重,程式碼如下:

/// <summary>
/// 從指定文字中抽取關鍵詞的同時得到其權重
/// </summary>
/// <param name="text"></param>
/// <returns></returns>
static WordWeightPair[] ExtractTagsWithWeight(string text)
{
var extractor = new TfidfExtractor();
var wordWeight = extractor.ExtractTagsWithWeight(text, 50);
StringBuilder sbr = new StringBuilder();
sbr.Append("詞語");
sbr.Append(",");
sbr.Append("權重");
sbr.AppendLine(",");
foreach (var item in wordWeight)
{
sbr.Append(item.Word);
sbr.Append(",");
sbr.Append(item.Weight);
sbr.AppendLine(",");
}
string filename = "關鍵詞權重統計.csv";
File.WriteAllText(filename, sbr.ToString(), Encoding.UTF8);
Console.WriteLine("關鍵詞提取完成:" + filename);
return wordWeight.ToArray();
}

使用JiebaNet.Segmenter.Common下的Counter類統計詞頻,其實現來自Python標準庫的Counter類(具體介面和實現細節略有不同),程式碼如下:

/// <summary>
/// 分詞並統計詞頻:預設為精確模式,同時也使用HMM模型
/// </summary>
/// <param name="text"></param>
/// <param name="wordWeightAry"></param>
/// <returns></returns>
static KeyValuePair<string, int>[] Counter(string text, WordWeightPair[] wordWeightAry)
{
var segmenter = new JiebaSegmenter();
var segments = segmenter.Cut(text);
var freqs = new Counter<string>(segments);
KeyValuePair<string, int>[] countAry = new KeyValuePair<string, int>[wordWeightAry.Length];
for (int i = 0; i < wordWeightAry.Length; i++)
{
string key = wordWeightAry[i].Word;
countAry[i] = new KeyValuePair<string, int>(key, freqs[key]);
}
StringBuilder sbr = new StringBuilder();
sbr.Append("詞語");
sbr.Append(",");
sbr.Append("詞頻");
sbr.AppendLine(",");
foreach (var pair in countAry)
{
sbr.Append(pair.Key);
sbr.Append(",");
sbr.Append(pair.Value);
sbr.AppendLine(",");
}
string filename = "詞頻統計結果.csv";
File.WriteAllText(filename, sbr.ToString(), Encoding.UTF8);
Console.WriteLine("詞頻統計完成:" + filename);
return countAry;
}

使用WordCloudSharp生成詞雲圖,蒙版圖必須使用黑白圖片,記得手動引用System.Drawing,程式碼如下:

/// <summary>
/// 建立詞雲圖
/// </summary>
/// <param name="countAry"></param>
static void CreateWordCloud(KeyValuePair<string, int>[] countAry)
{
string markPath = "mask.jpg";
string resultPath = "result.jpg";
Console.WriteLine("開始生成圖片,讀取蒙版:" + markPath);
Image mask = Image.FromFile(markPath);
//使用蒙版圖片
var wordCloud = new WordCloud(mask.Width, mask.Height, mask: mask, allowVerical: true, fontname: "YouYuan");
//不使用蒙版圖片
//var wordCloud = new WordCloud(1000, 1000,false, null,-1,1,null, false);
var result = wordCloud.Draw(countAry.Select(it => it.Key).ToList(), countAry.Select(it => it.Value).ToList());
result.Save(resultPath);
Console.WriteLine("圖片生成完成,儲存圖片:" + resultPath);
}

執行測試

以本文為分析文字生成詞雲圖,程式碼如下:

static void Main(string[] args)
{
string text = File.ReadAllText("待處理資料.txt");
var wordWeight = ExtractTagsWithWeight(text);
var wordFreqs = Counter(text, wordWeight);
CreateWordCloud(wordFreqs);
Console.Read();
}

蒙版圖如下:

詞雲圖如下(使用蒙版):

詞雲圖如下(不使用蒙版):

在得到關鍵詞的詞頻資訊後,通過線上工具網站生成詞雲圖片會更加方便一點,如詞雲文字圖悅等。

參考資料