Sansan Tech Blog

Sansanのものづくりを支えるメンバーの技術やデザイン、プロダクトマネジメントの情報を発信

【Techの道も一歩から】第12回「基礎的な考え方であるTF-IDFを学ぶ」

f:id:kanjirz50:20180830101137j:plain
Techの道も一歩から

こんにちは。 DSOC R&D グループの高橋寛治です。

前回のブログの終わりに書きましたが、今回からは言語処理のアルゴリズムの紹介を行います。 ただ単にアルゴリズムを紹介するだけではなく、実際に実装し動作させた結果も掲載することで直感的な感覚も掴めるものにしたいと思います。

まずは、単純かつよく利用されるTF-IDFから始めていきます。

TF-IDFの基本的な考え方

TF(Term Frequency)-IDF(Inverse Document Frequency)とは、文書中の単語の重要度を頻度を用いて数値化するための手法です。 たとえば次の文書を読んでみましょう。

文書1

自然な会話を行うアルゴリズムを作りました。本アルゴリズムは、最近のディープラーニングで流行している系列変換モデルを用いています。

文書2

豊かな自然の中で会話を楽しめる、そんな場所を作りました。

さて、どの単語が重要に感じましたか?

文書1の「アルゴリズム」が重要に感じませんでしたか。 「アルゴリズム」は文書1で2回出現していますが、文書2では出現しません。 なんとなく頻出する語が重要に感じます。 頻度で見ると、「自然」という単語は、文書1でも文書2でも使われています。 しかしながら、両方の文書に出現するためあまり重要ではなさそうです。

こういった直感をモデル化しているのがTF-IDFです。

数式を確認する

TF-IDFの計算は次の数式で表します。

$$ TF IDF = TF \cdot IDF $$

TFは、文書中で単語がどれくらい出現したかを表します。 IDFは、逆文書頻度とよばれ、より多くの文書に出現する単語ほど数値が低くなる尺度です。

文書は単語で表現されるため、ここで数えている頻度は単語となります。

$$ TF = \frac{ある文書dにおける単語t_iの頻度}{ある文書dにおけるすべての単語tの頻度の総和} $$

\( t_i \) はある文書に含まれるある一つの単語を表します。 文書1では「アルゴリズム」が2回出現しました。 総頻度は簡単にするために名詞だけを数え上げて、「自然」「会話」「アルゴリズム」「本」「アルゴリズム」「最近」「ディープラーニング」「流行」「系列変換モデル」の9とします。 そうしたときに、TFは \( 2/9 \fallingdotseq 0.22 \) となります。

$$ IDF = \log{\frac{文書数}{ある単語を含む文書数}} $$

逆文書頻度は、「アルゴリズム」は2文書中で1度出現したため、 \( \log (2/1) \fallingdotseq 0.30 \) となります。

TF-IDFはそれをかけ合わせたものであるため、文書1中での「アルゴリズム」の重要度は次のようになります。

$$ TF IDF = TF \cdot IDF = 0.22 \cdot 0.30 \fallingdotseq 0.07 $$

このようにある文書中での単語の重要度を求めることができました。

英語版WikipediaのTFIDFの記事が非常に充実しているので、詳しく知りたい方はおすすめです。 文書の種類によっては、たとえばTFは単語が出現したかどうかの0, 1の2値で算出したほうがいい場合や、対数をとって正規化するものがあります。 IDFも同様に、スムージングのために1加算したり対数をとったりいろいろな亜種があります。

TF-IDFの使いみちを考える上で、重要な単語はある文書で頻出するが全体ではあまり使われないことをモデル化しているということを抑えておくことが大事です。

実際の文書に適用する

実際の文書に適用してみましょう。 scikit-learnのTfidfVectorizerを用います。

まず文書集合を用意します。 私の個人ブログの記事から9件文書を用意しました。 https://github.com/kanjirz50/tech-blog-scriptからクローンすると、tfidf/docs 以下にテキストを置いています。 ファイル名は yyyymmdd.txt です。

20171119.txt の文頭は次のようになっています。 head コマンドなどでご確認ください。

ICDAR2017に参加した

