Uncategorized

生成AI活用を現実にする──Intel Gaudi 2とRAGが切り拓く企業の次世代ナレッジソリューション

なぜPandasの“ちょい技”が効くのか

機械学習の精度はアルゴリズムだけで決まるわけではありません。多くの時間を占める前処理と特徴量づくりで、スピードと再現性を高めることが成果に直結します。ここでは、Pandasを使った実務で効いたトリックを7つに絞って紹介します。どれも小さな工夫ですが、積み上げると大きな差になります。

1. 読み込みを設計する:usecols・dtype・parse_dates

読み込みの最適化はその後のすべてを速く、軽くします。不要な列を読み込まない、型を明示、日付は最初から日時型に。

import pandas as pd
cols = ["id", "date", "price", "category"]
dtypes = {"id": "int32", "price": "float32", "category": "category"}
df = pd.read_csv(
    "data.csv",
    usecols=cols,
    dtype=dtypes,
    parse_dates=["date"],
)
df = df.set_index("id")

使う列だけを読み、型を固定することで、メモリと速度を両立します。読み込み時にインデックスを決めると、後工程の結合・検索も安定します。

2. 型とメモリを整える:downcast・to_datetimeのエラー許容

推論環境に載せることも考え、型を小さく安全に。

# 数値のダウンキャスト
for c in ["price"]:
    df[c] = pd.to_numeric(df[c], errors="coerce", downcast="float")

# 文字列→日付(壊れた値はNaTに)
df["date"] = pd.to_datetime(df["date"], errors="coerce")

エラーは強制的にNaN/NaTへ。後段の欠損処理と組み合わせて、堅牢さを担保します。

3. カテゴリはcategoryで管理し、コード化とダミー化を使い分け

低〜中カーディナリティな文字列はcategory型が最適。メモリ削減と処理速度の両方に効きます。

# カテゴリ型化とコード化
cat_col = "category"
df[cat_col] = df[cat_col].astype("category")
df[cat_col + "_code"] = df[cat_col].cat.codes

# one-hot(落とし込み過ぎに注意)
df = pd.get_dummies(df, columns=[cat_col], drop_first=True)

ツリー系ではコード化、線形モデルではダミー化など、学習器に合わせて選ぶのがコツです。

4. メソッドチェーンで“再現可能な前処理パイプライン”

assignqueryevalpipeを組み合わせると、ノートブックの散逸を防ぎ、処理を一望できます。

def add_features(df):
    return (
        df
        .query("price > 0")
        .assign(
            log_price=lambda d: np.log1p(d["price"]),
            day=lambda d: d["date"].dt.day,
        )
        .assign(
            price_rolling7=lambda d: d["price"].rolling(7, min_periods=1).mean()
        )
    )

import numpy as np

df_feat = (df
           .sort_values("date")
           .pipe(add_features))

関数add_featuresに閉じ込めると、学習・推論の両方で同じロジックを使い回せます。

5. シャッフル・分割を手早く:sampleとグループ分割

データフレームだけで手早く分割したいとき。

# シャッフル
df_shuffled = df.sample(frac=1, random_state=42)

# ホールドアウト分割(80/20)
train = df_shuffled.sample(frac=0.8, random_state=42)
valid = df_shuffled.drop(train.index)

# ラベルごとに比率を保つ分割(簡易ストラタム)
label = "target"
train_s = (df
           .groupby(label, group_keys=False)
           .apply(lambda x: x.sample(frac=0.8, random_state=42)))
valid_s = df.drop(train_s.index)

厳密な分割はsklearn.model_selection.train_test_splitstratifyが便利ですが、Pandasだけでも実用的に運用できます。

6. groupby・transform・rollingで“軽い”特徴量を量産

行指向のapplyは遅くなりがち。まずはベクトル化・集約で作れる特徴量を最大化しましょう。

# 集約特徴(顧客平均など)
df["price_user_mean"] = df.groupby("user_id")["price"].transform("mean")

# 時系列の移動平均(ユーザー単位)
df = df.sort_values(["user_id", "date"]).copy()
df["price_roll3"] = (
    df.groupby("user_id")["price"].rolling(3, min_periods=1).mean().reset_index(level=0, drop=True)
)

transformは元の行数を保つため、学習データにそのまま合流できるのが強みです。

7. 欠損と外れ値の“早期発見・早期治療”ルーチン

学習前のクイック健診を習慣に。

# 概要チェック
df.info()
print(df.describe(include="all"))

# 欠損率・分布
na_rate = df.isna().mean().sort_values(ascending=False)
print(na_rate.head())

# シンプルな欠損処理
num_cols = df.select_dtypes(include=["number"]).columns
df[num_cols] = df[num_cols].fillna(df[num_cols].median())

# カテゴリの穴埋め
cat_cols = df.select_dtypes(include=["category", "object"]).columns
df[cat_cols] = df[cat_cols].fillna("(missing)")

まずは単純な方針で一貫性を持たせ、必要なら後で高度な手法(KNNや多重代入など)へ切り替えます。

現場で効く運用のヒント

  • 最初に「読み込み契約(列・型・欠損)」を決めると、下流が安定します。
  • 特徴量関数はpipeでカプセル化し、学習・推論で同一化。
  • まずはベクトル化で速く作れる特徴量を最大化。遅いapplyは最後の手段。
  • 分割は常にrandom_state固定。結果の再現性が検証の土台です。

まとめ

Pandasの小さな工夫は、データ準備・特徴量エンジニアリング・検証の全部に効いてきます。ここで紹介した7つをベースに、自分の案件に合わせた“前処理スタイルガイド”を作っておくと、チームの速度と品質がぐっと上がります。まずは一つでも、今日のノートブックから取り入れてみてください。

関連記事
error: Content is protected !!