[[387235]] テスト セットのヒル クライミングは、トレーニング セットに影響を与えたり、予測モデルを開発したりすることなく、機械学習の競争で優れた予測または完璧な予測を達成する方法です。機械学習の競技方法としては、これは当然のことであり、ほとんどの競技プラットフォームではこれを防ぐために制限を課していることに注意することが重要です。しかし、テスト セットのヒル クライミングは、機械学習の専門家が競技会に参加する際に誤って行うものです。テスト セットを昇順で処理するための明示的な実装を開発することで、モデリング パイプラインを評価するためにテスト データセットを過度に使用することで、テスト データセットが過剰適合されやすいことをよりよく理解できるようになります。 このチュートリアルでは、機械学習のテスト セットをスケーリングする方法を説明します。このチュートリアルを完了すると、次のことが分かります。 - トレーニング データセットを確認することなく、テスト セットをクロールするだけで完璧な予測を行うことができます。
- 分類および回帰タスクのテスト セットを増やす方法。
- モデリング パイプラインを評価するためにテスト セットを過度に使用すると、暗黙的にテスト セットのレベルが上がることになります。
チュートリアルの概要 このチュートリアルは 5 つのパートに分かれています。彼らです: - ヒルクライムテスター
- ヒルクライミングアルゴリズム
- 登り方
- 登山糖尿病分類データセット
- ヒルクライミングハウス回帰データセット
ヒルクライムテスター Kaggle の機械学習コンペティションと同様に、機械学習コンペティションでは、完全なトレーニング データセットとテスト セットの入力が提供されます。特定のゲームの目的は、テスト セットのラベルや数値などのターゲット値を予測することです。ソリューションは、非表示のテスト設定の目標値に対して評価され、適切にスコア付けされます。テストセットで最高得点を獲得したエントリーがコンテストに勝利します。機械学習コンテストの課題は、最適化問題として捉えることができます。従来、コンテスト参加者は最適化アルゴリズムとして機能し、さまざまな予測セットにつながるさまざまなモデリング パイプラインを探索し、予測にスコアを付け、より高いスコアを達成することを期待してパイプラインに変更を加えます。このプロセスは最適化アルゴリズムを使用して直接モデル化することもでき、トレーニング セットを確認することなく候補予測を生成および評価できます。これはしばしばヒルクライミングテストセットと呼ばれ、この問題に対する最も単純な最適化アルゴリズムの 1 つがヒルクライミングアルゴリズムです。テスト セットをクリアすることは、実際の機械学習コンテストでは正しく実行する必要があることですが、このアプローチを実装して、方法の限界とテスト セットの過剰適合の危険性を理解するのは興味深い演習になるかもしれません。さらに、トレーニング データセットに一切触れることなくテスト セットを完全に予測できるという事実は、多くの初心者の機械学習実践者にとって衝撃となることがよくあります。最も重要なことは、さまざまなモデリング パイプラインを繰り返し評価する中で、暗黙的にテスト セットを拡張していったことです。リスクは、テスト セットのスコアは向上しますが、一般化エラーが増加する、つまり、より広範囲の問題でパフォーマンスが低下するという点です。機械学習のコンテストを運営している人たちはこの問題をよく認識しており、予測評価に制限を課して対処しています。たとえば、評価を 1 日に 1 回または数回に制限したり、テスト セット全体ではなくテスト セットの非表示のサブセットのスコアを報告したりします。 。詳細については、「参考文献」セクションに記載されている論文を参照してください。次に、ヒルクライミングアルゴリズムを実装してテストセットの予測を最適化する方法を見てみましょう。 ヒルクライミングアルゴリズム ヒルクライミングは非常に単純な最適化アルゴリズムです。候補ソリューションを生成し、評価することが含まれます。その後、さらなる改善が達成できなくなるか、時間、リソース、または関心がなくなるまで、段階的な改善の出発点があります。既存の候補ソリューションから新しい候補ソリューションを生成します。通常、これには、候補ソリューションに 1 つの変更を加えて評価し、候補ソリューションが以前の現在のソリューションと同等かそれ以上である場合は、その候補ソリューションを新しい「現在の」ソリューションとして受け入れることが含まれます。それ以外の場合は破棄します。より高いスコアを持つ候補者だけを受け入れるのが良い考えだと考えるかもしれません。多くの単純な問題ではこれは合理的なアプローチですが、より複雑な問題では、検索プロセスが特徴空間内の平坦な領域 (プラトー) をスケーリングできるように、同じスコアを持つ異なる候補を受け入れることが望ましいです。テスト セットを登るとき、候補ソリューションは予測のリストになります。バイナリ分類タスクの場合、これは 2 つのクラスの 0 と 1 の値のリストです。回帰タスクの場合、これはターゲット変数の範囲内の数値のリストです。候補分類ソリューションを変更するには、予測を選択し、それを 0 から 1 に、または 1 から 0 に反転します。回帰の候補ソリューションを変更するには、リスト内の値にガウス ノイズを追加するか、リスト内の値を新しい値に置き換えます。ソリューションのスコアリングには、分類タスクの分類精度や回帰タスクの平均絶対誤差などのスコアリング メトリックの計算が含まれます。アルゴリズムについて理解できたので、それを実装してみましょう。 登り方 包括的な分類タスクに関するヒルクライミングアルゴリズムを開発します。まず、多数の入力変数と 5,000 行の例を含むバイナリ分類タスクを作成します。次に、データセットをトレーニング セットとテスト セットに分割します。完全な例を以下に示します。 - # 合成データセットの例。
- sklearn.datasets から make_classification をインポートします
- sklearn.model_selection から train_test_split をインポートします
- #データセットを定義する
- X, y = make_classification ( n_samples = 5000 、 n_features = 20 、 n_informative = 15 、 n_redundant = 5 、 random_state = 1 )
- print(X.shape, y.shape)
- # データセットを分割
- X_train、X_test、y_train、 y_test = train_test_split (X、y、 test_size = 0.33 、 random_state = 1 )
- 印刷(X_train.shape、X_test.shape、y_train.shape、y_test.shape)
この例を実行すると、最初に作成されたデータセットの形状が報告され、5,000 行と 20 個の入力変数が表示されます。次に、データセットはトレーニング セットとテスト セットに分割され、トレーニング用に約 3,300 個の例、テスト用に約 1,600 個の例が含まれます。 - (5000, 20) (5000,)
- (3350, 20) (1650, 20) (3350,) (1650,)
今なら登山家を育てることができます。まず、データセットをロードする、またはこの場合はデータセットを定義する関数を作成します。この関数は、データセットを変更するときに後で更新できます。 - # 分類データセットをロードまたは準備する
- def load_dataset():
- make_classification を返します( n_samples = 5000 、 n_features = 20 、 n_informative = 15 、 n_redundant = 5 、 random_state = 1 )
次に、候補ソリューション、つまり予測のリストを評価する関数が必要です。分類精度を使用します。スコアの範囲は 0 (最悪の解決策) から 1 (予測の完全なセット) までです。 - # 一連の予測を評価する
- 予測を評価する定義(y_test, yhat):
- 精度スコア(y_test, yhat)を返す
次に、初期の候補ソリューションを作成する関数が必要です。これは、クラス 0 および 1 のラベルの予測のリストであり、テスト セット内の例の数 (この場合は 1650) と一致するのに十分な長さです。 randint() 関数を使用して、0 と 1 のランダムな値を生成できます。 - # ランダムな予測セットを作成する
- 定義: ランダム予測(n_examples):
- [randint(0, 1) を範囲(n_examples)] で返す
次に、候補ソリューションの修正バージョンを作成する機能が必要です。この場合、ソリューション内の値を選択し、それを 0 から 1 に、または 1 から 0 に反転することになります。通常、ヒルクライミング中に新しい候補ソリューションごとに 1 つの変更を加えますが、関数をパラメーター化して、必要なだけ変更を探索できるようにしました。 - # 現在の予測セットを変更する
- 変更予測を定義します(現在、 n_changes = 1 ):
- # 現在のソリューションをコピー
- 更新=現在の.copy()
- i が範囲内(n_changes)の場合:
- # 変更するポイントを選択
- ix = randint (0, len(更新)-1)
- # クラスラベルを反転する
- 更新[ix] = 1 - 更新[ix]
- 返品が更新されました
ここまでは順調ですね。次に、検索を実行する機能を開発します。まず、random_predictions() 関数を呼び出して初期ソリューションが作成され、評価され、その後、validate_predictions() 関数が呼び出されます。次に、固定回数ループして、modify_predictions() を呼び出して新しい候補を生成し、それを評価して、現在のソリューションと同じかそれよりも良いスコアの場合は置き換えます。このループは、事前に設定された反復回数(任意に選択)を完了するか、理想的なスコア(この場合は 1.0(100% の精度))に到達したときに終了します。以下の関数 hill_climb_testset() は、この機能を実装し、テスト セットを入力として受け取り、ヒル クライム中に見つかった予測の最良のセットを返します。 - # 一連の予測のためにヒルクライムを実行する
- hill_climb_testset(X_test、y_test、最大反復回数)を定義します。
- スコア=リスト()
- # 初期ソリューションを生成する
- 解=ランダム予測(X_test.shape[0])
- # 初期ソリューションを評価する
- スコア=予測評価(y_test, 解)
- スコア.append(スコア)
- # 解決への道
- i が範囲内(max_iterations)の場合:
- # 記録的なスコア
- スコア.append(スコア)
- # 最高スコアを達成したら停止します
- スコア== 1.0 の場合:
- 壊す
- # 新しい候補を生成する
- 候補=予測を修正(解決策)
- # 候補者を評価する
- 値=予測評価(y_test, 候補)
- # 同じかそれ以上か確認する
- 値> = スコアの場合:
- 解決策、スコア=候補、値
- print(' > %d,スコア=%.3f' % (i, スコア))
- リターンソリューション、スコア
以上です。ヒルクライム テスト セットアップの完全な例を以下に示します。 - # 分類タスクのテストセットを山登りする例
- ランダムインポートrandint
- sklearn.datasets から make_classification をインポートします
- sklearn.model_selection から train_test_split をインポートします
- sklearn.metricsからaccuracy_scoreをインポートする
- matplotlibからpyplotをインポートする
- # 分類データセットをロードまたは準備する
- def load_dataset():
- make_classification を返します( n_samples = 5000 、 n_features = 20 、 n_informative = 15 、 n_redundant = 5 、 random_state = 1 )
- # 一連の予測を評価する
- 予測を評価する定義(y_test, yhat):
- 精度スコア(y_test, yhat)を返す
- # ランダムな予測セットを作成する
- 定義: ランダム予測(n_examples):
- [randint(0, 1) を範囲(n_examples)] で返す
- # 現在の予測セットを変更する
- 変更予測を定義します(現在、 n_changes = 1 ):
- # 現在のソリューションをコピー
- 更新=現在の.copy()
- i が範囲内(n_changes)の場合:
- # 変更するポイントを選択
- ix = randint (0, len(更新)-1)
- # クラスラベルを反転する
- 更新[ix] = 1 - 更新[ix]
- 返品が更新されました
- # 一連の予測のためにヒルクライムを実行する
- hill_climb_testset(X_test、y_test、最大反復回数)を定義します。
- スコア=リスト()
- # 初期ソリューションを生成する
- 解=ランダム予測(X_test.shape[0])
- # 初期ソリューションを評価する
- スコア=予測評価(y_test, 解)
- スコア.append(スコア)
- # 解決への道
- i が範囲内(max_iterations)の場合:
- # 記録的なスコア
- スコア.append(スコア)
- # 最高スコアを達成したら停止します
- スコア== 1.0 の場合:
- 壊す
- # 新しい候補を生成する
- 候補=予測を修正(解決策)
- # 候補者を評価する
- 値=予測評価(y_test, 候補)
- # 同じかそれ以上か確認する
- 値> = スコアの場合:
- 解決策、スコア=候補、値
- print(' > %d,スコア=%.3f' % (i, スコア))
- リターンソリューション、スコア
- # データセットをロードする
- X, y = load_dataset ()
- print(X.shape, y.shape)
- # データセットをトレーニングセットとテストセットに分割する
- X_train、X_test、y_train、 y_test = train_test_split (X、y、 test_size = 0.33 、 random_state = 1 )
- 印刷(X_train.shape、X_test.shape、y_train.shape、y_test.shape)
- # ヒルクライムを走る
- yhat、スコア= hill_climb_testset (X_test、y_test、20000)
- # スコアと反復回数をプロットする
- pyplot.plot(スコア)
- pyplot.show()
例を実行すると、検索が 20,000 回反復して実行されるか、目的の精度が達成されると停止します。注意: アルゴリズムや評価手順の確率的特性、または数値精度の違いにより、結果が異なる場合があります。例を複数回実行し、平均結果を比較することを検討してください。この場合、約 12,900 回の反復でテスト セット予測の理想的なセットが見つかりました。これは、トレーニング データセットに触れることなく、またテスト セットのターゲット値を確認することで不正行為をすることなく達成されることを思い出してください。代わりに、一連の数字を単純に最適化しました。ここでの教訓は、テスト パイプラインを山登り最適化アルゴリズムとして使用し、テスト セットでモデリング パイプラインの評価を繰り返すことで同じことが行われることです。ソリューションはテスト セットに過剰適合します。 - ...
- > 8092 、スコア= 0.996
- > 8886 、スコア= 0.997
- > 9202 、スコア= 0.998
- > 9322 、スコア= 0.998
- > 9521 、スコア= 0.999
- > 11046 、スコア= 0.999
- > 12932 、スコア= 1.000
最適化の進行状況グラフも作成されます。これは、最適化アルゴリズムの変更 (ランプ上で何を変更するか、どのように変更するかの選択など) が検索の収束にどのように影響するかを理解するのに役立ちます。 登山糖尿病分類データセット 分類問題のためのヒルクライミングテストセットを調査するための基礎として、糖尿病データセットを使用します。各記録には女性の健康状態の詳細が記されており、今後5年以内に糖尿病を発症すると予測されていた。 データセットの詳細: pima-indians-diabetes.names データセット: pima-indians-diabetes.csv データセットには 8 つの入力変数と 768 行のデータがあります。入力変数はすべて数値で、ターゲットには 2 つのクラス ラベルがあります。つまり、これはバイナリ分類タスクです。データセットの最初の 5 行の例を以下に示します。 - 6,148,72,35,0,33.6,0.627,50,1
- 1,85,66,29,0,26.6,0.351,31,0
- 8,183,64,0,0,23.3,0.672,32,1
- 1,89,66,23,94,28.1,0.167,21,0
- 0,137,40,35,168,43.1,2.288,33,1
- ...
以下に示すように、Pandas を使用してデータセットを直接読み込むことができます。 - # 分類データセットをロードまたは準備する
- def load_dataset():
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.csv'
- df = read_csv (url、ヘッダー=なし)
- データ= df.values
- データ[:, :-1]、データ[:, -1]を返す
残りのコードは変更されません。このファイルは、独自のバイナリ分類タスクをドロップして試すことができるように作成されました。完全な例を以下に示します。 - # 糖尿病データセットのテストセットのヒルクライミングの例
- ランダムインポートrandint
- pandasからread_csvをインポートする
- sklearn.model_selection から train_test_split をインポートします
- sklearn.metricsからaccuracy_scoreをインポートする
- matplotlibからpyplotをインポートする
- # 分類データセットをロードまたは準備する
- def load_dataset():
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/pima-indians-diabetes.csv'
- df = read_csv (url、ヘッダー=なし)
- データ= df.values
- データ[:, :-1]、データ[:, -1]を返す
- # 一連の予測を評価する
- 予測を評価する定義(y_test, yhat):
- 精度スコア(y_test, yhat)を返す
- # ランダムな予測セットを作成する
- 定義: ランダム予測(n_examples):
- [randint(0, 1) を範囲(n_examples)] で返す
- # 現在の予測セットを変更する
- 変更予測を定義します(現在、 n_changes = 1 ):
- # 現在のソリューションをコピー
- 更新=現在の.copy()
- i が範囲内(n_changes)の場合:
- # 変更するポイントを選択
- ix = randint (0, len(更新)-1)
- # クラスラベルを反転する
- 更新[ix] = 1 - 更新[ix]
- 返品が更新されました
- # 一連の予測のためにヒルクライムを実行する
- hill_climb_testset(X_test、y_test、最大反復回数)を定義します。
- スコア=リスト()
- # 初期ソリューションを生成する
- 解=ランダム予測(X_test.shape[0])
- # 初期ソリューションを評価する
- スコア=予測評価(y_test, 解)
- スコア.append(スコア)
- # 解決への道
- i が範囲内(max_iterations)の場合:
- # 記録的なスコア
- スコア.append(スコア)
- # 最高スコアを達成したら停止します
- スコア== 1.0 の場合:
- 壊す
- # 新しい候補を生成する
- 候補=予測を修正(解決策)
- # 候補者を評価する
- 値=予測評価(y_test, 候補)
- # 同じかそれ以上か確認する
- 値> = スコアの場合:
- 解決策、スコア=候補、値
- print(' > %d,スコア=%.3f' % (i, スコア))
- リターンソリューション、スコア
- # データセットをロードする
- X, y = load_dataset ()
- print(X.shape, y.shape)
- # データセットをトレーニングセットとテストセットに分割する
- X_train、X_test、y_train、 y_test = train_test_split (X、y、 test_size = 0.33 、 random_state = 1 )
- 印刷(X_train.shape、X_test.shape、y_train.shape、y_test.shape)
- # ヒルクライムを走る
- yhat、スコア= hill_climb_testset (X_test、y_test、5000)
- # スコアと反復回数をプロットする
- pyplot.plot(スコア)
- pyplot.show()
例を実行すると、各検索中に改善が見られる反復回数と精度が報告されます。 この場合、予測する回数が少なくなるため、反復回数が少なくなり、最適化が簡単になります。 注意: アルゴリズムや評価手順の確率的特性、または数値精度の違いにより、結果が異なる場合があります。例を複数回実行し、平均結果を比較することを検討してください。 この場合、約 1,500 回の反復で完全な精度が達成されることがわかります。 - ...
- > 617 、スコア= 0.961
- > 627 、スコア= 0.965
- > 650 、スコア= 0.969
- > 683 、スコア= 0.972
- > 743 、スコア= 0.976
- > 803 、スコア= 0.980
- > 817 、スコア= 0.984
- > 945 、スコア= 0.988
- > 1350 、スコア= 0.992
- > 1387 、スコア= 0.996
- > 1565 、スコア= 1.000
検索の進行状況を示す折れ線グラフも作成され、収束が速かったことが示されました。 ヒルクライミングハウス回帰データセット 住宅データセットを基礎として、ヒルクライミングテストセット回帰問題を調査します。住宅データセットには、住宅とその周辺地域に関する詳細な情報に基づく、数千ドル相当の住宅価格予測が含まれています。 データセットの詳細: housing.names データセット: housing.csv これは回帰問題であり、数値を予測することを意味します。合計 506 個の観測値があり、13 個の入力変数と 1 個の出力変数で構成されています。最初の 5 行の例を以下に示します。 - 0.00632,18.00,2.310,0,0.5380,6.5750,65.20,4.0900,1,296.0,15.30,396.90,4.98,24.00
- 0.02731,0.00,7.070,0,0.4690,6.4210,78.90,4.9671,2,242.0,17.80,396.90,9.14,21.60
- 0.02729,0.00,7.070,0,0.4690,7.1850,61.10,4.9671,2,242.0,17.80,392.83,4.03,34.70
- 0.03237,0.00,2.180,0,0.4580,6.9980,45.80,6.0622,3,222.0,18.70,394.63,2.94,33.40
- 0.06905,0.00,2.180,0,0.4580,7.1470,54.20,6.0622,3,222.0,18.70,396.90,5.33,36.20
- ...
まず、load_dataset() 関数を更新して、住宅データセットをロードします。データセットをロードする一環として、ターゲット値を正規化します。浮動小数点値を 0 ~ 1 の範囲に制限できるため、ヒルクライムの予測がはるかに簡単になります。これは通常必要ありません。検索アルゴリズムを簡素化するための方法にすぎません。 - # 分類データセットをロードまたは準備する
- def load_dataset():
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- df = read_csv (url、ヘッダー=なし)
- データ= df.values
- X, y =データ[:, :-1]、データ [:, -1]
- # ターゲットを正規化する
- スケーラー=最小最大スケーラー()
- y y = y.reshape((len(y), 1))
- y =スケーラー.fit_transform (y)
- X, yを返す
次に、期待値と予測値の間の平均絶対誤差を使用するようにスコアリング関数を更新できます。 - # 一連の予測を評価する
- 予測を評価する定義(y_test, yhat):
- 平均絶対誤差(y_test, yhat)を返す
また、ソリューションの表現を 0 と 1 のラベルから 0 と 1 の間の浮動小数点値に更新する必要があります。ランダムな浮動小数点数のリストを作成するには、初期候補ソリューションの生成を変更する必要があります。 - # ランダムな予測セットを作成する
- 定義: ランダム予測(n_examples):
- [_ の範囲内(n_examples)] のランダムな値を返します。
この場合、新しい候補ソリューションを作成するためにソリューションに加えられる単一の変更は、リスト内のランダムに選択された予測を新しいランダムな浮動小数点数に置き換えることだけです。シンプルだから選びました。 - # 現在の予測セットを変更する
- 変更予測を定義します(現在、 n_changes = 1 ):
- # 現在のソリューションをコピー
- 更新=現在の.copy()
- i が範囲内(n_changes)の場合:
- # 変更するポイントを選択
- ix = randint (0, len(更新)-1)
- # クラスラベルを反転する
- 更新[ix] = ランダム()
- 返品が更新されました
より良いアプローチとしては、既存の値にガウスノイズを追加することですが、これは拡張機能として残しておきます。試してみたら、下のコメント欄で教えてください。例えば: - # ガウスノイズを追加
- 更新[ix] += ガウス(0, 0.1)
最後に、検索を更新する必要があります。最適値はエラー 0.0 となり、エラーが見つかった場合に検索を停止するために使用されます。 - # 最高スコアを達成したら停止します
- スコア== 0.0 の場合:
- 壊す
また、検索を最大スコアから最小スコアに変更する必要があります。 - # 同じかそれ以上か確認する
- 値< = スコアの場合:
- 解決策、スコア=候補、値
- print(' > %d,スコア=%.3f' % (i, スコア))
これら 2 つの変更を加えた更新された検索機能を以下に示します。 - # 一連の予測のためにヒルクライムを実行する
- hill_climb_testset(X_test、y_test、最大反復回数)を定義します。
- スコア=リスト()
- # 初期ソリューションを生成する
- 解=ランダム予測(X_test.shape[0])
- # 初期ソリューションを評価する
- スコア=予測評価(y_test, 解)
- print(' > %.3f' % スコア)
- # 解決への道
- i が範囲内(max_iterations)の場合:
- # 記録的なスコア
- スコア.append(スコア)
- # 最高スコアを達成したら停止します
- スコア== 0.0 の場合:
- 壊す
- # 新しい候補を生成する
- 候補=予測を修正(解決策)
- # 候補者を評価する
- 値=予測評価(y_test, 候補)
- # 同じかそれ以上か確認する
- 値< = スコアの場合:
- 解決策、スコア=候補、値
- print(' > %d,スコア=%.3f' % (i, スコア))
- リターンソリューション、スコア
これらすべてをまとめると、回帰タスクのテスト セット ヒル クライミングの完全な例が以下になります。 - # 住宅データセットのテストセットの山登りの例
- ランダムインポートからランダム
- ランダムインポートrandint
- pandasからread_csvをインポートする
- sklearn.model_selection から train_test_split をインポートします
- sklearn.metricsからmean_absolute_errorをインポートします
- sklearn.preprocessing から MinMaxScaler をインポートします
- matplotlibからpyplotをインポートする
- # 分類データセットをロードまたは準備する
- def load_dataset():
- url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/housing.csv'
- df = read_csv (url、ヘッダー=なし)
- データ= df.values
- X, y =データ[:, :-1]、データ [:, -1]
- # ターゲットを正規化する
- スケーラー=最小最大スケーラー()
- y y = y.reshape((len(y), 1))
- y =スケーラー.fit_transform (y)
- X, yを返す
- # 一連の予測を評価する
- 予測を評価する定義(y_test, yhat):
- 平均絶対誤差(y_test, yhat)を返す
- # ランダムな予測セットを作成する
- 定義: ランダム予測(n_examples):
- [_ の範囲内(n_examples)] のランダムな値を返します。
- # 現在の予測セットを変更する
- 変更予測を定義します(現在、 n_changes = 1 ):
- # 現在のソリューションをコピー
- 更新=現在の.copy()
- i が範囲内(n_changes)の場合:
- # 変更するポイントを選択
- ix = randint (0, len(更新)-1)
- # クラスラベルを反転する
- 更新[ix] = ランダム()
- 返品が更新されました
- # 一連の予測のためにヒルクライムを実行する
- hill_climb_testset(X_test、y_test、最大反復回数)を定義します。
- スコア=リスト()
- # 初期ソリューションを生成する
- 解=ランダム予測(X_test.shape[0])
- # 初期ソリューションを評価する
- スコア=予測評価(y_test, 解)
- print(' > %.3f' % スコア)
- # 解決への道
- i が範囲内(max_iterations)の場合:
- # 記録的なスコア
- スコア.append(スコア)
- # 最高スコアを達成したら停止します
- スコア== 0.0 の場合:
- 壊す
- # 新しい候補を生成する
- 候補=予測を修正(解決策)
- # 候補者を評価する
- 値=予測評価(y_test, 候補)
- # 同じかそれ以上か確認する
- 値< = スコアの場合:
- 解決策、スコア=候補、値
- print(' > %d,スコア=%.3f' % (i, スコア))
- リターンソリューション、スコア
- # データセットをロードする
- X, y = load_dataset ()
- print(X.shape, y.shape)
- # データセットをトレーニングセットとテストセットに分割する
- X_train、X_test、y_train、 y_test = train_test_split (X、y、 test_size = 0.33 、 random_state = 1 )
- 印刷(X_train.shape、X_test.shape、y_train.shape、y_test.shape)
- # ヒルクライムを走る
- yhat、スコア= hill_climb_testset (X_test、y_test、100000)
- # スコアと反復回数をプロットする
- pyplot.plot(スコア)
- pyplot.show()
例を実行すると、検索中に改善が見られるたびに反復回数と MAE が報告されます。 この場合、最適化するのはより複雑な問題なので、より多くの反復処理を使用します。候補ソリューションを作成するために選択された方法により、処理速度が遅くなり、完全なエラーが達成される可能性も低くなります。実際には、完全なエラーは達成されません。代わりに、エラーが最小値 (例: 1e-7) を下回る値、またはターゲット ドメインに適した値に達した場合に停止するのが最善です。これも読者の練習問題として残しておきます。例えば: - # 十分な成果が得られたら停止します
- スコア< = 1e-7 の場合:
- 壊す
注意: アルゴリズムや評価手順の確率的特性、または数値精度の違いにより、結果が異なる場合があります。例を複数回実行し、平均結果を比較することを検討してください。 この場合、実行の最後に適切なエラーが達成されていることがわかります。 - > 95991 、スコア= 0.001
- > 96011 、スコア= 0.001
- > 96295 、スコア= 0.001
- > 96366 、スコア= 0.001
- > 96585 、スコア= 0.001
- > 97575 、スコア= 0.001
- > 98828 、スコア= 0.001
- > 98947 、スコア= 0.001
- > 99712 、スコア= 0.001
- > 99913 、スコア= 0.001
検索の進行状況を示す折れ線グラフも作成され、収束が速く、ほとんどの反復で一定のままであることが示されます。 |