テービーテックのデータサイエンス

未経験リケジョがゼロからデータサイエンティストを目指す姿を記す奮闘記です。2019/12/05文系出身者が共同で更新を開始

TAG index

▲心くじけず言語処理100本ノック==55~59==

f:id:TBT_matsu:20200515145048p:plain
こんにちは!
テービーテックの村松です。

「言語処理100本ノック2020]」
nlp100.github.io
に挑戦中!
途中でくじけないか見守ってください・・・。
そして、皆さんも一緒に挑戦してみましょう!

本日は第 5章:機械学習 55~59です!
間違い・コード改善点などありましたら教えていただけると嬉しいです。

第5章:機械学習

「Fabio Gasparetti氏が公開しているNews Aggregator Data Setを用い,ニュース記事の見出しを「ビジネス」「科学技術」「エンターテイメント」「健康」のカテゴリに分類するタスク(カテゴリ分類)に取り組む.」
ここからは
UCI Machine Learning Repository: News Aggregator Data Set
を使用して問題に取り組んでいきます。

本日の内容の補助知識として、

混同行列・適合率・再現率・F1スコアに関しては
こちらがわかりやすいのでおススメです。

55. 混同行列の作成

「52で学習したロジスティック回帰モデルの混同行列(confusion matrix)を,学習データおよび評価データ上で作成せよ.」

from sklearn.metrics import confusion_matrix
import seaborn as sns
import matplotlib.pyplot as plt
#学習データの混同行列
train_cm = confusion_matrix(y_train, train_predict[1])
print(train_cm)
sns.heatmap(train_cm, annot=True, cmap='Blues')
plt.show()
##出力
[[4486    5    0   11]
 [   7 4227    0    2]
 [   4    4  721    0]
 [  20    5    0 1180]]

f:id:TBT_matsu:20200901104453p:plain

#評価データの混同行列
test_cm = confusion_matrix(y_test, test_predict[1])
print(test_cm)
sns.heatmap(test_cm, annot=True, cmap='Blues')
plt.show()
##出力
[[546   9   3  17]
 [  9 518   0   3]
 [ 12  12  59   2]
 [ 20  13   2 109]]

f:id:TBT_matsu:20200901104625p:plain

56.適合率・再現率・F1スコアの計測

「52で学習したロジスティック回帰モデルの適合率,再現率,F1スコアを,評価データ上で計測せよ.カテゴリごとに適合率,再現率,F1スコアを求め,カテゴリごとの性能をマイクロ平均(micro-average)とマクロ平均(macro-average)で統合せよ.」

#適合率
from sklearn.metrics import precision_score
pre = precision_score(y_test, test_predict[1], average=None, labels=['b','t','e','m'])
print (pre)
micro_average = precision_score(y_test, test_predict[1], average='micro')
macro_average = precision_score(y_test, test_predict[1], average='macro')
print('ミクロ平均:' + str(micro_average))
print('マクロ平均:' + str(macro_average))
##出力
[0.93015332 0.83206107 0.9384058  0.921875  ]
ミクロ平均:0.9235382308845578
マクロ平均:0.9056237969449723
#結合
pre = np.append(pre, [micro_average, macro_average])
print(pre)
##出力
[0.93015332 0.83206107 0.9384058  0.921875   0.92353823 0.9056238 ]

再現率とF1スコアも同様の手順で算出します。

#再現率
from sklearn.metrics import recall_score
rec = recall_score(y_test, test_predict[1], average=None, labels=['b','t','e','m'])
micro_average = recall_score(y_test, test_predict[1], average='micro')
macro_average = recall_score(y_test, test_predict[1], average='macro')
rec = np.append(rec, [micro_average, macro_average])

#Fスコア
from sklearn.metrics import f1_score
f1 = f1_score(y_test, test_predict[1], average=None, labels=['b','t','e','m'])
micro_average = f1_score(y_test, test_predict[1], average='micro')
macro_average = f1_score(y_test, test_predict[1], average='macro')
f1 = np.append(f1, [micro_average, macro_average])

最後に見やすいようにデータフレーム化します。

#データフレーム化
scores = pd.DataFrame({'適合率':pre, '再現率':rec, 'F1スコア':f1},
                      index=['b','e','t','m','micro','macro'])
scores

f:id:TBT_matsu:20200901105406p:plain

57.特徴量の重みの確認

「52で学習したロジスティック回帰モデルの中で,重みの高い特徴量トップ10と,重みの低い特徴量トップ10を確認せよ.」

#カラム名
features = x_train.columns.values
#重みの高い特徴量トップ10
for c,coef in zip(model.classes_, model.coef_):
  idx = np.argsort(coef)
  print(c,features[idx][-10:][::-1])
##出力
b ['bank' 'fed' 'ecb' 'obamacare' 'yellen' 'ukraine' 'argentina' 'china'
 'buy' 'oil']
e ['kardashian' 'chris' 'miley' 'transformers' 'thrones' 'cyrus' 'movie'
 'paul' 'trailer' 'met']
m ['ebola' 'cancer' 'fda' 'mers' 'study' 'drug' 'brain' 'cases' 'cigarettes'
 'doctors']
t ['facebook' 'google' 'apple' 'climate' 'microsoft' 'tesla' 'nasa' 'fcc'
 'moon' 'heartbleed']
#重みの低い特徴量トップ10
for c,coef in zip(model.classes_, model.coef_):
  idx = np.argsort(coef)
  print(c,features[idx][:10])
