私は 1000 件以上の調査を行っており、その多くには自由回答が含まれています。
すべての単語を「解析」して、最も使用されている単語 (一般的な単語は無視) のランキングを取得して、傾向を特定できるようにしたいと考えています。
これどうやってするの?使用できるプログラムはありますか?
編集サード パーティのソリューションが利用できない場合は、Microsoft テクノロジのみに議論を続けていただければ幸いです。乾杯。
私は 1000 件以上の調査を行っており、その多くには自由回答が含まれています。
すべての単語を「解析」して、最も使用されている単語 (一般的な単語は無視) のランキングを取得して、傾向を特定できるようにしたいと考えています。
これどうやってするの?使用できるプログラムはありますか?
編集サード パーティのソリューションが利用できない場合は、Microsoft テクノロジのみに議論を続けていただければ幸いです。乾杯。
分割統治。問題を多くの小さな問題に分割し、それぞれを解決します。
最初の問題: 段落を単語のリストに変換します。
完璧であることを心配する必要がないので、あなたは幸運です。実際に自然言語を解析して「単語」が何であるかを正確に判断することは非常に難しい場合がありますが、率直に言って、「電球」が「電球」と同じセマンティクスを持っているかどうかはあまり気にしないでしょう。特に一般的な単語を探しているので (これについては後で詳しく説明します)、興味深い単語とは、よく出てくるので識別しやすい単語です。
したがって、この問題をさらに分解します。単語のリストが必要です。テキストを含む文字列を取得することから始めます。
StreamReader streamReader = new StreamReader(@"c:\survey.txt");
string source = streamReader.ReadToEnd();
よし、何とか文字列を手に入れたぞ。これを単語の配列に変換します。おそらく "Frog" と "frog" を同じ単語として数えたいので、すべて小文字にします。それをすべて行う方法は?スペース、改行、タブ、句読点に基づいて小文字の文字列を分割します。
char[] punctuation = new char[] {' ', '\n', '\r', '\t', '(', ')', '"'};
string[] tokens = source.ToLower().Split(punctuation, true);
次に、出力を調べます。それはひどかった。私たちが忘れているものはいろいろあります。ピリオド、コンマ、コロン、セミコロンなど。気になる句読点を見つけて、リストに追加します。
ToLower は正しいことですか? ToLowerInvariant はどうですか? それについて強調したい場合があります。これはそれらの1つではありません。ToLower がトルコ語の小文字 I を一貫して往復する方法で正規化するとは限らないという事実は、要約統計を台無しにする可能性は低いです。ここではピンポイントの正確さを求めるつもりはありません。誰かが「luxury-yacht」と言い、誰かが「luxury yacht」と言った場合、ハイフンの区切りを忘れれば、前者は 1 つの単語になる可能性があります。誰も気にしない?いずれにせよ、ハイフンでつながれた単語がトップ 10 に入る可能性はほとんどありません。
次の問題: 各単語の出現回数をすべて数えます:
var firstPass = new Dictionary<string, int>();
foreach(string token in tokens)
{
if (!firstPass.ContainsKey(token))
firstPass[token] = 1;
else
++firstPass[token];
}
偉大な。これで、単語を整数にマップする辞書ができました。問題は、それが逆だということです。知りたいのは、出現回数が同じすべての単語が何であるかです。辞書は一連のキーと値のペアであるため、グループ化します。
var groups = from pair in firstPass
group pair.Key by pair.Value;
OK、これで、単語のグループのシーケンスができました。それぞれが出現回数に関連付けられています。注文してください。グループのキーは辞書の値であるカウントであることを思い出してください。
var sorted = from group in groups
orderby group.Key
select group;
そして、あなたはトップ100が欲しいとしましょう:
foreach(var g in sorted.Take(100))
{
Console.WriteLine("Words with count {0}:", g.Key);
foreach(var w in g)
Console.WriteLine(w);
}
これで完了です。
さて、これは本当にあなたが興味を持っていることですか?珍しい単語や単語のペアを探す方が面白いのではないかと思います。「ヨット」と「レーシング」という言葉が一緒にたくさん出てきても、驚くことではありません。「トマト」と「ケチャップ」が一緒にたくさん出てきてもおかしくありません。「tomato」と「racing」が一緒に登場し始めたら、何か注目すべきことが起こっているのかもしれません。
それには、より深い分析が必要です。ベイズの定理に興味がある場合は、ベイズの定理を読んでください。
また、これは単語の頻度(1,000 単語あたりの出現回数) ではなく、単語の生の数を追跡することに注意してください。これは、この単語がピリオドで何回出現したかだけでなく、テキストのパーセンテージとして何回出現したかを測定する興味深い指標になるかもしれません。
NLTKには、自然言語を扱うのに役立つものがたくさん含まれています。
この記事(NLTK サイトからリンク) を参照して、永続的でネットワークにアクセス可能な頻度分布を構築する例を確認してください。探しているものと正確に一致しない場合でも、問題へのアプローチ方法の感触をつかむのに役立つ場合があります。
更新:
Re: MS テクノロジでは、IronPython を使用して .NET で NLTK を実行できます。この関連する SO の質問を参照してください。
SharpNLPは、NLP を行うためのネイティブ .NET ライブラリです。グーグルで調べるまで聞いたことがなかったので、NLTK と比較してどうなのかはわかりません。
一般的な単語をスキップするカスタム ストップ ワード リストを使用して、テキストの lucene インデックスを作成できます。Luke で lucene インデックスを開くと、インデックスの上位の用語が表示されます。
単語が語根形にグループ化されるように、索引付け中にステミングを有効にすることができます。これは、同じ単語の異なる形式 (複数形、異なる時制など) をまとめるのに役立ちます。つまり、「質問、質問、質問済み」などは「質問」として表示されます。これは他の方法ではできません。