AI学習を継続中。今回はKaggleの定番教材であるTitanicデータセットを使いながら、
pandasによるデータ分析、欠損値処理、特徴量エンジニアリング、train/test分割まで進めた。
ここ数日はNumPyや統計の基礎を復習していたが、今回から「実際のデータを読む」段階へ入ってきた感覚がある。
ChatGPTを講師兼レビュー役として使いながら進めている。
今回の学習テーマ
- Titanicデータセットの読み込み
- 欠損値の確認
- 統計量の確認
- 相関分析
- 特徴量エンジニアリング
- カテゴリ変数の数値化
- train_test_split
Titanicデータセットを読み込む
まずはKaggleからTitanicのtrain.csvをダウンロードして読み込んだ。
Kaggle:
https://www.kaggle.com/competitions/titanic
import pandas as pd
pd.set_option("display.max_columns", None)
pd.set_option("display.width", None)
df = pd.read_csv("train.csv")
print(df.head())
print(df.info())
print(df.describe())
pandasの表示が省略される問題
最初、describe()やhead()の出力で列が途中省略されていた。
pandasは列数が多いと自動で省略するため、以下設定を追加すると見やすくなる。
pd.set_option("display.max_columns", None)
pd.set_option("display.width", None)
初学者だと「データが消えた?」と勘違いしやすいポイントだと思う。
欠損値を確認する
print(df.isnull().sum()) print(df.isnull().mean() * 100)
結果を見ると、かなり特徴的だった。
Age 19.8% Cabin 77.1% Embarked 0.2%
特にCabinの欠損率が非常に高い。
以前は「欠損値=とりあえず埋める」と考えていたが、
実際には「使うか捨てるか」「別特徴量として扱うか」を考える必要があると学んだ。
ChatGPTとのやり取りの中でも、
「欠損率が高すぎる列は扱いが難しい」
という視点を得られたのが大きかった。
describe()から分布を読む
特に興味深かったのがFare(運賃)列。
mean 32.20 50% 14.45 max 512.32
平均値と中央値が大きく離れている。
最初は「ピークが左側なのに、なぜ右に歪んでいると言うのか?」が分からなかった。
調べながら理解したのは、
「右に歪む(right-skewed)」とは、
右側に長い尾を持つ分布を意味するということ。
つまり、
- 大半は小さい値
- 一部だけ極端に大きい値がある
という状態である。
これは実務データでも非常によくあるらしい。
平均と中央値の違い
右に歪んだ分布では、
外れ値によって平均値が引っ張られる。
そのため、
- 平均より中央値が重要
- 欠損補完でも中央値を使うことがある
という話がつながって理解できた。
groupby()を使った集計
今回かなり理解が深まったのがgroupby。
print(df.groupby("Sex")["Survived"].mean())
最初は文法がかなり怪しかった。
ただ、ChatGPTとの対話の中で、
- groupby(“Sex”) → 性別ごとに分割
- [“Survived”] → 生存列を選択
- mean() → 平均を計算
という形で理解できた。
Survived列は0/1なので、
平均値=生存率になる。
female 0.742038 male 0.188908
女性の生存率がかなり高い。
ここで「なぜそうなるのか?」という背景まで考えるのが重要らしい。
特徴量エンジニアリングを体験する
今回から、いよいよ「特徴量を作る」作業へ入った。
Kaggleではかなり重要な領域らしい。
FamilySizeを作成
df["FamilySize"] = df["SibSp"] + df["Parch"] + 1 print(df[["SibSp", "Parch", "FamilySize"]].head())
+1しているのは本人を含めるため。
こういう「意味のある特徴量を自分で作る」のが特徴量エンジニアリング。
FamilySizeごとの生存率
print(df.groupby("FamilySize")["Survived"].mean())
FamilySize 1 0.303538 2 0.552795 3 0.578431 4 0.724138 5 0.200000 6 0.136364 7 0.333333 8 0.000000 11 0.000000
ここがかなり面白かった。
- 一人客は生存率が低い
- 2〜4人程度は高い
- 大家族は逆に低い
単なる数値ではなく、
「なぜそうなるのか?」を考えるのが重要らしい。
カテゴリ変数の数値化
機械学習モデルは文字列を扱えないことが多いため、
数値化が必要になる。
df["Sex"] = df["Sex"].map({
"male": 0,
"female": 1
})
print(df["Sex"].head())
0 0 1 1 2 1 3 1 4 0
これはEncoding(エンコーディング)と呼ばれる処理。
今後かなり頻出しそう。
train_test_splitで学習データを分割する
今回はまだモデル学習はしていないが、
train_test_splitまで進んだ。
from sklearn.model_selection import train_test_split features = ["Pclass", "Sex", "Age", "Fare", "FamilySize"] X = df[features] y = df["Survived"] X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, random_state=42 ) print(X_train.shape) print(X_test.shape) print(y_train.shape) print(y_test.shape)
(712, 5) (179, 5) (712,) (179,)
Xが大文字、yが小文字なのはなぜ?
ここも疑問だった。
調べると、
- X → 特徴量行列(複数列)
- y → 正解ラベル(通常1列)
という慣習らしい。
また、
- DataFrame → 2次元
- Series → 1次元
の違いもここで理解できた。
random_state=42とは?
これも気になった。
random_state=42
42に特別な数学的意味はなく、
乱数固定用の値とのこと。
毎回同じ分割結果になるため、
再現性を確保できる。
AIやデータ分析では、
「再現可能性」が非常に重要らしい。
今回学んだこと
- AIはまずデータを見ることが重要
- 欠損値処理はかなり重要
- groupbyはpandasの核心機能
- 特徴量エンジニアリングがKaggleの本質に近い
- 平均と中央値の違いを意識する必要がある
- 分布の歪みや外れ値を見る癖が重要
以前は「AI=モデル作成」というイメージだったが、
実際には前処理やデータ理解の比重がかなり大きいと感じ始めている。
次回はいよいよscikit-learnのLogisticRegressionを使って、
最初の機械学習モデルを作成予定。