##はじめに
初めまして!閲覧いただきありがとうございます!
都内のIT会社でデータサイエンティストとして働いており、主に社内のデータ活用・AI活用の推進や社外のデータを用いて、データ分析や予測・分類モデルの作成も行っています。
今回、会社でインターン生の受け入れを行いました。
インターン生には、データサイエンスに興味を持ってもらいつつ、Kaggleのチュートリアルのコンペ「House Prices - Advanced Regression Techniques」でコードを提出していただきました!
提出に至るまでのソースコードを本投稿で紹介いたします。
※事前にインターン生には承諾は得ております。予めご了承下さい。
##コンペの詳細
House Prices - Advanced Regression Techniques
Predict sales prices and practice feature engineering, RFs, and gradient boostin
g
###Overview
Ask a home buyer to describe their dream house, and they probably won't begin with the height of the basement ceiling or the proximity to an east-west railroad. But this playground competition's dataset proves that much more influences price negotiations than the number of bedrooms or a white-picket fence.
With 79 explanatory variables describing (almost) every aspect of residential homes in Ames, Iowa, this competition challenges you to predict the final price of each home.
###Data
files
├ data_description.txt
├ sample_submission.csv
├ test.csv
├ train.csv
###Reprint
https://www.kaggle.com/c/house-prices-advanced-regression-techniques
#インターン生の取り組み
以下、インターンの取り組み結果を、ご本人のコメントとともにご覧ください。
###コンペ参加に至った背景
インターンに参加させていただけることになり、データサイエンティストになるためのファーストステップとして、kaggleのコンペに参加することになった。
インターンに参加するまではデータサイエンティストという職種がそもそもどういうものなのかすらよくわかっていないような状態だったため、kaggleに挑戦するまでにAidemyで学習して事前知識をつけた。
###Aidemyで得た事前知識
受け入れてくれた会社でAidemyを無料で受講した!助かる!!!
多くのカリキュラムがあったが、データサイエンスに関わるカリキュラムを受講した。
以下、受講したカリキュラムの一部を記載する。
<Aidemy受講講座>
AI・データサイエンスとは何かの基礎知識
統計学基礎
SQLのデータ抽出方法
Python / Pandas / Numpy 入門
Pandasを用いたデータクレンジング方法
機械学習に関する知識(教師あり・なし学習)
Kaglleのコンペに挑戦
###ライブラリのインポート・基本設定
import numpy as np # linear algebra
import pandas as pd # data processing, CSV file I/O (e.g. pd.read_csv)
import matplotlib.pyplot as plt
import sklearn as sk
import os
for dirname, _, filenames in os.walk('/kaggle/input'):
for filename in filenames:
print(os.path.join(dirname, filename))
####訓練用・テスト用データの読み込み
Pandasを用いてデータを読み込む、処理しやすい?ようにDataFrameで出力
train_df = pd.read_csv('/kaggle/input/house-prices-advanced-regression-techniques/train.csv')
test_df = pd.read_csv('/kaggle/input/house-prices-advanced-regression-techniques/test.csv')
print(train_df.shape)
print(test_df.shape)
(1460,81)
(1459,80)
####訓練用データ確認
本来ならカラム毎に確認する必要があるが、時間が限られていたため、相関関係に着目した
相関関係に強弱があるものを中心に取り組む
#データ全体を俯瞰
train_df
test_df
#データ型確認
train_df.info()
#各カラムごとの欠損値確認
train_df.isnull().sum()
#相関関係を確認
train_df.corr().iloc[-20]
####前処理の実施
目的変数についてデータの確認を実施した
どのような分布なのかを確認する
## SalePrice を可視化する
import seaborn as sns
sns.histplot(train_df['SalePrice'])
SalePriceを可視化した結果、右に裾が長いグラフになっていたので、対数変換を実施した
#対数変換
train_df['SalePrice'] = np.log1p(train_df['SalePrice'])
次に、今回欠損値が多いカラムを削除した
train_df = train_df.drop(["Alley","PoolQC","MiscFeature","Fence","FireplaceQu","LotFrontage"],axis=1)
カテゴリー変数をダミー変数化する
LotConfig / LotShape / Foundation / CentralAir / KitchenQual / xterQual の計5つをダミー変数化
train_df=pd.get_dummies(train_df,
drop_first=True,
columns=[['LotConfig','LotShape','Foundation','CentralAir',KitchenQual','xterQual']]
)
####特徴量の選定
#使う特徴量
original_columns = ['OverallQual','YearBuilt', 'YearRemodAdd',
'1stFlrSF','GrLivArea','FullBath','HalfBath',
'TotRmsAbvGrd', 'Fireplaces','GarageCars',
'GarageArea', 'OpenPorchSF','YrSold',
'OpenPorchSF','MasVnrArea','KitchenQual_Gd','KitchenQual_Fa',
'CentralAir_Y', 'KitchenQual_TA','BsmtFinSF1',
'ExterQual_Fa', 'ExterQual_Gd','ExterQual_TA',
'Foundation_CBlock', 'Foundation_PConc',
'Foundation_Slab','LotConfig_CulDSac',
'LotConfig_FR2', 'LotConfig_FR3',
'LotConfig_Inside','Foundation_Stone',
'Foundation_Wood','LotShape_IR2', 'LotShape_IR3', 'LotShape_Reg']
##説明変数(X_train)・目的変数(y_train)に分割
X_train = train_df[original_columns]
y_train = train_df['SalePrice']
X_test = test_df[original_columns]
print(X_train.shape, y_train.shape, X_test.shape)
####様々なモデルで汎化性能を確認
Lasso / Ridge / RandomForestRegressor の3種類のモデルで性能を確認した
交差検証はCross_val_score ・ Kfoldを使用
評価指標はR^2(決定係数)を使用
##LassoRegressor
from sklearn.linear_model import Lasso
#モデルの作成
model_l = Lasso()
model_l.fit(X_train,y_train)
#Kfoldの実装
kf = KFold(n_splits=3,shuffle=True)
score_l = cross_val_score(model_l, X_train, y_train, cv=kf)
#正解率を出力する
print(f"スコア: {score_l}")
#平均値を出力する
print(f"平均値: {score_l.mean()}")
##RidgeRegressor
from sklearn.linear_model import Ridge
#alpha=10などを引数に入れると制約の強さを変化できる
model_r = Ridge()
model_r.fit(X_train,y_train)
kf = KFold(n_splits=3,shuffle=True)
score_r = cross_val_score(model_r, X_train, y_train, cv=kf)
print(f"スコア: {score_r}")
print(f"平均値: {score_r.mean()}")
##RandomForestRegressor
from sklearn.ensemble import RandomForestRegressor
import random
random.seed(0)
model_rf = RandomForestRegressor(n_estimators=100,random_state=0)
model_rf.fit(X_train,y_train)
kf = KFold(n_splits=3,shuffle=True,random_state=0)
score_rf = cross_val_score(model_rf, X_train, y_train, cv=kf,scoring="r2")
print(f"スコア: {score_rf}")
print(f"平均値: {score_rf.mean()}")
一番スコア値が高かったものは 「RadomForestRegressor」
テストデータには、RandomForestRegressorを使用し提出することにした
####テストデータの読み込み・確認・前処理
訓練用で使用したデータカラム数を一致させた(訓練用でダミー変数化したので同じくダミー変数化させる)
#訓練用データ読み込み
test_df = pd.read_csv('/kaggle/input/house-prices-advanced-regression-techniques/test.csv')
#データの基本情報確認
test_df.shape
test_df.info()
test_df.isnull().sum()
test_df.head(20)
##ダミー変数化
test_df = pd.get_dummies(test_df,
drop_first=True,
columns=[['LotConfig','LotShape','Foundation','CentralAir','KitchenQual','xterQual']])
test_df = test_df[original_columns]
##欠損値があったカラムに対して欠損値処理を行う
test_df['GarageCars'] = test_df['GarageCars'].fillna(test_df['GarageCars'].median())
test_df['GarageArea'] = test_df['GarageArea'].fillna(test_df['GarageArea'].mean())
test_df['BsmtFinSF1'] = test_df['BsmtFinSF1'].fillna(test_df['BsmtFinSF1'].mean())
test_df['MasVnrArea'] = test_df['MasVnrArea'].fillna(test_df['MasVnrArea'].mean())
####モデルを適合・提出
##訓練用で作成したモデルを当てはめる
prediction = model.predict(test_df)
##予測した値は指数に変換した値で算出されるので、逆変換を行う
prediction = np.expm1(prediction)
##予測結果を提出用のcsvファイルに出力し、提出を行う
sub_df = pd.read_csv('/kaggle/input/house-prices-advanced-regression-techniques/test.csv')
submission = {'ID':test_df['ID'],
'pred':prediction
pd.dataFrame(submission).to_csv('submission',as_index=False)
}
###結果
なんとか提出出来た!!
ベンチマーク以上のスコアであったが、上位には食い込む事は出来なかった。
###参考
Aidemyの講座
https://aidemy.net/
###反省・感想
corr()関数での数値に頼りすぎていた部分があり、自分でカラムの中身と意味をもっと考えて特徴量を選ぶべきだったのかもしれない。
スコアが著しく悪くなった際、原因がわからず半日費やしてしまったが、原因は対数変換したものを指数変換していなかったというものだった。
train_df['SalePrice'] = np.log1p(train_df['SalePrice'])
この一行で半日頭を悩ませてしまったので、次回データフレームに何か変化を及ぼすコードを書いた際はよく注意して扱いたい。
外れ値の処理では、外れ値とみなす境界線が甘かったせいであまり外れていない値も削除してしまったため、精度が悪くなってしまった。次回外れ値の処理について考える際は、散布図なども見つつ、あまりにもずれている値だけ削除したい。
あまりに自由かつ無知なので、何をすればいいのかわからなかった。タイタニックのコンペではAidemyが特徴量の作り方を教えてくれていたが、いざ自分で考えてみても、何を結合すればうまく行くのかなど何も思いつかなかった。
その点に関しても、特徴量をもっと詳しく見て、何を表しているのか理解してから前処理に取り組む必要があったと思う。
やりたい処理があってもAidemyでやったのだが覚えていないというケースが多かった。調べようとしてもなかなか見つけるのに苦労した。調べることができる程度の知識がないと何もできないと分かった。
数学の知識が皆無なので、対数関数から指数関数に変えるところなどあまり理解できなかった。
精度を上げるために「これをしたら上がるかもしれない」という手法の模索が足りなかった。同じ手法を何回も繰り返して精度を上げようとしていたが、もっとさまざまなアプローチを考えればよかったと思う。
インターン全体を通して、自分がどの程度理解できているのかを把握できていなかったと感じた。自分が理解したことを説明できる程度の理解がないのにどんどん進めていってしまったため、あいまいな理解でkaggleでアウトプットできず苦しんだ。あいまいな理解がどこなのか確認しつつ進めないと質問することすらできないため、自分がどの程度理解しているのかを常に確認しながら学習することが大切だと感じた。
###これからやりたいこと
インターンを通して痛感したことはそもそも社会を知らなすぎる、ということである。(そもそもデータサイエンティストもしらなかったので)
さまざまな職種、業界についてより深く知ることで、ビジネス力を上げていきたい。結果としてデータサイエンティストになるにしても必ず役に立つと思う。
ほかのkaggleのコンペにも積極的に参加していきたい。せっかく一か月かけて身に着けたことを忘れないためにも継続的に学習したい。
また、アプリ開発にも興味があるので、エンジニアリング力を上げていきたい。就職を考える際に、自分が働きたい職種を選べるよう、選択肢を増やしたい。
インターンを通じて自分がやりたいことは何なのかを深く考えるきっかけになった。今まではプログラミングをする仕事に就きたいというざっくりした考え方だったが、もっと視野を広く持てるように様々な経験をしていきたい。以上。
##受け入れ側の受け入れての感想
プログラミング未経験の学生を受け入れることに対して最初はとても不安でした。
しかしながら、インターン生のやる気に満ち触れていた姿勢・行動を見て、身が引き締まりました。笑
結果的にはインターン生がベンチマーク以上のスコアが出せて良かったです。
反省点は様々あるので、次回に活かしていこうと思っています。
##今後について
今後も学生さんを受け入れてインターンを実施する予定でいます!
具体的には、短期ではなく長期で受け入れる体制に構築し、実業務にも触れる機会を増やす事で就業経験をより濃く体験出来るようにし努めて参ります!!
インターンお待ちしております!!!