Main Content

日本語のテキスト データの解析

この例では、トピック モデルを使用して、日本語のテキスト データをインポート、準備、および解析する方法を示します。

日本語のテキスト データは大きくなる可能性があり、統計解析に悪影響を与えるノイズが多く含まれる可能性があります。たとえば、テキスト データに次のような内容が含まれることがあります。

  • 語形のバリエーション。たとえば、"難しい" ("is difficult") と "難しかった" ("was difficult")

  • ノイズを付加する単語。たとえば、"あそこ" ("over there")、"あたり" ("around")、"あちら" ("there") などのストップ ワード

  • 句読点と特殊文字

次のワード クラウドは、一連の工場レポートの生テキスト データの一部に適用された単語頻度解析と、同じテキスト データの前処理済みバージョンに適用された単語頻度解析を示しています。

この例では、最初に日本語のテキスト データをインポートして準備する方法を示し、次に、潜在的ディリクレ配分 (LDA) モデルを使用してテキスト データを解析する方法を示します。LDA モデルは、文書のコレクションに内在するトピックを発見し、トピック内の単語の確率を推測するトピック モデルです。

データのインポート

サンプル データ "factoryReportsJP.csv" を読み込みます。データには、各イベントの日本語での説明テキストとカテゴリカル ラベルを含む工場レポートが格納されています。関数 readtable を使用して table を読み取り、テキストを string として抽出します。ReadVariableNames オプションを false に設定して、名前 "Var1""Var2"、...、"Var5" を table の各変数に割り当てます。

filename = "factoryReportsJP.csv";
data = readtable(filename,"TextType","string","ReadVariableNames",false);

table の最初の数行を表示します。table には、次の変数が含まれています。

  • Var1 — 説明

  • Var2 — カテゴリ

  • Var3 — 緊急性

  • Var4 — 解決策

  • Var5 — コスト

変数 Var1 からテキスト データを抽出し、最初のいくつかのレポートを表示します。

textData = data.Var1;
textData(1:10)
ans = 10×1 string
    "スキャナーのスプールにアイテムが詰まることがある。"
    "アセンブラのピストンからガタガタと大きな音がします。"
    "工場起動時に電源が切れる。"
    "アセンブラのコンデンサが飛ぶ。"
    "ミキサーでヒューズが切れる。"
    "コンストラクション・エージェントのパイプが破裂して冷却水を噴射している。"
    "ミキサーでヒューズが飛んだ。"
    "ベルトから物が続々と落ちてきます。"
    "ベルトから物が落下する。"
    "スキャナーのリールが割れている、すぐにカーブし始める。"

テキスト データをワード クラウドで可視化します。

figure
wordcloud(textData);

文書のトークン化

tokenizedDocument を使用してテキストをトークン化し、最初のいくつかの文書を表示します。

documents = tokenizedDocument(textData);
documents(1:10)
ans = 
  10×1 tokenizedDocument:

    11 tokens: スキャナー の スプール に アイテム が 詰まる こと が ある 。
    12 tokens: アセンブラ の ピストン から ガタガタ と 大きな 音 が し ます 。
     8 tokens: 工場 起動 時 に 電源 が 切れる 。
     6 tokens: アセンブラ の コンデンサ が 飛ぶ 。
     6 tokens: ミキサー で ヒューズ が 切れる 。
    17 tokens: コンストラクション ・ エージェント の パイプ が 破裂 し て 冷却 水 を 噴射 し て いる 。
     7 tokens: ミキサー で ヒューズ が 飛ん だ 。
    11 tokens: ベルト から 物 が 続々 と 落ち て き ます 。
     7 tokens: ベルト から 物 が 落下 する 。
    14 tokens: スキャナー の リール が 割れ て いる 、 すぐ に カーブ し 始める 。

品詞タグの取得

トークンの詳細を取得し、最初のいくつかのトークンの詳細を表示します。