##出力
b ['aereo' 'ebola' 'virus' 'subscription' 'nintendo' 'she' 'cap' 'apple'
 'gay' 'my']
e ['google' 'facebook' 'china' 'microsoft' 'gm' 'data' 'ebola' 'study' 'oil'
 'climate']
m ['dimon' 'gm' 'facebook' 'ceo' 'apple' 'twitter' 'climate' 'google' 'jobs'
 'sales']
t ['stocks' 'percent' 'still' 'office' 'concerns' 'fed' 'thrones' 'drug'
 'grows' 'movie']
58.正則化パラメータの変更

「ロジスティック回帰モデルを学習するとき,正則化パラメータを調整することで,学習時の過学習(overfitting)の度合いを制御できる.異なる正則化パラメータでロジスティック回帰モデルを学習し,学習データ,検証データ,および評価データ上の正解率を求めよ.実験の結果は,正則化パラメータを横軸,正解率を縦軸としたグラフにまとめよ.」

result = []
C = np.logspace(-5, 4, 10, base=10)
for c in C:
  #モデルの学習
  model = LogisticRegression(random_state=0, max_iter=5000, C=c)
  model.fit(x_train, y_train)
  #それぞれの予測値
  train_predict = predict(model, x_train)
  val_predict = predict(model, x_val)
  test_predict = predict(model, x_test)
  #正解率の計算
  train_acc = accuracy_score(y_train, train_predict[1])
  val_acc = accuracy_score(y_val, val_predict[1])
  test_acc = accuracy_score(y_test, test_predict[1])
  #resultに格納
  result.append([c, train_acc, val_acc, test_acc])
result = np.array(result).T
result
##出力
array([[1.00000000e-05, 1.00000000e-04, 1.00000000e-03, 1.00000000e-02,
        1.00000000e-01, 1.00000000e+00, 1.00000000e+01, 1.00000000e+02,
        1.00000000e+03, 1.00000000e+04],
       [4.21945277e-01, 5.58470765e-01, 7.21045727e-01, 7.86356822e-01,
        9.27380060e-01, 9.94565217e-01, 9.98969265e-01, 9.99062969e-01,
        9.99062969e-01, 9.99062969e-01],
       [4.12293853e-01, 5.52473763e-01, 7.00899550e-01, 7.61619190e-01,
        8.65067466e-01, 9.04797601e-01, 9.07046477e-01, 9.07046477e-01,
        9.05547226e-01, 9.01799100e-01],
       [4.31034483e-01, 5.57721139e-01, 7.16641679e-01, 7.78110945e-01,
        8.88305847e-01, 9.23538231e-01, 9.24287856e-01, 9.27286357e-01,
        9.23538231e-01, 9.20539730e-01]])
#可視化
plt.plot(result[0], result[1], label='train')
plt.plot(result[0], result[2], label='val')
plt.plot(result[0], result[3], label='test')
plt.ylim(0, 1.1)
plt.ylabel('Accuracy')
plt.xscale('log')
plt.xlabel('C')
plt.legend()
plt.show()

f:id:TBT_matsu:20200901110118p:plain

59.ハイパーパラメータの探索

「学習アルゴリズムや学習パラメータを変えながら,カテゴリ分類モデルを学習せよ.検証データ上の正解率が最も高くなる学習アルゴリズム・パラメータを求めよ.また,その学習アルゴリズム・パラメータを用いたときの評価データ上の正解率を求めよ.」

import itertools
def calc_scores(C,class_weight):
    #モデルの宣言
    model = LogisticRegression(random_state=0, max_iter=10000, C=C, class_weight=class_weight)
    #モデルの学習
    model.fit(x_train, y_train)
    #モデルの検証
    y_train_pred = model.predict(x_train)
    y_valid_pred = model.predict(x_val)
    y_test_pred = model.predict(x_test)
    #スコア
    scores = []
    scores.append(accuracy_score(y_train, y_train_pred))
    scores.append(accuracy_score(y_val, y_valid_pred))
    scores.append(accuracy_score(y_test, y_test_pred))
    return scores

# Cとclass_weightの総当たりの組み合わせを試します
C = np.logspace(-5, 4, 10, base=10)
class_weight = [None, 'balanced']
best_parameter = None
best_scores = None
max_valid_score = 0
#itertools.product()で全ての組み合わせを作成
for c, w in itertools.product(C, class_weight):
  # ハイパーパラメータの組み合わせの表示
  print(c, w)
  #ハイパーパラメータの組み合わせで関数の実行
  scores = calc_scores(c, w)
  #前のスコアより高ければ結果を更新
  if scores[1] > max_valid_score:
    max_valid_score = scores[1]
    best_parameter = [c, w]
    best_scores = scores
#最適なハイパーパラメータの組み合わせとスコアの表示
print ('C: ', best_parameter[0], 'solver: ', 'class_weight: ', best_parameter[1])
print ('best scores: ', best_scores)
print ('test accuracy: ', best_scores[2])
##出力
1e-05 None
1e-05 balanced
~中略~
10000.0 None
10000.0 balanced
C:  1.0 solver:  class_weight:  balanced
best scores:  [0.9921289355322339, 0.9160419790104948, 0.9212893553223388]
test accuracy:  0.9212893553223388


ここまでご覧いただきありがとうございます。
以上、第6章55~59でした!