上記期間のstation_list.csvの情報に誤り、一部データの不足がございました。
正しいデータのカラムは、「station_name,longitude,latitude」の順であり、総データ件数は746件となります(大型の駅については、一部重複駅名あり)。
該当データをご使用されている方は、誠に恐れ入りますが、再ダウンロードいただけますと幸いです。
お手数おかけいたしますが、何卒よろしくお願いいたします。
民泊サービスは、2016年に国内で解禁されて以降、わずか5年後の2020年3月には取扱件数12.9万件に達するほど大きな市場となりました。
物件の所有者であれば誰でも始められる手軽さが、新規参入者にとってのメリットではありますが、宿泊事業の専門化ではない多くの民泊オーナーにとって、料金設定は常に悩みの種となっています。
こうした中、大手民泊仲介事業者のAirbnbは、宿泊価格の決定方法として、機械学習アルゴリズムにより価格を決定する「ダイナミックプライシング*1」を採用したことで注目を集めました。
近年では、Beyond Pricing、メトロエンジン 等 価格設定の最適化を専門とする企業が登場するほど、ダイナミックプライシングへの機械学習技術の貢献度は大きなものとなっております。
今回は、機械学習のテーマとしても王道とも呼べる、ダイナミックプライシングをテーマとしたコンペティションを設計いたしました。
皆さまには、国内2地区の宿泊施設を対象とした、最適な宿泊料金を算出するアルゴリズムの開発に取り組んでいただきます。
コンペを通して、民泊料金がどのように設定されているのか、裏側にある因子についても興味を持っていただければと存じます。
*1 ダイナミックプライシングとは?
ダイナミックプライシングは、需要・供給に応じて、利益を最大化させるよう商品・サービス価格を変動させる技術です。
民泊サービスにおいては、立地やサービス、季節、利用動向 等の情報により、宿泊価格の最適化が図られています。
他業界での適用範囲も広く、民泊サービスのほかにも、スーパーの商品価格、スポーツ観戦チケット、テーマパーク入園料 等様々な業界への導入が進んでおります。
初心者の方でも取り組みやすいテーブルデータコンペティション形式となります。
またやり込み要素として、駅の位置情報データを提供しております。上位入賞を目指される方は、ぜひ駅と宿泊施設の位置関係も特徴量に用いてみてください。
1位 100,000円
※ 対象者には、コンペティション終了後メールにて連絡いたします
2022年5月8日 22:00 JST
LB公開 5月8日 24:00 JST
データをダウンロードするにはログインまたはユーザー登録して下さい
コンペに使用するデータは4つに分けられます。
訓練データセットとテストデータセットには、それぞれ9,990レコードと4,996レコードのサンプルが含まれています。
また追加情報として、東京都23区内駅緯度経度データ(station_list.csv)をご利用もいただけます。
今回、提供している訓練データとテストデータは、2020年4月のある特定の日に取得したデータとなります。
テストデータセットに対して、同日における各宿泊施設の一泊あたりの宿泊料金を予測してください。
また、提出ファイルの例に関しては、評価方法のタグを参照してください。
データセットのカラムは以下の通りです。
カラム名 | 説明 | 例 |
---|---|---|
name | 施設名称 | Downtown next to Koji-Machi |
host_id | 施設の提供者の識別子(乱数化済) | 181893395 |
neighbourhood | 所在地(東京都の23の特別区のいずれか) | Shinjuku Ku |
latitude | 緯度 | 3568185 |
longitude | 経度 | 139.68077 |
room_type | 部屋の形式 (Entire home/apt|Private room|Shared room|Hotel room) | Entire home/apt |
minimum_nights | 最短宿泊日数 | 1 |
number_of_reviews | 評価件数 | 523 |
last_review | 最終評価日 | 2020-02-03 |
reviews_per_month | 月当たりの評価件数 | 1.67 |
availability_365 | 年間の宿泊可能日数 | 288 |
y | 1泊あたりの宿泊料金 | 9923 |
カラム名 | 説明 | 例 |
---|---|---|
station_name | 駅名 | 東京 |
longitude | 経度 | 139.766103 |
latitude | 緯度 | 35.681391 |
目標は、テストデータセットの宿泊施設の情報にもとづき、宿泊料金を予測することです。y(宿泊料金)を予測してくだい。
モデルの予測性能は評価関数RMSLE(Root Mean Squared Logarithmic Error)で評価されます。
$$
\sqrt{\frac{1}{n}{\sum_{i=1}^{n}{(\log (Pred_i+1)-\log (Act_i+1))^2}}}
$$
回答用のsubmission.csvを用意する(エントリーとヘッダー行を含む) 。
提出されたファイルに余分な行や列(idとy以外)が含まれていた場合はエラーとなります。
提出ファイルは以下の列のみを必ず含んでください:
id,y
1, 9181
2, 14831
3, 34000
4, 1388
本コンペでは、開催期間終了後 賞金対象者のコードを公開し、ユーザーの皆様からのチーティング有無のレビュー後に順位を確定させる、オープンレビュー方式のコンペティションを行います。
賞金対象ユーザー
コンペ終了後1週間以内:
トピックにて、学習過程の分かるコードの公開をお願いいたします。
(簡易解説までつけていただけると助かります。)
コード公開後1週間:
レビュアー(ユーザー)より、チーティングの疑いに関するコメントがある場合は、ご回答をお願いいたします。
※チーティングとは無関係のコメント(ノウハウに関する質疑 等)についてもご回答いただけると幸いですが、順位確定の判断材料とは致しません。
コード公開後1週間:
公開コードを確認いただき、チーティングが疑われる場合は、トピックを通して質疑の投稿をお願いいたします。
レビュアーからの質疑と、回答状況をふまえて、最終的に運営側で順位確定を判断します。
開始 2022/2/28 15:00 JST
提出締切 2022/5/8 22:00 JST
終了日 2022/5/8 24:00 JST
エントリー締め切り なし
※コンペ期間中であっても、不正が疑われる場合は、運営より確認のためメール連絡させていただくことがございます。一週間以内にご回答いただけない場合も、不正と判断させていただきます。
原則外部データ/学習済みモデルの使用は禁止としておりますが、正解データの入手につながらない場合は、下記承認プロセスにより使用できることといたします。
注)ただし、コンペ終了まで7日をきってからの申請は禁止とします。
また、下記ホワイトリストについては、申請不要で使用いただくことが可能です。
・ホワイトリスト
https://docs.google.com/spreadsheets/d/1yciWoubQ_JtJSFcsGTjqemNDUL3KccL52dBfCzvVIZA/edit#gid=0
※注意事項
・上記をラップしたツールキットは申請不要で使用可能
・データを追加し再学習されたモデルについては使用不可(要申請)
公平性の担保、チーティング等の不正防止のため、予告なくルールの追加・変更を行う場合がございます。
ご不便をおかけすることもあるかと思いますが、サービス向上のためご了承ください。
はい。
最も精度の高い学習モデルを作成した優勝者には、賞金10万円を贈呈します。
順位確定までのプロセスについては、ルール「Open Review Competition」を参照ください。
可能です。チームページから作成いただけます。
こちらから作成いただけます。
コンペティション参加にはアカウント登録が必要となりますのでご注意ください。
申請を行うことによって利用可能です。
ルール「外部データ/学習済みモデルの使用申請について」を参照ください。
Seed を固定することが推奨です。
ただし、Seed を固定しなくても提出用コードとしては認めています。
ファイル提出後、23時間ごとにリセットとなります。
グローバル展開していくにあたり、居住国(時差)による有利・不利を最小化するため、一定時間でリセットする仕様としております。
このチュートリアルでは、民泊の宿泊施設データに対して
を行います。
import pandas as pd
import numpy as np
import sklearn
!python3 --version
print("Pandas", pd.__version__)
print("Numpy", np.__version__)
print("Scikit learn", sklearn.__version__)
import matplotlib
print("Matplotlib", matplotlib.__version__)
Python 3.9.8
Pandas 1.3.0
Numpy 1.20.3
Scikit learn 0.24.2
Matplotlib 3.4.2
まずはデータを読み込んで見ましょう。csvデータの読み込みは複数のやり方がありえますが、pandas
のread_csv
関数はその中でも機能が豊富で、扱いやすいためこれを使います。
これを使うと、csvデータを読み込み、pandas.DataFrame
にして返してくれます。
#データの読み込みと前処理
import pandas as pd
train_data = pd.read_csv("../compe_data/train_data.csv", index_col='id')
print(train_data.shape)
(9990, 12)
また、DataFrame
には.head()
というメソッドが定義されており、これを呼び出すとDataFrame
の先頭の数行を確認できます。
train_data['room_type'].unique()
array(['Entire home/apt', 'Private room', 'Shared room', 'Hotel room'],
dtype=object)
train_data.head()
name | host_id | neighbourhood | latitude | longitude | room_type | minimum_nights | number_of_reviews | last_review | reviews_per_month | availability_365 | y | |
---|---|---|---|---|---|---|---|---|---|---|---|---|
id | ||||||||||||
1 | KiyosumiShirakawa 3min|★SkyTree★|WIFI|Max4|Tre... | 242899459 | Koto Ku | 35.68185 | 139.80310 | Entire home/apt | 1 | 55 | 2020-04-25 | 2.21 | 173 | 12008 |
2 | Downtown Tokyo Iriya next to Ueno | 308879948 | Taito Ku | 35.72063 | 139.78536 | Entire home/apt | 6 | 72 | 2020-03-25 | 2.11 | 9 | 6667 |
3 | Japan Style,Private,Affordable,4min to Sta. | 300877823 | Katsushika Ku | 35.74723 | 139.82349 | Entire home/apt | 1 | 18 | 2020-03-23 | 3.46 | 288 | 9923 |
4 | 4 min to Shinjuku Sta. by train / 2 ppl / Wi-fi | 236935461 | Shibuya Ku | 35.68456 | 139.68077 | Entire home/apt | 1 | 2 | 2020-04-02 | 1.76 | 87 | 8109 |
5 | LICENSED SHINJUKU HOUSE: Heart of the action! | 243408889 | Shinjuku Ku | 35.69840 | 139.70467 | Entire home/apt | 1 | 86 | 2020-01-30 | 2.00 | 156 | 100390 |
訓練データにおける一日あたりの宿泊料の分布がどうなっているのか見てみましょう。
import matplotlib.pyplot as plt
%matplotlib inline
plt.hist(train_data['y'], log=True, bins=20)
(array([9.357e+03, 4.600e+02, 4.200e+01, 2.400e+01, 6.000e+00, 5.100e+01,
1.000e+00, 0.000e+00, 0.000e+00, 5.000e+00, 0.000e+00, 0.000e+00,
0.000e+00, 1.000e+00, 0.000e+00, 1.000e+00, 0.000e+00, 3.500e+01,
4.000e+00, 3.000e+00]),
array([9.210000e+02, 5.088010e+04, 1.008392e+05, 1.507983e+05,
2.007574e+05, 2.507165e+05, 3.006756e+05, 3.506347e+05,
4.005938e+05, 4.505529e+05, 5.005120e+05, 5.504711e+05,
6.004302e+05, 6.503893e+05, 7.003484e+05, 7.503075e+05,
8.002666e+05, 8.502257e+05, 9.001848e+05, 9.501439e+05,
1.000103e+06]),
<BarContainer object of 20 artists>)
10,000円以下に大きなピークがあり、90,000円程度のところにも小さな峰があることがわかります。
続いて、下記のコードを使用して使用するデータ全体の概観を確認します。
各項目について欠損値('null')の値がどの程度含まれているか把握できます。また、データの形式についてもここで判別可能です。
train_data.isnull().sum(axis=0)
name 0
host_id 0
neighbourhood 0
latitude 0
longitude 0
room_type 0
minimum_nights 0
number_of_reviews 0
last_review 1699
reviews_per_month 1699
availability_365 0
y 0
dtype: int64
(train_data['number_of_reviews'] == 0).sum()
1699
カラムのうち欠損値が含まれているのはlast_review
とreviews_per_month
のようです。この2つのカラムがnullとなっているのはreviews
数が0となっているデータのようです。これらのカラムは宿泊施設の人気度の尺度になりそうです。
モデルに投入する目的変数(y),説明変数(X)を作成します
train_columns = ['neighbourhood', 'room_type', 'minimum_nights', 'number_of_reviews']
target = 'y'
X = pd.get_dummies(train_data[train_columns], drop_first=True)
y = train_data[target] / 10000
いよいよ予測モデルの作成に入ります。model.fit('説明変数','目的変数')
と記述することでモデルの学習が可能となります。目的変数を説明変数の組み合わせで説明可能な回帰モデルを作成できます。
#scikit-learnライブラリをimport
import sklearn
from sklearn.ensemble import RandomForestRegressor as RFR
#回帰モデルのインスタンス化
model = RFR()
#予測モデルの作成
result = model.fit(X, y)
score
メソッドを用いてモデルの評価を行うことができます。
model.score(X, y)
0.46400404613856716
テストデータに対する回帰モデルの当てはまりの良さの指標としては'決定係数'などの指標が用いられます。
決定係数の値は、.score
で確認が可能です。
1に近いほど回帰式で予測された値が実際のデータに当てはまることを表します。
また、コンペの評価指標となるRMSLE
についても出力が可能です。
今回は、sklearn.metrics
に含まれるmean_squared_log_error
メソッドとnp.sqrt
メソッドを使用します。
RMSLEは出力値と真値の差を表し、0に近いほど予測精度が高いことを表します。
モデルを元にした予測値は、model.predict('説明変数')
で表します。
# accuracyの出力
from sklearn.metrics import mean_squared_log_error
y_true = y
y_pred = model.predict(X)
print(np.sqrt(mean_squared_log_error(y_true, y_pred)))
0.483417271534843
今回作成したモデルのRMSLEは0.483程度でした。
最後に、作成したモデルを使用してテストデータでの取引金額を予測します。
テストデータの説明変数については予め、上記でモデルに学習させたデータの説明変数と同様の前処理をする必要があります。
path_test = "../compe_data/test_data.csv"
test_data = pd.read_csv(path_test, index_col='id')
test_data.head()
name | host_id | neighbourhood | latitude | longitude | room_type | minimum_nights | number_of_reviews | last_review | reviews_per_month | availability_365 | |
---|---|---|---|---|---|---|---|---|---|---|---|
id | |||||||||||
1 | 5-minute walk from Akasaka Sta, Superior double | 184730720 | Minato Ku | 35.67131 | 139.73285 | Private room | 1 | 0 | NaN | NaN | 183 |
2 | 7 min Sta.-Center of IKEBUKURO Cozy Room#503 | 20993205 | Toshima Ku | 35.73014 | 139.71739 | Entire home/apt | 2 | 21 | 2020-04-16 | 1.94 | 337 |
3 | Designer'sApt 1min sta☆Shinjuku 7min☆Shibuya 4min | 322521715 | Setagaya Ku | 35.66193 | 139.66540 | Entire home/apt | 1 | 14 | 2020-02-12 | 0.82 | 240 |
4 | Komagome Station 2 minutes on foot | 234477095 | Toshima Ku | 35.73603 | 139.74794 | Entire home/apt | 1 | 16 | 2020-02-17 | 1.19 | 0 |
5 | Monthly/Metro1min/JR5min/Ueno,Asakusa,Akihabara | 145453833 | Taito Ku | 35.72126 | 139.78320 | Entire home/apt | 30 | 2 | 2019-07-21 | 0.19 | 164 |
test_X = pd.get_dummies(test_data[train_columns], drop_first=True)
先ほど使用した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')
コンペティションへの参加に際しては、ProbSpace利用規約(以下、「利用規約」といいます。)に加え、本ProbSpace参加規約(以下「本規約」といいます。)に同意いただく必要があります。利用規約にて定義された用語は、本規約においても同様の意味で用いられるものとします。
第1条(適用)
第2条(定義)
本規約において次の各用語の定義は、それぞれ以下に定めるとおりとします。
第3条(権利の帰属)
第4条(入賞者の義務)
第5条(禁止事項)
第6条(本コンペの変更、中断、終了等)
第7条(損害賠償)
第8条(本規約の変更)
当社は、必要と判断した場合には、参加者に対して事前に通知する(本コンペにかかる当社ウェブサイト上での告知その他当社が適当と認める方法を含みます。)ことにより、いつでも本規約を変更することができるものとします。なお、変更内容の通知後、参加者が当社の定める期間内に本コンペへの参加を取り消す手続をとらなかった場合には、当該参加者は変更後の規約に同意したものとみなされます。当社は、本規約の変更により参加者に生じたすべての損害について一切の責任を負いません。
第9条(その他)
本契約の準拠法は日本法とし、本契約に起因し又は関連する一切の紛争については、当社の本店所在地を管轄する裁判所を第一審の専属的合意管轄裁判所とします。
(制定)2020年6月22日