tdetails = tokenDetails(documents);
head(tdetails)
       Token       DocumentNumber    LineNumber     Type      Language    PartOfSpeech       Lemma         Entity  
    ___________    ______________    __________    _______    ________    ____________    ___________    __________

    "スキャナー"          1               1         letters       ja        noun           "スキャナー"     non-entity
    "の"                 1               1         letters       ja        adposition     "の"           non-entity
    "スプール"            1               1         letters       ja        noun           "スプール"       non-entity
    "に"                 1               1         letters       ja        adposition     "に"           non-entity
    "アイテム"            1               1         letters       ja        noun           "アイテム"       non-entity
    "が"                 1               1         letters       ja        adposition     "が"           non-entity
    "詰まる"              1               1         letters       ja        verb           "詰まる"        non-entity
    "こと"               1               1         letters       ja        noun           "こと"          non-entity

table の変数 PartOfSpeech には、トークンの品詞タグが格納されています。すべての名詞と形容詞のワード クラウドをそれぞれ作成します。

figure
idx = tdetails.PartOfSpeech == "noun";
tokens = tdetails.Token(idx);
subplot(1,2,1)
wordcloud(tokens);
title("Nouns")

idx = tdetails.PartOfSpeech == "adjective";
tokens = tdetails.Token(idx);
subplot(1,2,2)
wc = wordcloud(tokens);
title("Adjectives")

解析用のテキスト データの準備

ストップ ワードを削除します。

documents = removeStopWords(documents);
documents(1:10)
ans = 
  10×1 tokenizedDocument:

    5 tokens: スキャナー スプール アイテム 詰まる 。
    6 tokens: アセンブラ ピストン ガタガタ 大きな 音 。
    5 tokens: 工場 起動 電源 切れる 。
    4 tokens: アセンブラ コンデンサ 飛ぶ 。
    4 tokens: ミキサー ヒューズ 切れる 。
    8 tokens: コンストラクション ・ エージェント パイプ 破裂 冷却 噴射 。
    4 tokens: ミキサー ヒューズ 飛ん 。
    6 tokens: ベルト 物 続々 落ち き 。
    4 tokens: ベルト 物 落下 。
    8 tokens: スキャナー リール 割れ 、 すぐ カーブ 始める 。

句読点を消去します。

documents = erasePunctuation(documents);
documents(1:10)
ans = 
  10×1 tokenizedDocument:

    4 tokens: スキャナー スプール アイテム 詰まる
    5 tokens: アセンブラ ピストン ガタガタ 大きな 音
    4 tokens: 工場 起動 電源 切れる
    3 tokens: アセンブラ コンデンサ 飛ぶ
    3 tokens: ミキサー ヒューズ 切れる
    6 tokens: コンストラクション エージェント パイプ 破裂 冷却 噴射
    3 tokens: ミキサー ヒューズ 飛ん
    5 tokens: ベルト 物 続々 落ち き
    3 tokens: ベルト 物 落下
    6 tokens: スキャナー リール 割れ すぐ カーブ 始める

normalizeWords を使用してテキストをレンマ化します。

documents = normalizeWords(documents);
documents(1:10)
ans = 
  10×1 tokenizedDocument:

    4 tokens: スキャナー スプール アイテム 詰まる
    5 tokens: アセンブラ ピストン ガタガタ 大きな 音
    4 tokens: 工場 起動 電源 切れる
    3 tokens: アセンブラ コンデンサ 飛ぶ
    3 tokens: ミキサー ヒューズ 切れる
    6 tokens: コンストラクション エージェント パイプ 破裂 冷却 噴射
    3 tokens: ミキサー ヒューズ 飛ぶ
    5 tokens: ベルト 物 続々 落ちる くる
    3 tokens: ベルト 物 落下
    6 tokens: スキャナー リール 割れる すぐ カーブ 始める

ストップ ワードの削除や句読点の消去など、前処理ステップによっては、空の文書が返されることがあります。関数 removeEmptyDocuments を使用して空の文書を削除します。

documents = removeEmptyDocuments(documents);

前処理関数の作成

前処理を実行する関数を作成すると、さまざまなテキスト データのコレクションを同じ方法で準備するのに役立ちます。たとえば、1 つの関数を使用して、学習データと同じ手順で新しいデータを前処理することができます。

