【データコンペ】目的変数の変換について(対数と平米単価)
Nishikaの不動産コンペに挑戦して、過去のディスカッション内容を見ていると、
上位ランナー全員が平米単価を予測するモデルを作成していました。
提出する目的変数が物件価格(log)なので、
チュートリアルコードでも、物件価格を算出する仕様になっています。
聞くと簡単なのですが、
なぜそうなるか?実際にコードに反映するとどうなるか?難しいものです。
1 なぜ平米単価に変換するのか?
コンペ参加者の中では当然のことなのか?
データ的に説明する記事は他を探して見当たらなかったです。
理解するために見たのは、不動産のサイト。
データ云々ではなくテーマの中から適切なアプローチを捉える、
ということが重要なのかと思いました。
坪単価を知っていれば、マンションを選ぶ際にその価値を知るための基準ができます。たとえば、専有面積が異なるマンションの価格を比較したいときは、坪単価を算出すれば比較検討がしやすくなるでしょう。また、同じマンション内で別の住戸との比較に使うこともできます。西向き、南向きなどの方位による坪単価の違いがわかれば、そのマンションが方位の違いにどのくらいの価値の差を設けているのかがわかるのです。階数やルーフバルコニーの有無などの条件の違いについても同じことが言えます。
また、坪単価は物件のおおまかな相場を掴むのにも便利です。会社別・商品別のグレードがわかれば、予算と物件を比較検討しやすくなります。ほかにも、物件を沿線広域で探す際にも、坪単価は便利です。エリアごとの相場観を把握することができるので、自分の希望にあった物件のあるエリアを探しやすくなるでしょう。
つまりは、面積の違いを除外した単価でみることで、
条件が異なる物件価値を比較できる。
ちなみに、今回は面積で割った平米単価を使ってます。
不動産価格予測が身近なテーマなので、目的変数の変換であったり、
平米単価とうい馴染みある言葉なので、感覚的に理解ができます。
テーマに合わせて予測精度を上げるためには、
モデリングに着手する前に、その領域を深く理解することが重要そうです。
ビジネスシーンで考えても、要検定義やビジネス理解なしに、
そのデータPJTは成功しないのと同様。
その背景や知識から、外部データやデータ変換をどう取り入れるか?
というアプローチの仮説立てができるようになると思いました。
2 平米単価への変換実装
※詳しいデータセットはNishikaのコンペサイトから見てみてください。
2.1 なぜ対数が使われているのか?
このコンペでは不動産価格が常用対数を取っています。
なので単純に物件価格÷面積でいいじゃないか、とはならないです!
なぜ対数が使われているのでしょうか?
不動産価格を整数に変換してグラフ化すると、
平均値付近に激しく偏った分布になっています。
機械学習において偏ったデータをそのまま使用すると精度が落ちます。
右がもはや見えないですが、右の裾が非常に長いグラフに分布になってます
![](https://assets.st-note.com/img/1665799214829-pyav1ZurJ5.png?width=1200)
そこで使われるのが対数変換です。
対数変換はデータの分布が狭い時に拡大して、
広い時には凝縮してくれる特性があります。 ※以下参照
実際に対数変換すると、以下のように見慣れた正規分布に近いような分布に変換することが出来ます。
・・という理由で対数変換という前処理を行います。
![](https://assets.st-note.com/img/1665799289440-WwygIfo30P.png?width=1200)
2.2 対数の四則演算
対数の意味を理解したうえで、
面積データを見ると、こちらは対数変換されていません。
そのため、面積も対数変換して計算する必要があります。
logの割り算は引き算になります。(掛け算は足し算)
logaM/N=logaM−logaN
logaMN=logaM+logaN
面積を常用対数に変換して元の面積はdropし、
引き算を行うことで平米単価(log)が算出できます。
df['area'] = np.log10(df['面積(㎡)'])
df.drop(['面積(㎡)'], axis=1, inplace=True)
df['平米単価'] = df['取引価格(総額)_log'] - df['area']
df.drop(['取引価格(総額)_log'], axis=1, inplace=True)
Excelで実行するときは、「=log10」という関数で変換できます。
3 まとめとおまけ
まず対数変換の意味を知ることと、
次に対数の四則演算を理解して算出する必要があります。
対数変換は基本的な前処理方法の1つということで、
理解して慣れておかないとですね。
おまけに・・
どこかで説明するかもですが、
今回のモデルでは最後に一度、整数に戻して別処理をしてから、
再度対数変換するということを行っています。
その時は10の対数乗で戻すことが出来ます。
Pythonでは以下になります。
sub_df['取引価格(総額)_円'] = 10 ** sub_df['取引価格(総額)_log']
また、平米単価を物件価格に戻すこときはこれです。
sub_df['取引価格(総額)_log'] = sub_df['平米単価'] + sub_df['area']
他の分散が大きい説明変数の方も試してみたくなりました。
今後も色々と自分が学んだノウハウをNoteにしていきます。
この記事が気に入ったらサポートをしてみませんか?