#はじめに
勝手なイメージですが、自然言語処理の機械学習と言えば、世間的にはLSTMやトピックモデルなどが挙げられると思います。LSTMやトピックモデルは自然文章のデータが大量にあることで、効果を得られるものです。しかし、ビジネス領域において自然文章のデータを大量に集めることは大変難しいです。
それならば、少量のデータで機械学習できれば、幸せになれる人がいるんじゃないかと考えました。
なので、今回は、少量データで機械学習をして、学習できるのか見たいと思います。
今回のやること
以下の技術を用いて、分類器を作ります。
-
tfidf
こちらを参考に勉強させて頂きました。
http://ailaby.com/tfidf/ -
svm(サポートベクターマシン)
こちらを参考に勉強させて頂きました。
https://qiita.com/kazuki_hayakawa/items/18b7017da9a6f73eba77
#今回の流れ
① twitterからテキストデータの取得
「機械学習」、「自然言語処理」、「データサイエンティスト」の文字列を含むツイートを100件ずつ取得する。
#####② テキストデータへのラベル付け
以下のようなルールでラベル付け。(テキストデータ => ラベル)
- 「機械学習」で検索したテキストデータ => 機械学習
- 「自然言語処理」で検索したテキストデータ => 自然言語処理
- 「データサイエンティスト」で検索したテキストデータ => データサイエンティスト
#####③ tfidfモデル、tfidfベクトルを作成
取得したデータから名詞、形容詞の単語を抽出し、単語リストを生成。
単語リストからtfidfモデル、tfidfベクトルを作成。
#####④ tfidfベクトルとsvmを用いて、分類器を作成
tfidfベクトルとラベルを基にsvmで学習。
ソースコード
#####① twitterからテキストデータの取得
データ取得は、以下の記事を参考にしてみてください。
https://qiita.com/teri/items/e10a3be38113b31c0c9a
#####② テキストデータへのラベル付け
ラベル付けは、以下の記事を参考にしてみてください。
https://qiita.com/kazuki_hayakawa/items/18b7017da9a6f73eba77
#####③ tfidfモデルを作成
名詞、形容詞の単語のみを取得
def wakati_word_list_create(sentences:list, get_word_class:list) -> list:
#複数文から、指定の品詞(GET_WORD_CLASS)を抽出した単語リスト
sentences_word_list = []
for sentence in sentences:
#一文から、指定の品詞(GET_WORD_CLASS)を抽出した単語リスト
one_sentence_word_str = ''
#形態素解析
node = mecab.parseToNode(sentence)
while node:
#語幹
word = node.feature.split(",")[-3]
#品詞
word_class = node.feature.split(",")[0]
#(指定の品詞(GET_WORD_CLASS)である) and (語幹が*のもの(つまり未知語))場合は、単語リストに追加
if word_class in get_word_class and word != '*':
one_sentence_word_str = one_sentence_word_str + " " + word
node = node.next
sentences_word_list.append(one_sentence_word_str)
return sentences_word_list
#twitterデータから、指定品詞の分かち分割形式の単語リストを生成
wakati_word_list = nlp_util.wakati_word_list_create(search_tweet_list, GET_WORD_CLASS)
tfidfモデル、tfidfベクトルを作成
#tfidfベクトル化
from sklearn.feature_extraction.text import TfidfVectorizer
tfidf = TfidfVectorizer(use_idf=True, token_pattern=u'(?u)\\b\\w+\\b')
#tfidfモデルの作成
tfidf_model = tfidf.fit(wakati_word_list)
#tfidfベクトルに変換
vectors = tfidf_model.transform(wakati_word_list).toarray()
#####④ tfidfベクトルとsvmを用いて、分類器を作成
準備したデータを学習データ、テストデータに振り分ける。
今回は学習データを7割、テストデータを3割に振り分ける。
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
input_train, input_test, output_train, output_test = train_test_split(vectors, targets, test_size=0.3, random_state=None )
sc = StandardScaler()
sc.fit(input_train)
input_train_std = sc.transform(input_train)
input_test_std = sc.transform(input_test)
tfidfベクトルとsvmで学習。
from sklearn.svm import SVC
# 学習インスタンス生成
svc_model = SVC(kernel='linear', random_state=None)
# 学習
svc_model.fit(input_train_std, output_train)
学習データで精度確認
from sklearn.metrics import accuracy_score
#traning dataのaccuracy
pred_train = svc_model.predict(input_train_std)
accuracy_train = accuracy_score(output_train, pred_train)
print('traning data accuracy: %.2f' % accuracy_train)
実行結果は以下。
traning data accuracy: 1.00
テストデータで精度確認
#test dataのaccuracy
pred_test = svc_model.predict(input_test_std)
accuracy_test = accuracy_score(output_test, pred_test)
print('test data accuracy: %.2f' % accuracy_test)
実行結果は以下。
test data accuracy: 0.93
#少し遊んでみました。
適当な文章を入力して、ちゃんと分類されるか試してみました。
input_textsに格納されている文章が、「自然言語処理」、「機械学習」、「データサイエンティスト」のいずれかに分類されます。
#正解ラベル{1:機械学習、2:データサイエンティスト, 3:自然言語処理}
input_texts = [
"自然言語処理の技術発展スピードはすごいな~",
"データサイエンティストってどんな職種なんやろかー",
"機械学習用のデータを集めるのって大変やなー",
"自然言語処理系のデータサイエンティストって楽しそう!!",
"ネガポジ分析について",
"言葉ネットワークとは?",
]
wakati_input_texts = nlp_util.wakati_word_list_create(input_texts, GET_WORD_CLASS)
tfidf_vectors = tfidf_model.transform(wakati_input_texts).toarray()
predict = svc_model.predict(tfidf_vectors)
print("{: <30} : {: <20}".format("予測する文章", "予測結果"))
print("====================================================================================")
for pre, text in zip(predict, input_texts):
print("{: <30} : {: <20}".format(text, LABEL_MAP[pre]))
ネガポジ分析、言葉ネットワークが機械学習に分類されるのは、よくないっすね・・・。
考察
ネガポジ分析、言葉ネットワークは、個人的には、自然言語処理に分類してほしかったんですが、機械学習に分類されちゃいました。。。
今回は、tfidfベクトルを使ったため、学習に用いた単語以外の単語を入力されると、分類が難しいんだと思います。なので、これを解消するためには、word2vecなどの分散表現を使うことで、より色んな単語に対応させ精度が高まるかと思います。
次回は、word2vecを使った分類器を作って、精度比較をしてみますね!!
#参考にさせて頂いた記事です。