最近 会社の技術ブログにうつつを抜かし 、個人ブログに投稿できていなかったので、久しぶりの投稿となります。 (個人ブログ、少しはがんばろう)

会社スポンサーブース対応および聴講を目的に、京都で開催されたICDAR2017に参加しました。

形態素解析には janome を用います。 Pure pythonで書かれており、Analyzerが充実してるツールです。

次にコードを示します。 レポジトリにはノートブックもありますので、そちらを実行されてもよいかと思います。

# 必要なモジュールのインポート
import glob

import numpy as np

from janome.analyzer import Analyzer
from janome.tokenizer import Tokenizer
from janome.tokenfilter import POSKeepFilter, CompoundNounFilter

from sklearn.feature_extraction.text import TfidfVectorizer

# janomeアナライザーの定義(複合名詞処理+名詞抽出処理)
a = Analyzer(token_filters=[CompoundNounFilter(), POSKeepFilter("名詞")])

# ファイルを読み込み、アナライザーで解析し、文書集合を作る
docs = []
for f in glob.glob("./docs/*.txt"):
    with open(f, "r", encoding="utf-8") as fin:
        doc = []
        for line in fin:
            line = line.strip()
            if not line:
                continue
            doc.append(" ".join([tok.surface for tok in a.analyze(line)]))
        docs.append(" ".join(doc))

# TFIDF変換器により変換する
vectorizervectori  = TfidfVectorizer()
vector = vectorizer.fit_transform(docs)

以上でTFIDF値が格納された行列が作られました。 実際に重要度の高い語を表示します。

# 各文書で重要な単語上位10語を表示する
feature_names = np.array(vectorizer.get_feature_names())
for vec in vector:
    index = np.argsort(vec.toarray(), axis=1)[:,::-1]
    feature_words = feature_names[index]
    print(feature_words[:,:10])

文書1

参加 cnn 学会 チュートリアル icdar2017 発表 analysis 議論 recognition 投稿

文書2

hug api パラメータ cli コマンドラインツール 引数 デコレータ ラップ webapi world

文書3

cchardet beautifulsoup requestsモジュール 文字化け apparent_encoding 文字コード response html ページ レスポンスヘッダ

文書4

xonsh プロセス置換 コマンド よう python subprocess ファイル zsh bash mom

文書5

ergodoxez 購入 ため 手数料 開封 ergodoxezライフ 猫背解消 注文 hhkb 記載

文書6

インストール sh catboost lightgbm gpu gce ログインパスワード engine pyenv with

文書7

素性抽出 テンプレート 素性 surface 抽出 タグ 対象単語 関数 推定 よう

文書8

自然言語処理 文書分類 勉強会 実装 ハンズオン みなさま テーマ 勉強 参加 得意

文書9

企業 勉強会 自然言語処理 アルゴリズム 取り組み ため 開発 企業特定 企業辞書 曖昧さ

それぞれの元文書はどのようなものでしょうか。 複合名詞処理+名詞抽出した文書がdocsに格納されているため、それを表示します。

for doc in docs:
    print(doc[:200])
    print()

文書1

ICDAR2017 参加 最近 会社 技術ブログ うつつ 個人ブログ 投稿 久しぶり 投稿 個人ブログ 会社スポンサーブース対応 聴講 目的 京都 開催 ICDAR2017 参加 これ 言語処理系 学会 参加 画像系 ため 新鮮 参加 所感 ICDAR International Conference on Document Analysis and Recognition 略 文書 構造解析 O

文書2

hug API CLI Sansan Advent Calendar 2017 1日目 記事 Python WebAPI コマンドラインツール とき ボトルネック がち の ルーティング 引数 管理 hug ここらへん Pythonモジュール hug WebAPI コマンドラインツール 作成 備忘録 hug WebAPI きまり Hello World! パラメータ デプロイ とき コマンドライン

文書3

Python requestsモジュール 文字コード対策 編集 Webスクレイピング Advent Calendar 2017 4日目 記事 Python requestsモジュール Requests 人 よう 設計 Python Apache2 Licensed ベース HTTPライブラリ 公式サイト1文目 記述 HTTPライブラリ requestsモジュール 日本語HTML 対象 取得 際 文

