ML Boot Camp IIIの受賞者

こんにちは この記事では、mail.ruのML Boot Camp III機械学習コンテストで1位になったソリューションについて簡単に説明したいと思います。



私は自己紹介をします。私の名前はミハイル・カラチュンです。以前のmail.ruコンテストの勝者でもあります。 私の過去の決断はここに記述されており、時々それを参照します。



条件



選択したデータに基づいて、競争の参加者は、オンラインゲームをプレイしたプレーヤーが離脱する可能性を予測するように求められました。 サンプルには、2週間にわたるプレーヤーのアクティビティに関するデータが含まれていました。 ログロスがメトリックとして選択されました。これは、コンテストWebサイトのタスクの詳細な説明です。



エントリー



各機械学習のコンテストには、参加者に提供されるデータのサンプルに依存する独自の詳細があります。 クリーンアップしてサインに変換する必要がある生ログの巨大なテーブルにすることができます。 特性を生成する必要があるさまざまなテーブルを備えたデータベース全体にすることもできます。 私たちの場合、データは非常に少なく(25k行、12列)、ギャップやエラーはありませんでした。 これに基づいて、次の仮定が行われました。





つまり、データの適切な依存関係を見つけるのが難しく、単一のモデルではなく、モデルのアンサンブルで最適なソリューションが構成される競争であると想定されていました。 そしてそれが起こった。



少し叙情的な余談。 ほとんどの受賞した機械学習コンテストは、実際のシステムには適していません。 少なくともNetflixでよく知られている事例を取り上げると、彼らは実装できないソリューションに対して100万ドルを支払いました。 したがって、このような競技の最終モデルは、1つの小説を思い起こさせます。 彼の名前「モダンプロメテウス」の2番目の部分は、人々に火と知識をもたらしました。 もちろん、最初の部分はフランケンシュタインです。



基本的な解決策



基本的な解決策として、xgboostを使用しました。これは、hyperoptを介してパラメーターを最適化した後、すぐに0.3825リーダーボードで結果を生成しました。 次に、機能エンジニアリングに進みました。



たとえば、多くの特徴の分布が対数分布に似ていることに気づいたので、それらの対数をベース列に追加しました(またはlog(x + 1))。



画像






次に、2つの列のすべての可能な組み合わせからさまざまな関数を生成し、それらが結果に与える影響を確認しました。 このタスクの一環として、データ量が許すので単純に整理する方がはるかに高速であるため、「解釈された」兆候を思い付くのは無意味なように思えました。 たとえば、さまざまな記号の違いによって良い結果が得られ、同じxgboostで0.3819を取得できるようになりました。



前の記事でパラメーターの最適化と列の選択について読むことができます。



最初のトラブル



チャンピオンシップの最初の段階ですでに決定を確認したところ、リーダーボード上のスコアの変化は、ローカルスコアの変化とあまり一致していませんでした。 新しい列を生成すると、ローカル交差検証の対数損失は着実に減少し、リーダーボード上で成長し、テスト用のサンプルのローカルパーティション分割のパラメーターの変更は助けになりませんでした。 コンテストの一般的なチャットを観察すると、ローカル推定値の平均と分散に関係なく、多くの参加者がこの問題に直面していることに気付くことができました。 これは、モデルのアンサンブルを作成することを支持する別の兆候でした。



もっと木...



同じ列のセット(その時点で70個を取得)で、さらに2つのグラデーションツリーのアンサンブルを作成しましたが、他のライブラリ-sklearnとlightgbmから作成しました 。 トレーニングは次のとおりでした。最初に各モデルを個別に調整して最良の結果を出し、次に平均を取り、すべてのモデルの結果を保存して順番に調整しましたが、自分の最良の結果ではなく、3つのモデルのアンサンブルで最良の結果を得るために調整しました。 これにより、リーダーボードで約0.3817が得られました。



回帰