解析に使用するテキスト データをトークン化して前処理する関数を作成します。関数 preprocessText は、以下の手順を実行します。

  1. tokenizedDocument を使用してテキストをトークン化します。

  2. erasePunctuation を使用して句読点を消去します。

  3. removeStopWords を使用して、ストップ ワード ("あそこ"、"あたり"、"あちら" など) のリストを削除します。

  4. normalizeWords を使用して単語をレンマ化します。

関数 removeEmptyDocuments を使用して前処理を行った後、空の文書を削除します。タイムスタンプやラベルなどの独立した配列に格納されたデータを関連付けた場合は、これに対応する要素も削除します。削除する要素のインデックスを取得するには、削除されたドキュメントのインデックスも返します。

この例では、例の最後にリストされている前処理関数 preprocessText を使用して、テキスト データを準備します。

documents = preprocessText(textData);
documents(1:5)
ans = 
  5×1 tokenizedDocument:

    4 tokens: スキャナー スプール アイテム 詰まる
    5 tokens: アセンブラ ピストン ガタガタ 大きな 音
    4 tokens: 工場 起動 電源 切れる
    3 tokens: アセンブラ コンデンサ 飛ぶ
    3 tokens: ミキサー ヒューズ 切れる

空の文書を削除します。

documents = removeEmptyDocuments(documents);

トピック モデルを当てはめる

潜在的ディリクレ配分 (LDA) トピック モデルをデータに当てはめます。LDA モデルは、文書のコレクションに内在するトピックを発見し、トピック内の単語の確率を推測します。

LDA モデルをデータに当てはめるには、まず bag-of-words モデルを作成しなければなりません。bag-of-words モデル (用語頻度カウンターとも呼ばれる) は、コレクションの各文書内で単語が出現する回数を記録します。bagOfWords を使用して bag-of-words モデルを作成します。

bag = bagOfWords(documents);

bag-of-words モデルから空の文書を削除します。

bag = removeEmptyDocuments(bag);

fitlda を使用して、トピック数 7 の LDA モデルを当てはめます。詳細出力を抑制するには、'Verbose'0 に設定します。

numTopics = 7;
mdl = fitlda(bag,numTopics,"Verbose",0);

ワード クラウドを使用して、最初の 4 つのトピックを可視化します。

figure
for i = 1:4
    subplot(2,2,i)
    wordcloud(mdl,i);
    title("Topic " + i)
end

積み上げ棒グラフを使用して、複数のトピックの混合率を可視化します。ランダムに 5 つの入力文書を表示し、対応するトピックの混合率を可視化します。

numDocuments = numel(documents);
idx = randperm(numDocuments,5);
documents(idx)
ans = 
  5×1 tokenizedDocument:

    4 tokens: ミキサー 大きな 音 出る
    5 tokens: スキャナー 熱 発す 動く ない
    3 tokens: ミキサー 冷却 漏れる
    4 tokens: ソーター 制御 電源 故障
    2 tokens: ミキサー 煙る

topicMixtures = transform(mdl,documents(idx));
figure
barh(topicMixtures(1:5,:),"stacked")
xlim([0 1])
title("Topic Mixtures")
xlabel("Topic Probability")
ylabel("Document")
legend("Topic " + string(1:numTopics),"Location","northeastoutside")

例の前処理関数

関数 preprocessText は、以下の手順を実行します。

  1. tokenizedDocument を使用してテキストをトークン化します。

  2. erasePunctuation を使用して句読点を消去します。

  3. removeStopWords を使用して、ストップ ワード ("あそこ"、"あたり"、"あちら" など) のリストを削除します。

  4. normalizeWords を使用して単語をレンマ化します。

function documents = preprocessText(textData)

% Tokenize the text.
documents = tokenizedDocument(textData);

% Erase the punctuation.
documents = erasePunctuation(documents);

% Remove a list of stop words.
documents = removeStopWords(documents);

% Lemmatize the words.
documents = normalizeWords(documents,"Style","lemma");
end

参考

| | | | |

関連するトピック