15
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

少量のテキストデータとSVMを使って、自然文章の分類器を作ったゾ!

Posted at

#はじめに
勝手なイメージですが、自然言語処理の機械学習と言えば、世間的にはLSTMやトピックモデルなどが挙げられると思います。LSTMやトピックモデルは自然文章のデータが大量にあることで、効果を得られるものです。しかし、ビジネス領域において自然文章のデータを大量に集めることは大変難しいです。
それならば、少量のデータで機械学習できれば、幸せになれる人がいるんじゃないかと考えました。
なので、今回は、少量データで機械学習をして、学習できるのか見たいと思います。

今回のやること

以下の技術を用いて、分類器を作ります。

#今回の流れ

① 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]))

実行結果は以下。
image.png

ネガポジ分析、言葉ネットワークが機械学習に分類されるのは、よくないっすね・・・。

考察

ネガポジ分析、言葉ネットワークは、個人的には、自然言語処理に分類してほしかったんですが、機械学習に分類されちゃいました。。。
今回は、tfidfベクトルを使ったため、学習に用いた単語以外の単語を入力されると、分類が難しいんだと思います。なので、これを解消するためには、word2vecなどの分散表現を使うことで、より色んな単語に対応させ精度が高まるかと思います。
次回は、word2vecを使った分類器を作って、精度比較をしてみますね!!

#参考にさせて頂いた記事です。

15
16
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
15
16

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?