自然言語処理⑨~100本ノック6, 7章~
今回は100本ノック6, 7章について取り上げます。
6章は機械学習、7章は単語ベクトルと、今までの自然言語処理と機械学習の範囲を使って挑戦していくことができます。
100本ノックなので、ここで一問ずつ解説するのもあまり意味がないので、いつも通りピックアップして解説していこうと思います。
では、今回もよろしくお願いします
(ちなみに、次回以降はtensorflow基礎をカバーして行き、またRNNに戻る予定にしました。)
・第6章
51. 特徴量抽出
学習データ,検証データ,評価データから特徴量を抽出し,それぞれtrain.feature.txt,valid.feature.txt,test.feature.txtというファイル名で保存せよ. なお,カテゴリ分類に有用そうな特徴量は各自で自由に設計せよ.記事の見出しを単語列に変換したものが最低限のベースラインとなるであろう.
今回使われていた関数としてstringというパッケージがあり、
string.punctuationというものが出てきました。
初めて見たのですが、いわゆる記号群たちを表示してくれます。
import string
print(string.punctuation)
また、maketrans(in, out)により、inをoutに変更するためのマッピングを準備します。
次にstr.translate(table)でtableで用意したフォーマットにマッチした文字を変更します。
intab = "aeiou"
outtab = "12345"
trantab = str.maketrans(intab, outtab)
str = "this is string example....wow!!!"
print (str.translate(trantab))
ちなみに、自分は今回前処理はせずに進めましたが、解答は丁寧ですね。。
59. ハイパーパラメータの探索
学習アルゴリズムや学習パラメータを変えながら,カテゴリ分類モデルを学習せよ.検証データ上の正解率が最も高くなる学習アルゴリズム・パラメータを求めよ.また,その学習アルゴリズム・パラメータを用いたときの評価データ上の正解率を求めよ.
今回自分はgridsearchを使いましたが、解答はoptunaを使っていました。
ここではoptuna には触れてこなかったので、少し調べてみました。
いわゆるハイパーパラメータチューニングの自動化をしてくれるもので、ベイズ最適化などが裏で行われているそうです。
ちょっと調べてみて使い方を調べると、以下のブログが一番わかりやすかったです。
それを踏まえて、今回の解答をみて行きます。
解答は以下のURLから引用させていただきました。
import optuna
# 最適化対象を関数で指定
def objective_lg(trial):
# チューニング対象パラメータのセット
l1_ratio = trial.suggest_uniform('l1_ratio', 0, 1)
C = trial.suggest_loguniform('C', 1e-4, 1e4)
# モデルの学習
lg = LogisticRegression(random_state=123,
max_iter=10000,
penalty='elasticnet',
solver='saga',
l1_ratio=l1_ratio,
C=C)
lg.fit(X_train, train['CATEGORY'])
# 予測値の取得
valid_pred = score_lg(lg, X_valid)
# 正解率の算出
valid_accuracy = accuracy_score(valid['CATEGORY'], valid_pred[1])
return valid_accuracy
まず、チューニングの実装手順としてobjective関数を定義する必要があります。
その中に
trial.suggest_uniformで指定したパラメータを指定範囲で一様分布したパラメータを順に取得して行きます。
trial.loguniformでは指定範囲を対数スケールで順番に取得して行きます。
今回はロジスティック回帰のみを用いていますが、複数の関数にて調整して行きたい時は
trial.suggest_categorical(関数名(自分で命名), [関数を格納])
で定義し、if文で分岐させて行きます
====以下が参考====
import sklearn.ensemble
import sklearn.svm
def objective(trial):
classifier_name = trial.suggest_categorical("classifier", ["SVC", "RandomForest"])
if classifier_name == "SVC":
svc_c = trial.suggest_float("svc_c", 1e-10, 1e10, log=True)
classifier_obj = sklearn.svm.SVC(C=svc_c)
else:
rf_max_depth = trial.suggest_int("rf_max_depth", 2, 32, log=True)
classifier_obj = sklearn.ensemble.RandomForestClassifier(max_depth=rf_max_depth)
========
次にロジスティック回帰の中に先程の変数を正しい場所に格納。
そのあとはいつも通りfit, predict or score などを行います(今回はその前の問題で自作した関数score_lgを利用されています。)
このobjective関数では正解率が返されます
次に、optuna の手順として、Studyのクラスをインスタンス化します。
# 最適化
study = optuna.create_study(direction='maximize')
study.optimize(objective_lg, timeout=3600)
# 結果の表示
print('Best trial:')
trial = study.best_trial
print(' Value: {:.3f}'.format(trial.value))
print(' Params: ')
for key, value in trial.params.items():
print(' {}: {}'.format(key, value))
directionを指定することで最大値を取るように指定します。
インスタンス化したら、先程生成したobjectiveとn_trialsで試行回数を指定します(今回は指定なし。デフォルトは100??)今回はtimeoutで時間制限内に可能な限り試行するように指示しています。
これでおしまい。
めちゃ簡単に調整してくれて、study.params.items()で誤分類率で一番正解率のよいパラメータも取得できたりと、gridsearchと似たような挙動を行ってくれます。
ガッツリ使う時があればその時にまた学習してここで書こうと思いますが、一旦はこの辺にします。
(ちなみに解説ではXGBoostでも挑戦しています。)
・第7章: 単語ベクトル
こちらも5章と同様に、データの読み込みがクセ。
60. 単語ベクトルの読み込みと表示
Google Newsデータセット(約1,000億単語)での学習済み単語ベクトル(300万単語・フレーズ,300次元)をダウンロードし,”United States”の単語ベクトルを表示せよ.ただし,”United States”は内部的には”United_States”と表現されていることに注意せよ.
FILE_ID = "0B7XkCwpI5KDYNlNUTTlSS21pQmM"
FILE_NAME = "GoogleNews-vectors-negative300.bin.gz"
!wget --load-cookies /tmp/cookies.txt "https://docs.google.com/uc?export=download&confirm=$(wget --quiet --save-cookies /tmp/cookies.txt --keep-session-cookies --no-check-certificate 'https://docs.google.com/uc?export=download&id=$FILE_ID' -O- | sed -rn 's/.*confirm=([0-9A-Za-z_]+).*/\1\n/p')&id=$FILE_ID" -O $FILE_NAME && rm -rf /tmp/cookies.txt
クセ。
今回、格納先がgoogle driveなので、シンプルにwgetだけではうまく行きません。
今回wgetに使われているオプションは以下が参考になります。
全部スラスラと書ける人がどれくらいいるのか不明ですw
正直ここは適当に解答を参照して進めましょうw
ちなみに、上記コマンドでは.gzファイルなので、catやheadコマンドでは見れないです。
また、普通に読み込むことも難しいため、.gzファイルのまま読み込むgensimのload_word2vec_formatを使っています。(クセ。)
ちなみに、この章の参考は第6章と同じサイトを使用しております。
from gensim.models import KeyedVectors
model = KeyedVectors.load_word2vec_format('./GoogleNews-vectors-negative300.bin.gz', binary=True)
ここではgensimのword2vec, doc2vecのみしか扱ってきませんでしたので、解説します。
classmethodload_word2vec_format(fname, fvocab=None, binary=False, encoding='utf8', unicode_errors='strict', limit=None, datatype=<class 'numpy.float32'>, no_header=False)
fname: word2vecで学習済みのフォーマットで保存されたファイルのpathを指定。
binary: word2vecで学習済みのフォーマットがbinary=Trueで保存されている時にTrueを指定。
load_~があるモジュールがKeyVectorsなのですが、ここで定義したmodelもWord2Vecのようにsimilarity, most_similarなどのメソッドを持っているため、同じように使うことができます。
あとはt-SNE以外は基本的に解ける解けないを別として解説を見ればわかるかと思いますので、是非挑戦してみましょう。
・終わり
次回以降からtensorflow基礎を(自分が)学び始めます