文書4

Xonsh Xonsh Advent Calendar 2017 13日目 記事 Xonsh 話 これ Xonsh the xonsh shell ~ こちらトム少佐 Xonsh地上管制 ~ Xonsh Python 動作 クロスプラットフォーム Unix よう シェル言語 コマンドプロンプト 言語 Python 3.4+ 上位互換 Bash IPython 基本的 シェル命令 追加 もの Lin

文書5

ErgoDoxEZ 購入 編集 HHKB Pro 2 type-S 日本語配列 左右分離型キーボード ErgoDoxEZ 移行 目的 猫背 解消 軽減 よう きっかけ 購入 紹介 猫背解消 きっかけ 徹底的 猫背解消 ため 現在猫背対策 スタンディングデスク ディスプレイ さ 気 ラットプルダウン デッドリフト 始め 筋トレ 中 HHKB 長所 スリム キーボード 体格 こと キー入力 肩 前 左

文書6

Google Compute Engine Python GPU環境 構築 機械学習環境 Google Compute Engine(GCE) GPUインスタンス上 Python 構築 GPU対応版 LightGBM Catboost インストール 記事 備忘録 導入プラン マシンタイプ n1-highmem-8 (vCPUx8 メモリ52GB) Ubuntu 18.04 GPU 1 x NVID

文書7

系列ラベリング 素性抽出 系列ラベリング問題 際 素性抽出 複雑 がち テンプレート サクッ 抽出 よう整理 素性 抽出 固有表現抽出 例 以下 表 午前8時 東京駅 集合 文 形態素解析 IOB2(Inside-outside-beggining)タグ形式 固有表現 ラベル 付与 もの 午前8時 TIME属性 東京駅 LOCATION属性 こと ここ 東京 単語 例 素性抽出 素性 対象単語 前

文書8

サポーターズ勉強会 文書分類 ハンズオン 7月31日 文書分類 自然言語処理 タイトル 講師 よう 機会 記事 題目 理由 講演 文書分類 自然言語処理 テーマ の 勉強会 講師 上 自分 こと 題目 何 専門 自然言語処理 実装 得意 ため テーマ 1度 勉強会 時間的制約 中 タスク 観点 文書分類 自然言語処理 魅力的 トピック たくさん 説明 実装 大変 新聞 雑誌 カテゴリ分け 文書分類

文書9

会社 勉強会 7月18日 自社開催 勉強会 登壇 記事 の 気 1ヶ月 ( はず ) 勉強会 こと 感想 自然言語処理(NLP)領域 話 壮大 テーマ もと 1回目 R&D 外部向け勉強会 開催 多大 サポート 人事部 みなさま 感謝 勉強会 何 正直 発表自体 特別 アルゴリズム 高度 手法 わけ 割 地味 こと サービス 稼働 こと 開発 運用 話 テーマ Eightニュースフィード活性化 た

いかがでしょうか。 直感にあった重要そうな単語が上位に出ているように見えますね。

文書5の ergodoxez や文書8の 自然言語処理 はかなり特徴を掴んでいるのではないかと思います。 単純に可視化するだけではなく、単語列と重み(スコア)を他の機械学習器の入力として利用もできます。

簡単な理論から始める

TF-IDFは親しみやすくかつ協力なアルゴリズムです。 簡単な理論から勉強すると、モチベーションも保ちやすいと思います。 (このブログの継続も然り。)

少しづつ難しいトピックに移っていければと思います。


前回まではmimiブログで連載していました。過去の記事については、そちらでご確認ください。

前回記事:【Techの道も一歩から】第11回「言語処理でのちょっとした前処理」

執筆者プロフィール

高橋寛治 Sansan株式会社 Data Strategy & Operation Center R&Dグループ研究員

阿南工業高等専門学校卒業後に、長岡技術科学大学に編入学。同大学大学院電気電子情報工学専攻修了。在学中は、自然言語処理の研究に取り組み、解析ツールの開発や機械翻訳に関連する研究を行う。大学院を卒業後、2017年にSansan株式会社に入社。現在はキーワード抽出など自然言語処理を生かした研究に取り組んでいる。

© Sansan, Inc.