こんにちは!
テービーテックの村松です。
「言語処理100本ノック2020]」
nlp100.github.io
に挑戦中!
途中でくじけないか見守ってください・・・。
そして、皆さんも一緒に挑戦してみましょう!
本日は第 5章:機械学習 50~54です!
間違い・コード改善点などありましたら教えていただけると嬉しいです。
第5章:機械学習
「Fabio Gasparetti氏が公開しているNews Aggregator Data Setを用い,ニュース記事の見出しを「ビジネス」「科学技術」「エンターテイメント」「健康」のカテゴリに分類するタスク(カテゴリ分類)に取り組む.」
ここからは
UCI Machine Learning Repository: News Aggregator Data Set
を使用して問題に取り組んでいきます。
50. データの入手・整形
「データを学習データ(train.txt)、検証データ(valid.txt)、評価データ(test.txt)に分割します。
条件は、
1.ダウンロードしたzipファイルを解凍し,readme.txtの説明を読む.
2.情報源(publisher)が”Reuters”, “Huffington Post”, “Businessweek”, “Contactmusic.com”, “Daily Mail”の事例(記事)のみを抽出する.
3.抽出された事例をランダムに並び替える.
4.抽出された事例の80%を学習データ,残りの10%ずつを検証データと評価データに分割し,それぞれtrain.txt,valid.txt,test.txtというファイル名で保存する.ファイルには,1行に1事例を書き出すこととし,カテゴリ名と記事見出しのタブ区切り形式とせよ(このファイルは後に問題70で再利用する).」
import pandas as pd import zipfile from sklearn.model_selection import train_test_split
#zipファイルの中身の確認 with zipfile.ZipFile('NewsAggregatorDataset.zip') as zf: print(zf.namelist())
##出力 ['2pageSessions.csv', '__MACOSX/', '__MACOSX/._2pageSessions.csv', 'newsCorpora.csv', '__MACOSX/._newsCorpora.csv', 'readme.txt', '__MACOSX/._readme.txt']
今回使用するのはnewsCorpora.csvです。
#newsCorpora.csvを展開 with zipfile.ZipFile('NewsAggregatorDataset.zip') as zf: zf.extract('newsCorpora.csv', '保存先')[f:id:TBT_matsu:20200828105543p:plain] #newsCorpora.csvの読み込み(タブ区切り・ヘッダーはなし) newsCorpora = pd.read_csv('参照先/newsCorpora.csv', sep='\t', header=None) #カラム名の指定 newsCorpora.columns = ['ID','TITLE','URL','PUBLISHER','CATEGORY','STORY','HOSTNAME','TIMESTAMP'] newsCorpora.head(5)
今回分析に使用するデータは、
TITLE:ニュースの見出し
CATEGORY:ニュースカテゴリ(b = business, t = science and technology, e = entertainment, m = health)
の2つです。
問題の条件に合わせてこの2つを切り出していきます。
#条件2つ目:指定の情報源で絞り込み df = newsCorpora[newsCorpora['PUBLISHER'].isin(['Reuters', 'Huffington Post', 'Businessweek', 'Contactmusic.com', 'Daily Mail'])] #条件3つ目:ランダムに並べ替え df = df.sample(frac=1) #条件4つ目:データの切り分け train, val_test = train_test_split(df, test_size=0.2) val, test = train_test_split(val_test, test_size=0.5) #保存 train.to_csv('保存先/train.txt', columns = ['CATEGORY','TITLE'], sep='\t',header=False, index=False) val.to_csv('保存先/valid.txt', columns = ['CATEGORY','TITLE'], sep='\t',header=False, index=False) test.to_csv('保存先/test.txt', columns = ['CATEGORY','TITLE'], sep='\t',header=False, index=False)
51.特徴量抽出
「学習データ,検証データ,評価データから特徴量を抽出し,それぞれtrain.feature.txt,valid.feature.txt,test.feature.txtというファイル名で保存せよ. なお,カテゴリ分類に有用そうな特徴量は各自で自由に設計せよ.」
#データの読み込み train_df = pd.read_csv('保存先/train.txt', sep='\t', header=None) val_df = pd.read_csv('保存先/valid.txt', sep='\t', header=None) test_df = pd.read_csv('保存先/test.txt', sep='\t', header=None) #前処理を一括で行うためのデータの統合 df = pd.concat([train_df, val_df, test_df], axis=0) #インデックスのふり直し(旧インデックスは無し(drop=True)、元のdfを変更する(inplace=True)) df.reset_index(drop=True, inplace=True)
#前処理の関数 def preprocessing(text): #記号(string.punctuation)をスペース(記号があった数分)に置換 table = str.maketrans(string.punctuation, ' '*len(string.punctuation)) text = text.translate(table) #数字を全て0に置換 text = re.sub(r'[0-9]+', "0", text) return text #前処理の実行 df[1] = df[1].map(lambda x: preprocessing(x))
#再度分割(train_valとtest) train_val = df[:len(train_df)+len(val_df)] test = df[len(train_df)+len(val_df):] #CountVectorizerクラスを利用したBoW形式の特徴抽出(train_valのみ) from sklearn.feature_extraction.text import CountVectorizer cv = CountVectorizer() train_val_cv = cv.fit_transform(train_val[1]) test_cv = cv.transform(test[1]) #データフレームに変換 train_val_ = pd.DataFrame(train_val_cv.toarray(), columns=cv.get_feature_names()) x_test = pd.DataFrame(test_cv.toarray(), columns=cv.get_feature_names())
#再度データを分割 x_train = train_val_[:len(train_df)] x_val = train_val_[len(train_df):] #保存 x_train.to_csv('保存先/train.feature.txt', sep='\t', index=False) x_val.to_csv('保存先/valid.feature.txt', sep='\t', index=False) x_test.to_csv('保存先/test.feature.txt', sep='\t', index=False)
52.学習
「51で構築した学習データを用いて,ロジスティック回帰モデルを学習せよ.」
#ロジスティック回帰による学習 from sklearn.linear_model import LogisticRegression model = LogisticRegression(max_iter=200, random_state=0) model.fit(x_train, y_train)
##出力 LogisticRegression(C=1.0, class_weight=None, dual=False, fit_intercept=True, intercept_scaling=1, l1_ratio=None, max_iter=200, multi_class='auto', n_jobs=None, penalty='l2', random_state=0, solver='lbfgs', tol=0.0001, verbose=0, warm_start=False)
53.予測
「52で学習したロジスティック回帰モデルを用い,与えられた記事見出しからカテゴリとその予測確率を計算するプログラムを実装せよ.」
#予測用の関数 def predict(model, data): return [np.max(model.predict_proba(data), axis=1), model.predict(data)] #関数の実行 train_predict = predict(model, x_train) test_predict = predict(model, x_test) print(train_predict) print(test_predict)
##出力 [array([0.87862756, 0.73442697, 0.98206866, ..., 0.88216148, 0.99258838, 0.90984908]), array(['b', 't', 'b', ..., 'm', 'b', 'm'], dtype=object)] [array([0.93636647, 0.98394973, 0.97860894, ..., 0.98522563, 0.97051698, 0.9177105 ]), array(['t', 'e', 'b', ..., 'b', 'e', 'b'], dtype=object)]
54. 正解率の計測
「52で学習したロジスティック回帰モデルの正解率を,学習データおよび評価データ上で計測せよ.」
from sklearn.metrics import accuracy_score train_accuracy = accuracy_score(y_train, train_predict[1]) test_accuracy = accuracy_score(y_test, test_predict[1]) print(f'正解率(学習データ):{train_accuracy:.3f}') print(f'正解率(評価データ):{test_accuracy:.3f}')
##出力 正解率(学習データ):0.995 正解率(評価データ):0.924
ここまでご覧いただきありがとうございます。
以上、第5章50~54でした!