民泊サービスの宿泊料金予測

一泊の適正価格はいくら?

賞金: 100,000 参加ユーザー数: 332 2年弱前に終了
※2022/2/28、3/1,2にデータダウンロードされた皆さま

上記期間の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つに分けられます。

  • 訓練データ(train_data.csv)
  • テストデータ(test_data.csv)
  • 東京都23区内駅緯度経度データ(station_list.csv)
  • サンプルサブミット用データ(submission.csv)

訓練データセットとテストデータセットには、それぞれ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)で評価されます。

  (RMSLEの評価値)

$$
\sqrt{\frac{1}{n}{\sum_{i=1}^{n}{(\log (Pred_i+1)-\log (Act_i+1))^2}}}
$$

  • 評価値は0以上の値をとり、精度が高いほど小さな値となります。

提出ファイルの形式

回答用のsubmission.csvを用意する(エントリーとヘッダー行を含む) 。
提出されたファイルに余分な行や列(idとy以外)が含まれていた場合はエラーとなります。

提出ファイルは以下の列のみを必ず含んでください:

  • id(テストデータセットと同じ順序)
  • y(予測された宿泊料金)

以下は提出ファイルの例です。
id,y
1, 9181
2, 14831
3, 34000
4, 1388
■Open Review Competition

本コンペでは、開催期間終了後 賞金対象者のコードを公開し、ユーザーの皆様からのチーティング有無のレビュー後に順位を確定させる、オープンレビュー方式のコンペティションを行います。

賞金対象ユーザー
コンペ終了後1週間以内:
トピックにて、学習過程の分かるコードの公開をお願いいたします。
(簡易解説までつけていただけると助かります。)

コード公開後1週間:
レビュアー(ユーザー)より、チーティングの疑いに関するコメントがある場合は、ご回答をお願いいたします。
※チーティングとは無関係のコメント(ノウハウに関する質疑 等)についてもご回答いただけると幸いですが、順位確定の判断材料とは致しません。

レビュアー(ユーザーの皆様)

コード公開後1週間:
公開コードを確認いただき、チーティングが疑われる場合は、トピックを通して質疑の投稿をお願いいたします。

レビュアーからの質疑と、回答状況をふまえて、最終的に運営側で順位確定を判断します。

■順位決定ロジック
  1. コンペ期間中はPublicリーダーボード(以下LB)により暫定評価を、最終結果についてはPrivate LBにより評価します。
    ※ Private LBはコンペ終了と同時に表示されます。
  2. Private スコア計算に使われるファイルについては、2つまで選択可能です。
    ※ 未選択の場合は、Public スコアの上位ファイルが提出上限まで自動選択されます。
  3. スコアが同値の場合は、早い日時に提出いただいたユーザーが上位となります。
  4. コンペ終了後であっても、不正が発覚の際は、対象ユーザーは失格となり、全体の順位が繰り上がります。
    順位繰上げにより賞金対象者となられた場合は、繰上げ日より一週間以内に、トピックにてコードを公開いただき、「Open Review Competition」と同様のフローにて順位を確定させていただきます。
■タイムライン

開始 2022/2/28 15:00 JST
提出締切 2022/5/8 22:00 JST
終了日 2022/5/8 24:00 JST

エントリー締め切り なし

■システム利用
  • 参加者ごとに1つのアカウントでご参加ください
  • チーム参加の場合は、最大5名までエントリー可能です
  • 1日あたり、最大5回までの提出が可能です
■禁止事項
  • ユーザー間での情報共有
    コンペティションに関連するコード・データを、チーム外のユーザーと共有することはできません。全参加者が利用できる場合に限り、共有可能です。
■外部データ/学習済みモデルの使用
  • 本コンペティションの基本情報/データから取得できるデータのみを用いてチャレンジして下さい。コンペ外データを用いて学習されたモデルの使用も禁止とします。
  • ただし、トピック上で、運営より承認された外部データのみ、使用を許可いたします。承認プロセスについては、「外部データ/学習済みモデルの使用申請について」をご確認ください。

