Optimization

43422 ワード

Stochastic Gradient Descent (SGD)


1. SGD Classifier

  • 版dasデータフレームを生成します.
  • import pandas as pd
    
    fish = pd.read_csv('https://bit.ly/fish_csv_data')
  • Species列を除き、残りの5つを入力データとして使用します.
  • fish_input = fish[['Weight','Length','Diagonal','Height','Width']].to_numpy()
    fish_target = fish['Species'].to_numpy()
  • データをトレーニングセットとテストセットに分けます.
  • from sklearn.model_selection import train_test_split
    
    train_input, test_input, train_target, test_target = train_test_split(
        fish_input, fish_target, random_state=42)
  • トレーニングキットとテストキットの特性を標準化する前処理を行った.
  • from sklearn.preprocessing import StandardScaler
    
    ss = StandardScaler()
    ss.fit(train_input)
    train_scaled = ss.transform(train_input)
    test_scaled = ss.transform(test_input)
    scikit−learnにおいて確率傾斜降下法を提供する代表分類クラスはSGDClassifierである.
    SGD Classifierでオブジェクトを作成する場合は、2つのパラメータを指定します.loss=損失関数のタイプを指定max_iter=実行するフォークリフトの回数を指定
    from sklearn.linear_model import SGDClassifier
    
    sc = SGDClassifier(loss='log', max_iter=10, random_state=42)
    sc.fit(train_scaled, train_target)
    
    print(sc.score(train_scaled, train_target))
    # 0.773109243697479
    
    print(sc.score(test_scaled, test_target))
    # 0.775
    出力されたトレーニングキットとテストキットは精度が低い.
    確率傾斜降下法は점진적を学ぶことができる.
    訓練したモデルscを再訓練する.
    型継ぎ訓練はpartial_fit()法を採用した.
    この方法はfit()メソッドと同様ですが、呼び出すたびに1つのフォークでトレーニングできます.
    sc.partial_fit(train_scaled, train_target)
    
    print(sc.score(train_scaled, train_target))
    # 0.8151260504201681
    
    print(sc.score(test_scaled, test_target))
    # 0.85
    点数はまだ低いが、エポックをもう一度実行すると精度が上がる.
    このモデルを複数のエポックドで訓練する必要があり,多訓練の基準が必要である.

    2. Epoch and Overfitting/Underfitting


    確率傾斜降下法を用いたモデルでは,エポック回数によっては不適合やオーバーフィットが生じる可能性がある.적은 에포크 횟수期間中に訓練したモデルは、学習が少ないためunderfittingのモデルになった可能性が高い.
    逆に、많은 에포크 횟수期間中に訓練したモデルは訓練セットに適しており、テストセットでは点数が逆に低く、overfittingのモデルである可能性が高い.

    トレーニングセットの点数はエポックが進むにつれて増加していくが、テストセットの点数はある瞬間減少する.この場所のこのモデルはoverfitting되기 시작하는 곳です.
    ここではpartial_fit()メソッドのみを用いるが,これを行うには訓練セットのすべてのクラスのラベルをpartial fit()メソッドに渡す必要がある.
    import numpy as np
    
    sc = SGDClassifier(loss='log', random_state=42)
    
    train_score = []
    test_score = []
    
    classes = np.unique(train_target)
    
    # -----
    
    # 300번의 에포크 진행
    for _ in range(0, 300):
        sc.partial_fit(train_scaled, train_target, classes=classes)
        
        train_score.append(sc.score(train_scaled, train_target))
        test_score.append(sc.score(test_scaled, test_target))
        
     # -----
    
    import matplotlib.pyplot as plt
    
    plt.plot(train_score)
    plt.plot(test_score)
    plt.xlabel('epoch')
    plt.ylabel('accuracy')
    plt.show()

    100番目のフォークの後、トレーニングコースとテストコースの点数が徐々に広がった.また、エポック初期には、小さすぎたため、トレーニングセットやテストセットの点数が低かった.
    エポックを100に減らして、もう一度訓練します.
    sc = SGDClassifier(loss='log', max_iter=100, tol=None, random_state=42)
    sc.fit(train_scaled, train_target)
    
    print(sc.score(train_scaled, train_target))
    # 0.957983193277311
    
    print(sc.score(test_scaled, test_target))
    # 0.925
    SGDClassifierはスケジュールの中でフォークリフト期間中に性能が向上しなければ、これ以上訓練せずに自動的に停止する.tolパラメータは、増加する最大値を指定します.
    GDClassifierのlossパラメータについては、lossパラメータのデフォルト値はhingeです.
    Hinge損失はsupport vector machine(SVM)と呼ばれる損失関数である.
    sc = SGDClassifier(loss='hinge', max_iter=100, tol=None, random_state=42)
    sc.fit(train_scaled, train_target)
    
    print(sc.score(train_scaled, train_target))
    # 0.9495798319327731
    
    print(sc.score(test_scaled, test_target))
    # 0.925

    Feature Engineering and Regularization


    1. Data Preparation


    前回の授業では、線形回帰(線形回帰)を訓練するために特性を使用しました.
    この授業では、複数の特性を使用し、複数の特性を使用する線形回帰を多重回帰(multiple regression)と呼びます.
    本例では、スズキの長さだけでなく、スズキの깊이두께を同時に使用する.
    また,3つの特性をそれぞれ二乗して追加し,各特性を乗算して別の特性を生成する.
    このように既存の特性を用いて新しい特性を抽出する作業を특성 공학(feature engineering)と呼ぶ.
    import pandas as pd
    
    df = pd.read_csv('https://bit.ly/perch_csv_data')
    perch_full = df.to_numpy()
    print(perch_full)

    (一部のみ)
    スズキfullとスズキweightをトレーニングセットとテストセットに分けます.
    # target data
    import numpy as np
    
    perch_weight = np.array(
        [5.9, 32.0, 40.0, 51.5, 70.0, 100.0, 78.0, 80.0, 85.0, 85.0, 
         110.0, 115.0, 125.0, 130.0, 120.0, 120.0, 130.0, 135.0, 110.0, 
         130.0, 150.0, 145.0, 150.0, 170.0, 225.0, 145.0, 188.0, 180.0, 
         197.0, 218.0, 300.0, 260.0, 265.0, 250.0, 250.0, 300.0, 320.0, 
         514.0, 556.0, 840.0, 685.0, 700.0, 700.0, 690.0, 900.0, 650.0, 
         820.0, 850.0, 900.0, 1015.0, 820.0, 1100.0, 1000.0, 1100.0, 
         1000.0, 1000.0]
         )
    
    # -----
    
    from sklearn.model_selection import train_test_split
    
    train_input, test_input, train_target, test_target =
    train_test_split(perch_full, perch_weight, random_state=42)

    2. Transformer of Scikit-learn


    scikit-learningは、プロパティを作成または前処理するためのさまざまなクラスを提供します.この等級を변환기(transformer)と呼ぶ.
    2つの特性で、2と3からなる例を適用する.fit()法は新しい特性の組合せを探し,transform()法は実際にデータを変換する.
    from sklearn.preprocessing import PolynomialFeatures
    
    poly = PolynomialFeatures()
    poly.fit([[2, 3]])
    print(poly.transform([[2, 3]]))
    
    # [[1. 2. 3. 4. 6. 9.]]
    2つの属性(要素)を持つサンプル[2,3]6つの属性を持つサンプル[1.2.3.6.9]に変更します.
    poly = PolynomialFeatures(include_bias=False)
    poly.fit([[2, 3]])
    print(poly.transform([[2, 3]]))
    # [[2. 3. 4. 6. 9.]]
    スライスの項目が削除され、特性の二乗と特性の間に乗じた港湾が追加されます.
    poly = PolynomialFeatures(include_bias=False)
    
    poly.fit(train_input)
    train_poly = poly.transform(train_input)
    print(train_poly.shape) # (42, 9)
    PolynomialFeaturesクラスはget feature names()メソッドを呼び出すと、9つのプロパティがどの入力から結合されているかを示します.
    poly.get_feature_names_out()
    # array(['x0', 'x1', 'x2', 'x0^2', 'x0 x1', 'x0 x2', 'x1^2', 'x1 x2'
    # ,'x2^2'], dtype=object)
    
    test_poly = poly.transform(test_input)
    「x 0」は第1の特性を表し、「x 0^2」は第1の特性の二乗を表し、「x 0 x 1」は第1の特性と第2の特性の積を表す.

    3. Training Multiple Regression Model

    from sklearn.linear_model import LinearRegression
    
    lr = LinearRegression()
    lr.fit(train_poly, train_target)
    print(lr.score(train_poly, train_target))
    # 0.9903183436982124
    
    print(lr.score(test_poly, test_target))
    # 0.9714559911594134
    テストキットの点数は向上しなかったが、スズキの長さだけを使用した場合、基準に合わない問題は発生しなかった.
    さらにいくつかのプロパティを追加し、プロパティを5つの平方項に出力します.
    poly = PolynomialFeatures(degree=5, include_bias=False)
    
    poly.fit(train_input)
    train_poly = poly.transform(train_input)
    test_poly = poly.transform(test_input)
    print(train_poly.shape) # (42, 55)
    train polyアレイの列数は特性の個数である.
    これらのデータを用いて線形回帰モデルを再訓練した.
    lr.fit(train_poly, train_target)
    print(lr.score(train_poly, train_target))
    # 0.9999999999991097
    
    print(lr.score(test_poly, test_target))
    # -144.40579242684848
    訓練セットの点数はほとんど完璧で、テストセットの点数は大きな負数です.
    特性の個数を大幅に増やせば,線形モデルはほとんど訓練セットを完璧に学習できる.
    しかし,このモデルはフィットしすぎて,テスト集中で点数が大幅に低下する.

    4. Regularization


    規則化は、モデルをトレーニングセットにあまり適さないようにすることです.
    線形回帰モデルでは、特性を乗じた係数(または傾斜)のサイズが小さくなります.

    以前の55特性訓練の線形回帰モデルの係数を制限することによって,訓練セットの点数を低減し,代わりに試験セットの点数を向上させた.
    これに先立ち、scikit−learnが提供するStandardScalerクラスを使用して、特性を표준점수に変換し、その規模を正規化した.
    from sklearn.preprocessing import StandardScaler
    
    ss = StandardScaler()
    ss.fit(train_poly)
    
    train_scaled = ss.transform(train_poly)
    test_scaled = ss.transform(test_poly)
    線形回帰モデルに正規化を加えたモデルをRidgeおよびLassoと呼ぶ.Ridgeは、係数が제곱の値に従って制限される.Lasso係数の절대값を基準として規定を適用する.
    どちらのアルゴリズムも係数の大きさを小さくしたが,Lassoはいっそゼロになる可能性がある.

    Ridge (L2 Regularization)


    Ridgeモデルをtrain scaledデータで訓練した.
    from sklearn.linear_model import Ridge
    
    ridge = Ridge()
    ridge.fit(train_scaled, train_target)
    print(ridge.score(train_scaled, train_target))
    # 0.9896101671037343
    
    print(ridge.score(test_scaled, test_target))
    # 0.9790693977615397
    RidgeとLassoモデルを使用する場合、正規化された量を任意に調整できます.モデルオブジェクトを作成するときに、alphaパラメータを使用して、正規化された강도を調整します.
    適切なalpha値を見つける方法の1つは、alpha値のためにR^2 값의 그래프を描画することである.
    Alpha値を変更するたびに、score()メソッドの結果を保存するリストが作成されます.
    import matplotlib.pyplot as plt
    
    train_score = []
    test_score = []
    
    # alpha 값을 0.001에서 100까지 10배씩 늘려가며
    # Ridge 회귀 모델을 훈련한 다음,
    # 훈련 세트와 테스트 세트의 점수를 파이썬 리스트에 저장
    
    alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
    for alpha in alpha_list:
        # 릿지 모델을 만듦
        ridge = Ridge(alpha=alpha)
        
        # 릿지 모델을 훈련
        ridge.fit(train_scaled, train_target)
        
        # 훈련 점수와 테스트 점수를 저장
        train_score.append(ridge.score(train_scaled, train_target))
        test_score.append(ridge.score(test_scaled, test_target))
    
    plt.plot(np.log10(alpha_list), train_score)
    plt.plot(np.log10(alpha_list), test_score)
    plt.xlabel('alpha')
    plt.ylabel('R^2')
    plt.show()

    上はトレーニングコース図、下はテストコース図です.
    適切なalpha値は、2つのグラフィックが最も近く、テストセットの得点が最も高い−1、すなわち0.1である.
    Alpha値を0.1に設定して最終モデルを訓練します.
    ridge = Ridge(alpha=0.1)
    ridge.fit(train_scaled, train_target)
    
    print(ridge.score(train_scaled, train_target))
    # 0.9903815817570366
    
    print(ridge.score(test_scaled, test_target))
    # 0.9827976465386926

    Lasso (L1 Regularization)

    from sklearn.linear_model import Lasso
    
    lasso = Lasso()
    lasso.fit(train_scaled, train_target)
    print(lasso.score(train_scaled, train_target))
    # 0.989789897208096
    
    print(lasso.score(test_scaled, test_target))
    # 0.9800593698421883
    
    train_score = []
    test_score = []
    
    alpha_list = [0.001, 0.01, 0.1, 1, 10, 100]
    for alpha in alpha_list:
        # 라쏘 모델을 만듦
        lasso = Lasso(alpha=alpha, max_iter=10000)
        # 라쏘 모델을 훈련
        lasso.fit(train_scaled, train_target)
        # 훈련 점수와 테스트 점수를 저장
        train_score.append(lasso.score(train_scaled, train_target))
        test_score.append(lasso.score(test_scaled, test_target))
    
    plt.plot(np.log10(alpha_list), train_score)
    plt.plot(np.log10(alpha_list), test_score)
    plt.xlabel('alpha')
    plt.ylabel('R^2')
    plt.show()

    Lassoモデルでは最適alpha値は1,すなわち10であった.
    この値段でモデルを再訓練します.
    lasso = Lasso(alpha=10)
    lasso.fit(train_scaled, train_target)
    
    print(lasso.score(train_scaled, train_target))
    # 0.9888067471131867
    
    print(lasso.score(test_scaled, test_target))
    # 0.9824470598706695
    Lassoモデルは直接係数値を0に設定できます.
    coef属性検証係数は0です.
    print(np.sum(lasso.coef_ == 0)) # 40