同じアルゴリズムの異なる実装でも、アンサンブル全体で平均化すると最良の結果が得られるという事実にもかかわらず、異なるアルゴリズムを組み合わせる方がはるかに効率的です。

そのため、ロジスティック回帰が一般的なアンサンブルに追加されました。 モデルは過去のものと同じ方法で作成されました-可能なすべてのサインを生成し、再帰的に最良のサインを選択して残します。 ここで私は失望しました。 ローカル回帰はxgboostよりも優れていました! リーダーボードでは、スコアは0.383でした。 長い間、私はこれに苦労し、トレーニングとテストサンプルで異なる分布のサインを捨て、さまざまな正規化方法を試し、サインを間隔に分割しようとしました-何も助けませんでした。 しかし、この結果でも、アンサンブルに回帰を追加すると有用であることが判明しました-結果は約0.3816です



ニューラルネットワーク



線形回帰は良い結果を示したため、ニューラルネットワークを試す価値があります。 標準の最適化アルゴリズムをニューロンネットワークの構造に適用すると、非常に弱い結果が得られるため、十分な時間を費やしました。 その結果、リグレッションとほぼ同じようにリーダーボードに表示される適切な構成が見つかりました。 kerasライブラリは実装に使用されました。ここでは構造を示しません。最終ファイルで見つけることができます。私を大いに助けたコードの小さな例を示します。 交差検証により、モデルの結果は研究のエポック数に大きく依存することが示されました。 学習率を下げることができます-しかし、結果が悪化し、減衰の設定に成功しませんでした-結果も悪化しています。 その後、トレーニングの途中で学習率を変更することにしました。



from keras.callbacks import Callback as keras_clb class LearningRateClb(keras_clb): def on_epoch_end(self, epoch, logs={}): if epoch ==300: self.model.optimizer.lr.set_value(0.01)
      
      





アンサンブルに追加した後の結果は、約0.3815の結果です。



他のモデルの神モデル



上記のモデルはすべて、ほぼ同じ列に基づいて構築されています-基本機能とその対数に基づいて生成されました。 また、ベース列とその平方根に基づいて属性を生成しようとしました。 それも助けになりました-さらに2つのグラデーションツリーのアンサンブルが追加されました。 そのようなセットが最終的になりました:回帰、ニューラルネットワーク、および5つの勾配ツリーの集合。 結果は約0.3813です



サンプル分析



アンサンブルへの重要な追加は、出荷前のモデルの全体的な結果のわずかな変更です。 トレーニングセットには、まったく同じ特性を持つ文字列の大きなグループがあることがわかりました。 また、ログロスにより確率を最適化することが推奨されるため、これらのグループのモデル結果をトレーニングサンプルで計算された平均値に置き換えることは論理的です。 これは、要素が50を超えるグループに対して行われました。 結果は約0.3809です



あきらめたアイデア



スタッキング。 非常に多くのモデルで、単純な算術平均よりもモデルを平均化するためのより良い関数を考えることができるようです。 たとえば、結果を別のモデルに入れることができます。 ローカルの結果がリーダーボードとあまり一致せず、最も単純なタイプのスタッキングでさえ機能しなかったため、私はこのアイデアを拒否しました-加重平均。



結果の手動変更。 トレーニングサンプルには、結果が厳密に1または厳密に0であるサブグループがありました。たとえば、14日間プレイしたすべてのプレーヤーなどです。 ここでは、もちろん、そのような値に対してloglossがどれだけ罰するかを覚えておく価値がありました;使用する場合、100以上の場所が失われる可能性があります。



また、最後の瞬間まで、モデル間にはまだランダムなフォレストがありましたが、最終的にはパブリックスコアに基づいて除外しましたが、後で判明したように、プライベートスコアではそれを持つモデルが最良の結果を示しました。



その結果、主催者に本当に感謝したいと思います! ここで、ソリューションのソースコードを確認できます。



All Articles