Python深さ学習(映画評論分類:二分類問題)--学習ノート(五)


3.4映画評論分類:二分類問題


3.4.1 IMDBデータセット

  • このセクションでは、インターネット映画データベース(IMDB)からの50000件の深刻な両極化に関するコメントを含むIMDBデータセットを使用します.データセットは、トレーニング用の25000件のコメントとテスト用の25000件のコメントに分けられ、トレーニングセットとテストセットはいずれも50%の正面コメントと50%の負のコメントを含む.
  • は、訓練機械学習モデルの同じデータをテストモデルに再使用するべきではありません.モデルはトレーニングデータでよく表現されていますが、あなたが本当に関係しているのはモデルの新しいデータでの性能です(トレーニングデータに対応するラベルを知っているので、予測するためにモデルは必要ありません).たとえば、モデルは最終的にトレーニングサンプルとターゲット値のマッピング関係を覚えているだけで、これまで見られなかったデータの予測には役に立たない可能性があります.
  • MNISTデータセットと同様にIMDBデータセットもKerasライブラリに内蔵されている.前処理済み:コメント(単語シーケンス)は整数シーケンスに変換され、各整数は辞書の単語を表します.
  • #  IMDB 
    from keras.datasets import imdb
    
    (train_data, train_labels), (test_data, test_labels) = imdb.load_data(num_words=10000)
    
  • パラメータnum_words=10000とは、訓練データの中で最もよく見られる単語を10000個だけ保持することを意味する.低周波数の単語は捨てられます.このようにして得られるベクトルデータはあまり大きくなく,処理が容易である.
  • train_dataとtest_dataの2つの変数はいずれもコメントからなるリストであり、各コメントは単語インデックスからなるリスト(一連の単語を表す)である.train_Labelsとtest_Labelsはいずれも0と1からなるリストであり、0は負(negative)、1は正面(positive)を表す.
  • は、最初の10000個の最も一般的な単語に限定されるため、単語インデックスは10000を超えません.
  • #  
    word_index = imdb.get_word_index() # word_index 
    reverse_word_index = dict([(value, key) for (key, value) in word_index.items()])
    decoded_review = ' '.join([reverse_word_index.get(i-3, '?') for i in train_data[0]]) #  。 , 3, 0、1、2 "padding"、"start of sequence"( )、"unknown"( ) 
    print(decoded_review)
    

    3.4.2データの準備

  • 整数シーケンスをニューラルネットワークに直接入力することはできません.リストをテンソルに変換する必要があります:(1)リストを埋めて同じ長さにし、リストを(samples,word_indices)形状の整数テンソルに変換し、ネットワークの第1層はこのような整数テンソルを処理できる層(すなわちEmbeeding層)を使用します.(2)リストをone-hot符号化し,0と1からなるベクトルに変換する.
  • import numpy as np
    
    def vectorize_sequences(sequences, dimension=10000):
        results = np.zeros((len(sequences), dimension)) #  (len(sequences), dimension) 
        for i, sequence in enumerate(sequences):
            results[i, sequence] = 1. #  results[i] 1
    
        return results
    
    x_train = vectorize_sequences(train_data) #  
    x_test = vectorize_sequences(test_data) #  
    
  • ラベルを量子化する:
  • y_train = np.asarray(train_labels).astype('float32')
    y_test = np.asarray(test_labels).astype('float32')
    

    3.4.3ネットワークの構築

  • 入力データはベクトルであり、ラベルはスカラー(1と0)であり、これはあなたが直面する最も簡単な状況です.このような問題において、reluアクティブ化された全接続層(Dense)を有する単純なスタック、例えばDense(16,activation=‘relu’)が良好に表現されているネットワークがある.
  • がDense層に伝達するパラメータ(16)は、その層隠蔽ユニットの個数である.1つの非表示ユニット(hidden unit)は、このレイヤが空間を表す次元である.o u t p u t = r e l u ( d o t ( W , i n p u t ) + b ) output = relu(dot(W, input) + b) output=relu(dot(W,input)+b)
  • 16個の隠蔽ユニットに対応する重み行列W W W Wの形状は(input_dimension,16)であり、W Wのドット積は入力データを16次元表現空間に投影することに相当する(そしてバイアスベクトルb bを加えてr e l u relu演算を適用する).空間を表す次元は「ネットワークが内部表現を学習する際に持つ自由度」と直感的に理解できる.隠しユニットが多ければ多いほど(すなわち、より高い次元の表現空間)、ネットワークはより複雑な表現を学ぶことができるが、ネットワークの計算コストもより大きくなり、悪いモードを学ぶ可能性がある(このモードはトレーニングデータ上の性能を向上させるが、テストデータ上の性能を向上させることはない).
  • Denseレイヤのスタックについては、ネットワークがどのくらいのレイヤを持っているか、次の2つの重要なアーキテクチャを決定する必要があります.各レイヤにはいくつの隠しユニットがありますか.
  • #  
    from keras import models
    from keras import layers
    
    model = models.Sequential()
    model.add(layers.Dense(16, activation='relu', input_shape=(10000,)))
    model.add(layers.Dense(16, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))
    
  • アクティブ化関数とは?アクティブ化関数を使用する理由:reluなどの活性化関数(非線形とも呼ばれる)がない場合、Dense層は、o u t p u t=d o t(W,i n p u t)+b output=dot(W,input)+b output=dot(W,input)+bの2つの線形演算点積と加算のみを含み、Dense層は、入力データから16ビット空間までのすべての可能な線形変換の集合を学習するしかない.この仮定空間は非常に有効であり、複数の表現層の利点を利用することはできない.複数の線形層スタックが実現しているのは線形演算であり、層数を追加しても仮定空間を拡張することはないからである.より豊富な仮定空間を得るために、多層表現の利点を十分に利用するには、非線形またはアクティブ化関数を追加する必要があります.reluは深さ学習で最もよく使われるアクティブ化関数ですが、prelu、eluなど、他にも多くの関数があります.
  • 最後に、損失関数とオプティマイザを選択する必要があります.二分類の問題に直面しているため、ネットワーク出力は確率値である(ネットワークの最後のレイヤはsigmoidアクティブ化関数を使用し、1つのユニットのみを含む)、binary_を使用することが望ましい.crossentropy(二元交差エントロピー)損失.確率値を出力するモデルでは,クロスエントロピー(crossentropy)が最良の選択であることが多い.クロスエントロピーは確率分布間の距離を測定するための情報論分野からの概念であり,この例では真の分布と予測値間の距離である.
  • #  
    model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuray'])
    
  • 上記のコードは、rmsprop、binary_crossentropyとaccuracyはkeras内蔵の一部です.カスタムオプティマイザのパラメータを構成したり、カスタム損失関数や指標関数を入力したりする場合があります.前者は、optimizerパラメータにオプティマイザクラスインスタンスを入力することによって実現することができる.後者は、lossおよびmetricsパラメータに関数オブジェクトを入力することによって実現することができる.
  • #  
    from keras import optimizers
    
    model.compile(optimizer=optimizers.RMSprop(lr=0.001), loss='binary_crossentropy', metrics=['accuracy'])
    
    #  
    from keras import optimizers
    from keras import losses
    from keras import metrics
    
    model.compile(optimizer=optimizers.RMSprop(lr=0.001), loss=losses.binary_crossentropy, metrics=[metrics.binary_accuracy])
    

    3.4.4あなたの方法を検証する

  • トレーニング中にモデルが以前に見られなかったデータの精度を監視するには、元のトレーニングデータを検証セットとして10000個のサンプルを残す必要があります.
  • #  
    x_val = x_train[:10000]
    partial_x_train = x_train[10000:]
    
    y_val = y_train[:10000]
    partial_y_train = y_train[10000:]
    
  • は、512個のサンプルからなる小ロットを使用して、モデルを20個のラウンド(すなわち、x_trainおよびy_trainの2つのテンソルのうちのすべてのサンプルを20回反復する)で訓練した.同時に、残された10000個のサンプルにおける損失と精度を監視する必要がある.検証データをvalidation_に転送できます.dataパラメータで完了します.
  • #  
    model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['acc'])
    
    history = model.fit(partial_x_train, partial_y_train, epochs=20, batch_size=512, validation_data=(x_val, y_val))
    
  • modelを呼び出す.fit()はHistoryオブジェクトを返します.このオブジェクトは、トレーニング中のすべてのデータを含む辞書であるメンバーhistoryによって構成されます.
  • history_dict = history.history
    print(history_dict.keys())
    
  • 辞書には、トレーニングプロセスと検証プロセスで監視される指標に対応する4つの項目が含まれています.
  • #  
    import matplotlib.pyplot as plt
    
    history_dict = history.history
    loss_values = history_dict['loss']
    val_loss_values = history_dict['val_loss']
    
    epochs = range(1, len(loss_values) + 1)
    
    plt.plot(epochs, loss_values, 'bo', label='Training loss')
    plt.plot(epochs, val_loss_values, 'b', label='Validation loss')
    plt.title('Training and validation loss')
    plt.xlabel('Epochs')
    plt.ylabel('Loss')
    plt.legend()
    plt.show()
    
    #  
    plt.clf() #  
    acc = history_dict['acc']
    val_acc = history_dict['val_acc']
    
    plt.plot(epochs, acc, 'bo', label='Training acc')
    plt.plot(epochs, val_acc, 'b', label='Validation acc')
    plt.title('Training and validation accuracy')
    plt.xlabel('Epochs')
    plt.ylabel('Accuracy')
    plt.legend()
    
  • 訓練損失は各ラウンドで低下し、訓練精度は各ラウンドで向上している.これが勾配降下最適化の予想される結果であり,反復のたびに最小化したい量はますます小さくなる.しかし、検証損失と検証精度はそうではありません.モデルの訓練データでの表現はますます良くなったが,これまで見られなかったデータでは必ずしもよくなったとは限らない.
  • #  
    model = models.Sequential()
    model.add(layers.Dense(16, activation='relu', input_shape=(10000, )))
    model.add(layers.Dense(16, activation='relu'))
    model.add(layers.Dense(1, activation='sigmoid'))
    
    model.compile(optimizer='rmsprop', loss='binary_crossentropy', metrics=['accuracy'])
    
    model.fit(x_train, y_train, epochs=4, batch_size=512)
    results = model.evaluate(x_test, y_test)
    
    print(results)
    

    3.4.5訓練されたネットワークを用いて新しいデータ上で予測結果を生成する

  • ネットワークを訓練する後、predict法で肯定的な可能性の大きさ:m o d e lとコメントすることができる.p r e d i c t ( x t e s t ) model.predict(x_test) model.predict(xt​est)

  • 3.4.7まとめ

  • は、通常、ニューラルネットワークにテンソル入力に変換するために、元のデータを大量に前処理する必要がある.単語シーケンスはバイナリベクトルとして符号化できるが、他の符号化方式もある.
  • relu活性化されたdense層のスタックは、感情分類を含む多くの問題を解決することができ、このモデルをよく使用する可能性があります.
  • 二分類問題(二つの出力カテゴリ)については、ネットワークの最後のレイヤは、sigmoid活性化関数を用いた1セルのみのDeseレイヤであるべきであり、ネットワーク出力は0~1の範囲内のスカラーであり、確率値を表すべきである.
  • 二分類問題のsigmoidスカラー出力はbinary_crossentropy損失関数.
  • 質問が何であれ、rmspropオプティマイザは通常十分な選択です.
  • ニューラルネットワークの訓練データ上の表現がますます良くなるにつれて、モデルは最終的にフィッティングされ、これまで見られなかったデータ上でますます悪い結果を得る.モデルのトレーニングセット以外のデータのパフォーマンスを常に監視する必要があります.