コンペティションルール
■Open Review Competition
本コンペでは、開催期間終了後 賞金対象者のコードを公開し、ユーザーの皆様にチーティング有無をレビューしていただき順位確定させる、オープンレビュー方式のコンペティションを行います。
賞金対象ユーザー
コンペ終了後1週間以内:
トピックにて、学習過程の分かるコードの公開をお願いいたします。
(簡易解説までつけていただけると助かります。)
コード公開後1週間:
レビュアー(ユーザー)より、チーティングの疑いに関するコメントがある場合は、ご回答をお願いいたします。
※チーティングとは無関係のコメント(ノウハウに関する質疑 等)についてもご回答いただけると幸いですが、順位確定の判断材料とは致しません。
レビュアー(ユーザーの皆様)
コード公開後1週間:
公開コードを確認いただき、チーティングが疑われる場合は、トピックを通して質疑の投稿をお願いいたします。
レビュアーからの質疑と、回答状況をふまえて、最終的に運営側で順位確定を判断します。
■順位決定ロジック
- コンペ期間中はPublicリーダーボード(以下LB)により暫定評価を、最終結果についてはPrivate LBにより評価します。
※ Private LBはコンペ終了と同時に表示されます
- スコアが同値の場合は、早い日時に提出いただいたユーザーが上位となります。
- コンペ終了後であっても、不正が発覚の際は、対象ユーザーは失格となり、全体の順位が繰り上がります。
順位繰上げにより賞金対象者となられた場合は、繰上げ日より一週間以内に、トピックにてコードを公開いただき、「Open Review Competition」と同様のフローにて順位を確定させていただきます。
■タイムライン
開始日 2020/8/19 17:00 JST
終了日 2020/10/18 24:00 JST
エントリー締め切り なし
■システム利用
- 参加者ごとに1つのアカウントでご参加ください
- チーム参加の場合は、最大5名までエントリー可能です
- 1日あたり、最大5回までの提出が可能です
■禁止事項
- ユーザー間での情報共有
コンペティションに関連するコード・データを、チーム外のユーザーと共有することはできません。全参加者が利用できる場合に限り、共有可能です。
- 外部データの使用
本コンペティションの基本情報/データから取得できるデータのみを用いてチャレンジして下さい。コンペ外データを用いて学習されたモデルの使用も禁止とします。
ただし、トピック上で、運営より承認された外部データのみ、活用を許可いたします。承認プロセスについては、「外部データの活用申請について」をご確認ください。
※コンペ期間中であっても、不正が疑われる場合は、運営より確認のためメール連絡させていただくことがございます。一週間以内にご回答いただけない場合も、不正と判断させていただきます。
■外部データの使用申請について
原則外部データ使用は禁止としておりますが、正解データの入手につながらない場合は、下記承認プロセスにより使用できることといたします
- トピックを作成し、取得元情報とデータ(格納先URLも可)を添付
- 運営にて判断・承認
注)ただし、コンペ終了まで10日をきってからの申請は禁止とします
■運営からのお願い
公平性の担保、チーティング等の不正防止のため、予告なくルールの追加・変更を行う場合がございます。
ご不便をおかけすることもあるかと思いますが、サービス向上のためご了承ください。
「対戦ゲームデータ分析甲子園」コンペティション参加規約
コンペティションへの参加に際しては、ProbSpace利用規約(以下、「利用規約」といいます。)に加え、本ProbSpace参加規約(以下「本規約」といいます。)に同意いただく必要があります。利用規約にて定義された用語は、本規約においても同様の意味で用いられるものとします。
第1条(適用)
- 参加者(第2条に定義します。)は、コンペティションに参加した時点で、本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールの一切に同意したものとみなされます。
- 本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールは、コンペティションの終了後も参加者に適用されます。
第2条(定義)
本規約において次の各用語の定義は、それぞれ以下に定めるとおりとします。
- 「本コンペ」とは、当社ウェブサイト上で開催されるAI開発又はデータ分析等に関するコンペティションのうち、本規約に紐づく特定のコンペティションを意味します。
- 「主催者」とは、当社またはユーザーのうち、本コンペを主催する者を意味します。また、本コンペが、当社の顧客又は提携先の企業、学校その他の団体等がスポンサードするものである場合は、当該団体等も主催者の定義に含まれます。
- 「参加者」とは、ユーザーのうち、主催者側以外の立場で本コンペに参加する方を意味します。
- 「成果物」とは、本コンペにおいて参加者により開発される学習済みモデル、そのソースコード及び乱数シード等の設定値を意味します。
- 「入賞者」とは、当社より本コンペに入賞した旨の通知を受けた参加者を意味します。
- 「知的財産権」とは、著作権(著作権法第27条及び第28条に定める権利を含みます。)、特許権、実用新案権、商標権、意匠権、その他のノウハウ及び技術情報等の知的財産権(それらの権利を取得し、又はそれらの権利につき登録等を出願する権利を含みます。)を意味します。
第3条(権利の帰属)
- 本コンペで発生した成果物に関する知的財産権は、参加者に帰属します。
第4条(入賞者の義務)
- 入賞者は、本コンペで公開した成果物を、MITライセンスを適用し、商用利用の許諾条項及び著作権人格権の包括的不行使条項をライセンス条項に付与した形式で、オープンソースソフトウェアとして公開する義務を負うものとします。その前提として、入賞者は、成果物について本項に基づく方法でオープンソース化する権利を有していることを当社に対して表明保証するものとします。
※第三者が、授業・研修・セミナー等で活用できるようにするための規約となります。ご理解のほどよろしくお願いいたします。
- 当社は、以下の3点の確認が完了した時点で、本コンペの賞金または商品を、入賞者に対して授与するものとします。
- 入賞者が、前項に基づいて成果物のオープンソース化を実施したこと
- 入賞者が、本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールの一切に違反していないこと
- 当社が定める方法による本人確認
- 当社は、入賞者が第1項に基づいてオープンソース化した成果物を、自由に商用利用することができます。
第5条(禁止事項)
- 参加者は、本コンペにおいて、以下の各号のいずれかに該当する行為を行ってはならないものとします。
- クラッキングやチート行為、なりすまし、盗用等の不正行為
- 第三者の知的財産権その他の権利を侵害する内容ないし態様で、参加者公開事項を公開する行為
- 主催者(当社以外の者に限ります。)に対する直接連絡、相談、依頼、勧誘、勧誘対応等の活動(但し、当社を介して当社が認めた方法により行うものは除きます。)
- 本コンペにおいて、当該コンペと直接関係のない成果物等を提出すること
- 本規約における参加者としての地位又は参加者としての権利義務について、譲渡、移転、担保設定、その他の処分をすること
- その他、本規約、参加ルール及び利用規約に違反する行為
- 参加者が前項に規定する禁止行為を行ったと当社が認める場合、当社は、当該参加者に事前に通知することなく、当該参加者の本コンペにおける失格処分、当社サービスの全部又は一部の利用停止、ユーザー登録の抹消、その他当社が必要と判断した措置をとることができるものとします。
第6条(本コンペの変更、中断、終了等)
- 当社は、参加者に事前の通知をすることなく本規約に基づく本コンペの開催内容の変更、本コンペの一時的な中断又は終了を行うことができます。
- 当社は、本条に基づき当社が行った措置により生じた結果及び損害について、一切の責任を負わないものとします。
第7条(損害賠償)
- 参加者は、本コンペに関連して、自らの責に帰すべき事由により、当社、主催者その他の第三者に損害を与えた場合には、その一切の損害(逸失利益、弁護士費用を含みます。)を賠償するものとします。
- 参加者が本規約の規定に違反したことにより主催者(当社を除きます。)その他の第三者が当社に対して何らかの訴え、異議、請求等がなされた場合において、当社から処理の要請がなされたときは、参加者は自己の責任と費用負担において、当社に代わって当該第三者との紛争を処理するとともに、当社がかかる訴え、異議、請求等により被った一切の損害(逸失利益、弁護士費用を含みます。)を賠償するものとします。
第8条(本規約の変更)
当社は、必要と判断した場合には、参加者に対して事前に通知する(本コンペにかかる当社ウェブサイト上での告知その他当社が適当と認める方法を含みます。)ことにより、いつでも本規約を変更することができるものとします。なお、変更内容の通知後、参加者が当社の定める期間内に本コンペへの参加を取り消す手続をとらなかった場合には、当該参加者は変更後の規約に同意したものとみなされます。当社は、本規約の変更により参加者に生じたすべての損害について一切の責任を負いません。
第9条(その他)
本契約の準拠法は日本法とし、本契約に起因し又は関連する一切の紛争については、当社の本店所在地を管轄する裁判所を第一審の専属的合意管轄裁判所とします。
(制定)2020年6月22日
概要
このチュートリアルでは、オンラインゲームの対戦データに対して
- データの読み込み
- データの確認と前処理
- Scikit-Learnを用いてRandomForestによる分類モデルの作成,学習
- 提出用データの作成
を行います。
import pandas as pd
import numpy as np
import sklearn
!python3 --version
print(pd.__version__)
print(np.__version__)
print(sklearn.__version__)
import matplotlib
print(matplotlib.__version__)
Python 3.7.3
0.25.3
1.17.4
0.22
3.1.1
環境
- python 3.7.3
- pandas 0.25.3
- sklearn 0.22
- numpy 1.17.4
- matplotlib 3.1.1
データのロード
まずはデータを読み込んで見ましょう。csvデータの読み込みは複数のやり方がありえますが、pandas
のread_csv
関数はその中でも機能が豊富で、扱いやすいためこれを使います。
これを使うと、csvデータを読み込み、pandas.DataFrame
にして返してくれます。
import pandas as pd
train_data = pd.read_csv("train_data.csv", index_col='id')
print(train_data.shape)
(66125, 31)
また、DataFrame
には.head()
というメソッドが定義されており、これを呼び出すとDataFrame
の先頭の数行を確認できます。
train_data.head()
id |
period |
game-ver |
lobby-mode |
lobby |
mode |
stage |
A1-weapon |
A1-rank |
A1-level |
A2-weapon |
... |
B2-weapon |
B2-rank |
B2-level |
B3-weapon |
B3-rank |
B3-level |
B4-weapon |
B4-rank |
B4-level |
y |
1 |
2019-10-15T20:00:00+00:00 |
5.0.1 |
regular |
standard |
nawabari |
sumeshi |
sshooter_becchu |
NaN |
139 |
soytuber_custom |
... |
hokusai_becchu |
NaN |
26.0 |
herocharger_replica |
NaN |
68.0 |
sharp_neo |
NaN |
31.0 |
1 |
2 |
2019-12-14T04:00:00+00:00 |
5.0.1 |
regular |
standard |
nawabari |
arowana |
parashelter_sorella |
NaN |
198 |
jetsweeper |
... |
squiclean_b |
NaN |
118.0 |
campingshelter |
NaN |
168.0 |
sputtery_clear |
NaN |
151.0 |
0 |
3 |
2019-12-25T14:00:00+00:00 |
5.0.1 |
gachi |
standard |
hoko |
ama |
nzap89 |
a- |
114 |
quadhopper_black |
... |
nzap85 |
a+ |
163.0 |
prime_becchu |
a- |
160.0 |
dualsweeper_custom |
a |
126.0 |
0 |
4 |
2019-11-11T14:00:00+00:00 |
5.0.1 |
regular |
standard |
nawabari |
engawa |
bamboo14mk1 |
NaN |
336 |
splatroller_becchu |
... |
liter4k |
NaN |
189.0 |
promodeler_mg |
NaN |
194.0 |
hotblaster_custom |
NaN |
391.0 |
0 |
5 |
2019-12-14T06:00:00+00:00 |
5.0.1 |
gachi |
standard |
hoko |
chozame |
bold_7 |
x |
299 |
hissen_hue |
... |
sputtery_hue |
x |
45.0 |
bucketslosher_soda |
x |
246.0 |
wakaba |
x |
160.0 |
1 |
5 rows × 31 columns
データの確認と前処理
訓練データにおける勝敗の比率がどのようになっているか見てみましょう。
np.sum(train_data['y'] == 1) / train_data['y'].count(), np.sum(train_data['y'] == 0) / train_data['y'].count()
(0.524703213610586, 0.47529678638941397)
このデータでは少しAチームの勝利数が多いようです.
続いて、下記のコードを使用して使用するデータ全体の概観を確認します。
各項目について欠損値以外('non-null')の値がどの程度含まれているか把握できます。また、データの形式についてもここで判別可能です。
train_data.info()
<class 'pandas.core.frame.DataFrame'>
Int64Index: 66125 entries, 1 to 66125
Data columns (total 31 columns):
period 66125 non-null object
game-ver 66125 non-null object
lobby-mode 66125 non-null object
lobby 66125 non-null object
mode 66125 non-null object
stage 66125 non-null object
A1-weapon 66125 non-null object
A1-rank 51681 non-null object
A1-level 66125 non-null int64
A2-weapon 66125 non-null object
A2-rank 51681 non-null object
A2-level 66125 non-null float64
A3-weapon 66125 non-null object
A3-rank 51681 non-null object
A3-level 66125 non-null float64
A4-weapon 66074 non-null object
A4-rank 51638 non-null object
A4-level 66074 non-null float64
B1-weapon 66125 non-null object
B1-rank 51681 non-null object
B1-level 66125 non-null int64
B2-weapon 66125 non-null object
B2-rank 51681 non-null object
B2-level 66125 non-null float64
B3-weapon 66124 non-null object
B3-rank 51681 non-null object
B3-level 66124 non-null float64
B4-weapon 66058 non-null object
B4-rank 51624 non-null object
B4-level 66058 non-null float64
y 66125 non-null int64
dtypes: float64(6), int64(3), object(22)
memory usage: 16.1+ MB
データの形式を見ると、数値についてはfloat64/int64
型になっていることが確認できます。
A1-weapon
、A2-weapon
、A3-weapon
、A4-weapon
、B1-weapon
、B2-weapon
、B3-weapon
、B4-weapon
は文字列で武器の名前が書かれているようです。A4-weapon
、B3-weapon
、B4-weapon
については少しですがnull
のデータがありました。
予測モデルの作成,学習
モデルに投入する目的変数(y),説明変数(X)を作成します
from sklearn.preprocessing import MultiLabelBinarizer
mlb = MultiLabelBinarizer()
mlb.fit([set(train_data['A1-weapon'].unique())])
MultiLabelBinarizer(classes=None, sparse_output=False)
def trans_weapon(df, columns=['A1-weapon', 'A2-weapon', 'A3-weapon', 'A4-weapon']):
weapon = df.fillna('none')
weapon_binarized = mlb.transform(weapon[columns].values)
return pd.DataFrame(weapon_binarized, columns=mlb.classes_)
def make_input_output(df, with_y=False):
a_weapon = trans_weapon(df, ['A1-weapon', 'A2-weapon', 'A3-weapon', 'A4-weapon'])
b_weapon = trans_weapon(df, ['B1-weapon', 'B2-weapon', 'B3-weapon', 'B4-weapon'])
X = pd.concat([a_weapon, b_weapon], axis=1)
if with_y:
y = df['y']
return X, y
return X
make_input_output
関数ではAチーム、Bチームのそれぞれでいずれかのメンバーがある武器を利用しているかを表すデータを作成しています。
これはsklearn
のMultiLabelBinarizer
という機能を用いることで作成できます。単にカテゴリカルデータではなく、一つのレコードが複数のカテゴリカルに属する可能性があるデータでは活用できるでしょう。
X, y = make_input_output(train_data, with_y=True)
/usr/local/lib/python3.7/site-packages/sklearn/preprocessing/_label.py:987: UserWarning: unknown class(es) ['none'] will be ignored
.format(sorted(unknown, key=str)))
いよいよ予測モデルの作成に入ります。
model.fit('説明変数','目的変数')
と記述することでモデルの学習が可能となります。目的変数を説明変数の組み合わせで説明可能な回帰モデルを作成できます。
import sklearn
from sklearn.ensemble import RandomForestClassifier
model = RandomForestClassifier()
model.fit(X, y)
RandomForestClassifier(bootstrap=True, ccp_alpha=0.0, class_weight=None,
criterion='gini', max_depth=None, max_features='auto',
max_leaf_nodes=None, max_samples=None,
min_impurity_decrease=0.0, min_impurity_split=None,
min_samples_leaf=1, min_samples_split=2,
min_weight_fraction_leaf=0.0, n_estimators=100,
n_jobs=None, oob_score=False, random_state=None,
verbose=0, warm_start=False)
分類モデルの評価
list(reversed(sorted(list(zip(model.feature_importances_, X.columns)))))[:10]
[(0.013357165181876553, 'prime_becchu'),
(0.011443964257055605, 'splatroller'),
(0.010996128432155314, 'nzap85'),
(0.01082213018002065, 'splatroller'),
(0.010276424036862188, 'nzap89'),
(0.010195469546078965, 'prime_becchu'),
(0.01001466293689794, 'wakaba'),
(0.009995963033009037, 'wakaba'),
(0.009555699489158472, 'nzap89'),
(0.009123588414361871, 'dualsweeper_custom')]
RandomForestではfeature_importances_
で特徴量の重要度を取得することができます。
重要度が大きな10つのカラムは以上の通りになります。
モデルの評価
テストデータに対する回帰モデルの当てはまりの良さの指標としては'決定係数'などの指標が用いられます。
決定係数の値は、.score
で確認が可能です。
1に近いほど回帰式で予測された値が実際のデータに当てはまることを表します。
また、コンペの評価指標となるaccuracy
についても出力が可能です。
今回は、sklearn.metrics
に含まれるaccuracy_score
メソッドを使用します。
accuracyは予測した出力のうち正答した割合を示す指標であり、1に近いほど予測精度が高いことを表します。
モデルを元にした予測値は、model.predict('説明変数')
で表します。
from sklearn.metrics import accuracy_score
y_true = y
y_pred = model.predict(X)
print(accuracy_score(y_true, y_pred))
0.9999848771266541
今回作成したモデルのaccuracyは99.9%程度でした。
テストデータに対する出力
最後に、作成したモデルを使用してテストデータでの勝敗を予測します。
テストデータの説明変数については予め、上記でモデルに学習させたデータの説明変数と同様の前処理をする必要があります。
path_test = "test_data.csv"
test_data = pd.read_csv(path_test, index_col='id')
test_data.head()
id |
period |
game-ver |
lobby-mode |
lobby |
mode |
stage |
A1-weapon |
A1-rank |
A1-level |
A2-weapon |
... |
B1-level |
B2-weapon |
B2-rank |
B2-level |
B3-weapon |
B3-rank |
B3-level |
B4-weapon |
B4-rank |
B4-level |
1 |
2019-12-17T12:00:00+00:00 |
5.0.1 |
gachi |
standard |
area |
hakofugu |
prime_collabo |
x |
174 |
herospinner_replica |
... |
160 |
nautilus47 |
x |
151.0 |
l3reelgun_d |
x |
213.0 |
nzap89 |
x |
306.0 |
2 |
2019-11-25T16:00:00+00:00 |
5.0.1 |
gachi |
standard |
asari |
anchovy |
prime_becchu |
s+ |
363 |
nzap89 |
... |
326 |
dualsweeper_custom |
s+ |
289.0 |
prime_becchu |
s+ |
147.0 |
splatroller |
s+ |
156.0 |
3 |
2019-10-22T08:00:00+00:00 |
5.0.1 |
gachi |
standard |
area |
mutsugoro |
furo_deco |
s |
116 |
bold |
... |
76 |
momiji |
s |
232.0 |
nzap83 |
s |
183.0 |
promodeler_pg |
s |
105.0 |
4 |
2019-12-30T04:00:00+00:00 |
5.0.1 |
gachi |
standard |
asari |
devon |
prime_becchu |
s+ |
192 |
splatspinner_collabo |
... |
90 |
quadhopper_black |
s+ |
119.0 |
soytuber |
s+ |
172.0 |
prime |
s+ |
70.0 |
5 |
2019-10-15T16:00:00+00:00 |
5.0.1 |
gachi |
standard |
yagura |
anchovy |
l3reelgun_d |
x |
267 |
rapid_becchu |
... |
259 |
sshooter_becchu |
x |
198.0 |
splatscope |
x |
50.0 |
screwslosher_becchu |
x |
287.0 |
5 rows × 30 columns
test_X = make_input_output(test_data)
/usr/local/lib/python3.7/site-packages/sklearn/preprocessing/_label.py:987: UserWarning: unknown class(es) ['none'] will be ignored
.format(sorted(unknown, key=str)))
先ほど使用したmodel.predict('説明変数')
の'説明変数'にテストデータの値を代入することで、テストデータの予測値を算出することができます。
下記のようにして、提出用のsubmission.csv
を出力することが可能です。
test_predicted = model.predict(test_X)
submit_df = pd.DataFrame({'y': test_predicted})
submit_df.index.name = 'id'
submit_df.to_csv('submission.csv')