※コンペ期間中であっても、不正が疑われる場合は、運営より確認のためメール連絡させていただくことがございます。一週間以内にご回答いただけない場合も、不正と判断させていただきます。

■外部データ/学習済みモデルの使用申請について

原則外部データ/学習済みモデルの使用は禁止としておりますが、正解データの入手につながらない場合は、下記承認プロセスにより使用できることといたします。

  1. トピックを作成し、取得元情報とデータ(格納先URLも可)を添付
  2. 運営にて判断・承認

注)ただし、コンペ終了まで7日をきってからの申請は禁止とします。
また、下記ホワイトリストについては、申請不要で使用いただくことが可能です。

・ホワイトリスト
https://docs.google.com/spreadsheets/d/1yciWoubQ_JtJSFcsGTjqemNDUL3KccL52dBfCzvVIZA/edit#gid=0

※注意事項

・上記をラップしたツールキットは申請不要で使用可能
・データを追加し再学習されたモデルについては使用不可(要申請)

■運営からのお願い

公平性の担保、チーティング等の不正防止のため、予告なくルールの追加・変更を行う場合がございます。
ご不便をおかけすることもあるかと思いますが、サービス向上のためご了承ください。

FAQ

このコンペティションでは賞金はでますか?

はい。
最も精度の高い学習モデルを作成した優勝者には、賞金10万円を贈呈します。
順位確定までのプロセスについては、ルール「Open Review Competition」を参照ください。

チームで参加できますか?

可能です。チームページから作成いただけます。

どこでアカウントをつくればいいですか?

こちらから作成いただけます。

コンペティション参加にはアカウント登録が必要となりますのでご注意ください。

外部データ/学習済みモデルを使うことは可能ですか?

申請を行うことによって利用可能です。
ルール「外部データ/学習済みモデルの使用申請について」を参照ください。

コードを提出するにあたって Seed を固定する必要はありますか?

Seed を固定することが推奨です。
ただし、Seed を固定しなくても提出用コードとしては認めています。

提出回数はいつリセットされますか?

ファイル提出後、23時間ごとにリセットとなります。
グローバル展開していくにあたり、居住国(時差)による有利・不利を最小化するため、一定時間でリセットする仕様としております。

概要

このチュートリアルでは、民泊の宿泊施設データに対して

  • データの読み込み
  • データの確認と前処理
  • Scikit-Learnを用いて回帰モデルの作成、学習
  • 提出用データの作成

を行います。

環境

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データの読み込みは複数のやり方がありえますが、pandasread_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>)

710d9851-ca09-4863-b8c4-e42c6ea7fde8.png

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_reviewreviews_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条(適用)

  1. 参加者(第2条に定義します。)は、コンペティションに参加した時点で、本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールの一切に同意したものとみなされます。
  2. 本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールは、コンペティションの終了後も参加者に適用されます。

第2条(定義)
本規約において次の各用語の定義は、それぞれ以下に定めるとおりとします。

  1. 「本コンペ」とは、当社ウェブサイト上で開催されるAI開発又はデータ分析等に関するコンペティションのうち、本規約に紐づく特定のコンペティションを意味します。
  2. 「主催者」とは、当社またはユーザーのうち、本コンペを主催する者を意味します。また、本コンペが、当社の顧客又は提携先の企業、学校その他の団体等がスポンサードするものである場合は、当該団体等も主催者の定義に含まれます。
  3. 「参加者」とは、ユーザーのうち、主催者側以外の立場で本コンペに参加する方を意味します。
  4. 「成果物」とは、本コンペにおいて参加者により開発される学習済みモデル、そのソースコード及び乱数シード等の設定値を意味します。
  5. 「入賞者」とは、当社より本コンペに入賞した旨の通知を受けた参加者を意味します。
  6. 「知的財産権」とは、著作権(著作権法第27条及び第28条に定める権利を含みます。)、特許権、実用新案権、商標権、意匠権、その他のノウハウ及び技術情報等の知的財産権(それらの権利を取得し、又はそれらの権利につき登録等を出願する権利を含みます。)を意味します。

