ヤフーニュースのタイトルからPythonでカテゴリ予測[特徴ベクトル作成編]

ヤフーニュースのタイトルから経済とスポーツの二種類に分けるということをやってきています。

これで4記事目です。

ながーーーーい。

前回はタイトルの単語を全部小文字に統一したり、半角に統一したりとデータの前処理をやってきました。

まだその記事を見ていない方は先にそっちを読んでおいてください。

https://magarikado0.com/yahoo-news-preprocessing/

今回すること

今回はランダムフォレストで学習させるための特徴ベクトルを作っていきたいと思います。ひゃーー。

わたしはデータの前処理が一番大変じゃないかと思っているのでここからは簡単にサラーっと行けるんじゃないですかね。

いきまあす。

特徴ベクトルを作るぞ

このコードは前回と同じファイルに前の続きで書いてください。

from gensim import corpora#辞書を作るためのもの
from gensim import matutils#辞書を特徴ベクトルにするやつ
dictionary=corpora.Dictionary(texts)#textsをもとに辞書を作成します
dictionary.filter_extremes(no_below=5)#出現文書数が5回以下のものはさようなら
dictionary.save_as_text('dictionary.txt')#辞書を保存
def vec2dense(vec, num_terms):#辞書を特徴ベクトル化する関数を作る
    return list(matutils.corpus2dense([vec], num_terms=num_terms).T[0])
data=[vec2dense(dictionary.doc2bow(texts[i]),len(dictionary)) for i in range(len(texts))]#さっきの関数
print(len(data))#dataリストの大きさを調べる
print(len(data[0]))#dataリストの大きさを調べる
f=open('vector.txt', 'w')#dataリストをファイルに保存します
for x in range(len(data)):
    for y in data[x]:
        f.write(str(y) + "\n")
f.close()

はい、まず全体としてはこんな感じですね。

上から順番に解説していきます。

dictionary=corpora.Dictionary(texts)#textsをもとに辞書を作成します
dictionary.filter_extremes(no_below=5)#出現文書数が5回以下のものはさようなら
dictionary.save_as_text('dictionary.txt')#辞書を保存

辞書の作成

辞書って何?

さっきからじしょじしょじしょじしょ言ってますが辞書とはいったい何なんでしょうか?

もちろん普段私たちが使うあの分厚くて重くてヘビーな奴ではありません。

では何かといいますと、単語ID、単語、単語の出現回数のデータのことです。

例として今回のヤフーニュースのタイトルから作っ手テキストファイルに保存した辞書をお見せします。

全部は多いので一部です。

単語ID 単語 出現回数
15	世界	9
72	中傷	5
93	中止	5
21	人気	10
87	今季	5
19	今年	5
31	企業	7
32	会社	5
30	優勝	10
46	元気	5
42	入り	7
41	公開	5
29	再開	17

左から単語ID、単語、出現回数となっています。

 

ということで

dictionary=corpora.Dictionary(texts)

で辞書がdictionaryに入っています。

次の

dictionary.filter_extremes(no_below=5)

では辞書の単語の中から出現文書数が5回以下のものを消しています

no_below以外にも引数はあります

  • no_below 出現文書数が指定値以下のものを消す
  • no_above   出現文書率が指定値以上のものを消す
  • keep_n   no_below,no_aboveに関わらず指定値個は保持する
  • keep_tokens   no_below,no_aboveに関わらず指定した単語は保持する

こんな感じですね。

私の場合いろいろ試した結果no_below=5が一番精度が良かったのでこれにしています。

dictionary.save_as_text('dictionary.txt')

で作成した辞書をdictionary.txtに保存しています。

べつにこれはなくてもいいんですが辞書を目で見えるようにできたほうがいいのでしときましょう。

特徴ベクトルを作りますよ

def vec2dense(vec, num_terms):#辞書を特徴ベクトル化する関数を作る
    return list(matutils.corpus2dense([vec], num_terms=num_terms).T[0])
data=[vec2dense(dictionary.doc2bow(texts[i]),len(dictionary)) for i in range(len(texts))]#さっきの関数

ここではですねランダムフォレストに入れるために辞書から特徴ベクトルを作っています。

具体的にどのような特徴ベクトルなのかといいますと

[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]

一個目のタイトルのやつです。

これは何を表しているのかというと単語IDが1から最後まで(ここではたぶん96まで)の単語があれば「1.0」、なかったら「0.0」になっています。

ここでは21番目のところが「1.0」になっているので単語IDが「21」の「人気」という単語が含まれていたんでしょうね。

こんな感じです。こんな0ばっかりでよく83%も精度が出たものですね。

特徴ベクトルのサイズを見るよ

print(len(data))#468
print(len(data[0]))#95

わたしは468と95がでました。もちろん人によって違います。

今は必要ないですが次の記事で必要になるので一応しておいてください。

保存

f=open('vector.txt', 'w')#dataリストをファイルに保存します
for x in range(len(data)):
    for y in data[x]:
        f.write(str(y) + "\n")
f.close()

毎回おなじみのやり方かと思いましたがちょっと違いますね。

今回は2次元のリストなので二重ループを使いましょう。

ちがいはそこだけです。

特徴ベクトルができたので今回もとりあえずおわり

これでついにランダムフォレストに入れる特徴ベクトルを作ることができましたね。

次の記事ではやっと機械学習ができますのでがんばりましょー。

 

ありがとうございました