第3条(権利の帰属)

  1. 本コンペで発生した成果物に関する知的財産権は、参加者に帰属します。

第4条(入賞者の義務)

  1. 入賞者は、本コンペで公開した成果物を、MITライセンスを適用し、商用利用の許諾条項及び著作権人格権の包括的不行使条項をライセンス条項に付与した形式で、オープンソースソフトウェアとして公開する義務を負うものとします。その前提として、入賞者は、成果物について本項に基づく方法でオープンソース化する権利を有していることを当社に対して表明保証するものとします。
    ※第三者が、授業・研修・セミナー等で活用できるようにするための規約となります。ご理解のほどよろしくお願いいたします。
  2. 当社は、以下の3点の確認が完了した時点で、本コンペの賞金または商品を、入賞者に対して授与するものとします。
    1. 入賞者が、前項に基づいて成果物のオープンソース化を実施したこと
    2. 入賞者が、本規約、利用規約、その他ご同意いただいた規約のすべて、及びコンペティションサイトに掲載されているコンペティションに関するルールの一切に違反していないこと
    3. 当社が定める方法による本人確認
  3. 当社は、入賞者が第1項に基づいてオープンソース化した成果物を、自由に商用利用することができます。

第5条(禁止事項)

  1. 参加者は、本コンペにおいて、以下の各号のいずれかに該当する行為を行ってはならないものとします。
    1. クラッキングやチート行為、なりすまし、盗用等の不正行為
    2. 第三者の知的財産権その他の権利を侵害する内容ないし態様で、参加者公開事項を公開する行為
    3. 主催者(当社以外の者に限ります。)に対する直接連絡、相談、依頼、勧誘、勧誘対応等の活動(但し、当社を介して当社が認めた方法により行うものは除きます。)
    4. 本コンペにおいて、当該コンペと直接関係のない成果物等を提出すること
    5. 本規約における参加者としての地位又は参加者としての権利義務について、譲渡、移転、担保設定、その他の処分をすること
    6. その他、本規約、参加ルール及び利用規約に違反する行為
  2. 参加者が前項に規定する禁止行為を行ったと当社が認める場合、当社は、当該参加者に事前に通知することなく、当該参加者の本コンペにおける失格処分、当社サービスの全部又は一部の利用停止、ユーザー登録の抹消、その他当社が必要と判断した措置をとることができるものとします。

第6条(本コンペの変更、中断、終了等)

  1. 当社は、参加者に事前の通知をすることなく本規約に基づく本コンペの開催内容の変更、本コンペの一時的な中断又は終了を行うことができます。
  2. 当社は、本条に基づき当社が行った措置により生じた結果及び損害について、一切の責任を負わないものとします。

第7条(損害賠償)

  1. 参加者は、本コンペに関連して、自らの責に帰すべき事由により、当社、主催者その他の第三者に損害を与えた場合には、その一切の損害(逸失利益、弁護士費用を含みます。)を賠償するものとします。
  2. 参加者が本規約の規定に違反したことにより主催者(当社を除きます。)その他の第三者が当社に対して何らかの訴え、異議、請求等がなされた場合において、当社から処理の要請がなされたときは、参加者は自己の責任と費用負担において、当社に代わって当該第三者との紛争を処理するとともに、当社がかかる訴え、異議、請求等により被った一切の損害(逸失利益、弁護士費用を含みます。)を賠償するものとします。

第8条(本規約の変更)
当社は、必要と判断した場合には、参加者に対して事前に通知する(本コンペにかかる当社ウェブサイト上での告知その他当社が適当と認める方法を含みます。)ことにより、いつでも本規約を変更することができるものとします。なお、変更内容の通知後、参加者が当社の定める期間内に本コンペへの参加を取り消す手続をとらなかった場合には、当該参加者は変更後の規約に同意したものとみなされます。当社は、本規約の変更により参加者に生じたすべての損害について一切の責任を負いません。

第9条(その他)
本契約の準拠法は日本法とし、本契約に起因し又は関連する一切の紛争については、当社の本店所在地を管轄する裁判所を第一審の専属的合意管轄裁判所とします。

(制定)2020年6月22日