
アルゴリズムを変えても精度が伸びない…
結論:モデル精度の大半は特徴量設計とリーク対策で決まります。
この記事で身に付く力
- 現場で使える特徴量設計の“型”(時間窓・集約・比/差分)
- リークを防ぐパイプライン構築(ColumnTransformer×Pipeline)
- 評価と自動化(CV±std、Permutation Importance、スクリプト化)
対象環境:Python 3.10+ / pandas 2.x / scikit-learn 1.x。未経験〜初学者が週10時間×2〜3週で、要件→設計→前処理→特徴量作成→評価→改善→自動化まで回せるテンプレを配布します。
関連記事:
>>【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得
>>【保存版】モデル評価:指標の選び方・交差検証・閾値最適化・ビジネス接続を“実務の型”で解説
>>【保存版】ハイパーパラメータ入門:Grid/Random/Optunaの実務チューニング完全ガイド
>>【保存版】pandas基礎:データフレームの作成・整形・結合・集計を“実務の型”で身につける
>>【実務で差がつく】pandas実践:欠損処理・結合・ウィンドウ関数・時系列・品質保証まで“読みやすく速い”型を習得
>>【保存版】NumPy基礎:配列・ブロードキャスト・ベクトル化・乱数・線形代数を“実務の型”で最短習得
>>実務で使える統計の型12 | Pythonで最短習得
>>【保存版】可視化入門:Matplotlib/Plotlyの使い分けと“伝わるグラフ設計”10ステップ
>>はじめてのSQL:SELECT/WHERE/GROUP BYを最短で理解【コピペOK】
>>【保存版】SQLite×Pythonで作る“ローカルDWH”——ETL・集計・レポート自動化の最短手順
>>【保存版】Jupyter Notebookの基本:環境構築・使い方・再現性・“読みやすいノート”設計まで完全ガイド
>>【保存版】Git/GitHub入門:バージョン管理・ブランチ戦略・レビュー・自動化を“実務の型”で最短習得
>>【コピペOK】pytestで“壊れないPython”を作る12ステップ
>>【保存版】データ職のポートフォリオ完全ガイド|再現性・評価・LTまで
よくあるつまずき(3つ)と先に押さえる解決方針
闇雲にアルゴリズムを変えても、土台が整っていないと精度は伸びません。まずはここを直します。
- リーク(情報漏れ):未来情報や目的変数の混入でCVは高いのに本番で崩壊。
- スケール不一致:桁バラバラで勾配/距離ベースが不安定。
- 高カーディナリティ:カテゴリが多すぎてOne-Hot爆発。
解決の型:ColumnTransformer+Pipelineで“学習内の処理”に閉じ込み、交差検証で評価しながら小さく積む。
実務で効いた話(ふみと)
役員会向けの意思決定支援で刺さったのは、業務ロジック×時間軸を写した特徴量(例:直近4週移動平均/前年同週比/在庫ギャップ)。そして訓練データ内統計のみで変換するリーク対策。以降はこの方針でテンプレ化していきます。
実装テンプレ:特徴量“実務の型”10ブロック
以下のコードはそのままコピペでOK。学習内に前処理を閉じ込めるのが最大のポイントです。
1) データ要件とターゲット定義(最重要)
誰が何を決めるための予測か、ターゲットと時間窓を最初に固定します。
予測日:YYYY-MM-DD
学習窓:予測日の過去N日(例:90日)
評価窓:直近L日(例:30日)
ターゲット:評価窓内の離反=1
2) 前処理の骨組み(ColumnTransformer+Pipeline)
import pandas as pd
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score, StratifiedKFold
num\_cols = \["qty","price","days\_since\_last","amount"]
cat\_cols = \["store","category","area"]
num\_pipe = Pipeline(\[
("impute", SimpleImputer(strategy="median")),
("scale", StandardScaler()),
])
cat\_pipe = Pipeline(\[
("impute", SimpleImputer(strategy="most\_frequent")),
("onehot", OneHotEncoder(handle\_unknown="ignore", min\_frequency=5))
])
preprocess = ColumnTransformer(\[
("num", num\_pipe, num\_cols),
("cat", cat\_pipe, cat\_cols)
])
clf = Pipeline(\[
("prep", preprocess),
("model", LogisticRegression(max\_iter=1000, n\_jobs=-1))
])
cv = StratifiedKFold(n\_splits=5, shuffle=True, random\_state=42)
# PR-AUC推奨(不均衡向け)
scores = cross\_val\_score(clf, X, y, scoring="average\_precision", cv=cv, n\_jobs=-1)
print(scores.mean(), scores.std())
ポイント:Impute/Scale/Encodeは学習内に包含。min_frequency
でレアカテゴリを束ねます。
3) 時間特徴量(時系列の基本)
df["date"] = pd.to_datetime(df["date"])
df["ym"] = df["date"].dt.to_period("M").astype(str)
df["dow"] = df["date"].dt.dayofweek
df = df.sort\_values("date")
df\["amt"] = df\["qty"]\*df\["price"]
# ラグ/移動平均(未来参照はNG)
df\["amt\_lag1"] = df.groupby("store")\["amt"].shift(1)
df\["amt\_ma4"] = df.groupby("store")\["amt"].rolling(4).mean().reset\_index(level=0, drop=True)
# 季節性
df\["month"] = df\["date"].dt.month
禁じ手:shift(-1)
等で未来を見る、学習/評価の境界を跨いだ平均。
4) 集約特徴量(顧客・店舗・カテゴリ単位)
# 直近90日の顧客別集約例
win = df.groupby(["customer"]).rolling("90D", on="date")["amt"].agg(["sum","mean","count"]).reset_index()
win.columns = ["customer","date","amt_sum90","amt_mean90","txn90"]
df = df.merge(win, on=["customer","date"], how="left")
時間窓を限定し、同一個体内の統計を使う(クロス個体の情報混入に注意)。
5) 高カーディナリティ対策(Rare/Hash/Target Encoding)
- Rare Bucketing:出現が少ない値を
_OTHER
にまとめる - Hashing:OneHotの代替(scikit-learn標準外/
min_frequency
も有効) - Target Encoding:Fold内平均を使いリーク回避
import pandas as pd
from sklearn.model_selection import KFold
def kfold\_target\_encoding(X\_col, y, n\_splits=5, seed=42):
X\_col = pd.Series(X\_col)
kf = KFold(n\_splits=n\_splits, shuffle=True, random\_state=seed)
enc = pd.Series(index=X\_col.index, dtype=float)
for tr, va in kf.split(X\_col):
m = y.iloc\[tr].groupby(X\_col.iloc\[tr]).mean()
enc.iloc\[va] = X\_col.iloc\[va].map(m).fillna(y.iloc\[tr].mean())
return enc
X\["store\_te"] = kfold\_target\_encoding(X\["store"], y)
全体平均でのエンコードはリークになります。必ずFold内で学習→検証へ適用。
6) 欠損と外れ値:方針とフラグ
from sklearn.impute import SimpleImputer
# 欠損フラグを別に持つ
X\["qty\_isna"] = X\["qty"].isna().astype(int)
# 数値はmedian、カテゴリは最頻
imputer\_num = SimpleImputer(strategy="median")
imputer\_cat = SimpleImputer(strategy="most\_frequent")
欠損そのものが情報になりやすいので、isna
フラグを別列で付与します。
7) 変換:スケーリング/ボックス変換/ビニング
- StandardScaler:平均0・分散1(ロジ回/線形/距離系に効く)
- MinMaxScaler:0–1(木系は不要)
- RobustScaler:外れ値に強い
- PowerTransformer(Yeo-Johnson):歪み是正
- KBinsDiscretizer:連続→離散(境界はドメイン判断)
これらは必ずPipeline内で実施([内部リンク:scikit-learn基礎])。
8) 相互作用・比・差分:業務ロジックを写す
X["unit_price"] = X["amount"]/X["qty"]
X["stock_gap"] = X["forecast_stock"] - X["actual_stock"]
X["price_ratio"] = X["price"] / X.groupby("category")["price"].transform("median")
差分/比は解釈が容易。カテゴリ基準比は季節影響を抑えやすいです。
9) 特徴量選択(軽量セット)
- 相関/共線性:高相関は片方を落とす(解釈用)
- L1(Lasso/Logistic)でスパース化
- Permutation Importance:CVの外側で計算(リーク回避)
from sklearn.inspection import permutation_importance
clf.fit(X_tr, y_tr)
r = permutation_importance(clf, X_va, y_va, n_repeats=5, random_state=42)
10) 評価・改善・自動化
- 評価:分類→PR-AUC/ROC-AUC、回帰→MAE/RMSE。CV±stdとTop-kでビジネス接続([内部リンク:モデル評価])。
- 改善:特徴量の追加/削除→再CV。過学習は正則化/単純化。
- 自動化:Pipeline+GridSearchCV/RandomizedSearchCV([内部リンク:ハイパーパラメータ入門])。
付録:よく使う拡張・チェック・テスト
A. ColumnTransformer×Datetime機能拡張例
from sklearn.preprocessing import FunctionTransformer
def add\_date\_parts(d):
d = d.copy()
dt = pd.to\_datetime(d\["date"])
d\["month"], d\["dow"] = dt.dt.month, dt.dt.dayofweek
return d\[\["month","dow"]]
preprocess = ColumnTransformer(\[
("num", num\_pipe, num\_cols),
("cat", cat\_pipe, cat\_cols),
("date", FunctionTransformer(add\_date\_parts), \["date"]) # date列から2列生成
])
B. リークのチェックリスト(保存版)
- 未来日付/未来在庫を使っていない
- Target EncodingはFold内平均で実施
- 標準化/欠損補完は学習内でfit
- 集約は同一個体/時間窓内で完結
- 評価は時系列CV or KFoldで設計(シャッフル有無を吟味)
C. テスト最小セット(pytest)
# tests/test_features.py
import pandas as pd
from src.features import make_features
def test\_no\_future\_leak():
df = pd.DataFrame({"date": pd.date\_range("2025-01-01", periods=10, freq="D"),
"amt": range(10)})
X = make\_features(df)
\# lagは必ずNaNを含む(未来参照なしの証拠)
assert X.filter(like="lag").isna().sum().sum() > 0
読者タイプ別:最短で“刺さる”一手
- 社会人(転職):時間窓×差分/比+Target Encoding(CV付き)。CV±stdとTop-kで提示 → [内部リンク:モデル評価]
- 副業(稼ぎたい):在庫ギャップ/需要移動平均/前年同週比などKPI直結を優先 → [内部リンク:データレポート納品の型]
- 主婦/夫(在宅):Pipeline化して“ボタン一発”。欠損フラグ+RobustScalerで安定 → [内部リンク:在宅×Python:子育てと両立する1日1時間学習術]
行動課題:ミニプロジェクト(提出推奨)
課題:「小売の需要予測(回帰)」を想定し、以下の特徴量を作成→CV(KFold)でMAE評価→Permutation Importanceで上位5を報告。
- ラグ:
amt_lag1, lag7
- 移動平均:
amt_ma4, ma12
- 季節:
month, dow
- カテゴリ基準比:
price_ratio
- 在庫ギャップ:
stock_gap
(あれば) - 欠損フラグ:
*_isna
- [ ] 未来参照なし(
shift
は正方向のみ) - [ ] 前処理はPipelineに含めた
- [ ] CV±stdを提示(回帰は
neg_mean_absolute_error
) - [ ] Top-k特徴量の重要度を提示
- [ ] Notebook→スクリプト化(
run_all.py
)
伴走サポート(任意)
ロジックを数字に翻訳できると、精度と納得感が一気に上がります。リーク対策と評価設計まで含め、短期で“回る”仕組みを作るなら、レビュー付きスクールの活用が近道です。
TechAcademy データサイエンスコース(受講料:174,600円~ ※更に割引あり)

株式会社キカガク AI人材長期育成コース(受講料:237,600円~)

この記事から次に読むべきもの(内部リンク)
-
-
【保存版】モデル評価:指標の選び方・交差検証・閾値最適化・ビジネス接続を“実務の型”で解説
精度が上がらない原因の多くは「評価設計の誤り」にあります。評価とは「何点取れたか」ではなく、意思決定に耐えるかを測る営み。この記事では、回帰/分類/ランキングの指標の選び方、交差検証の正しい使い分け、 ...
-
-
【保存版】ハイパーパラメータ入門:Grid/Random/Optunaの実務チューニング完全ガイド
チューニングのゴールは「スコアの数字遊び」ではありません。意思決定に耐える安定した最適化を短時間で作ること。本記事は未経験〜初学者が週10時間×2週間で、GridSearchCV / Randomiz ...
-
-
【保存版】scikit-learn基礎:回帰・分類・前処理・パイプライン・交差検証を“実務の型”で習得
機械学習で迷子になる最大の理由は、前処理→学習→評価→改善の順番が曖昧なまま個々のアルゴリズムに飛びつくこと。本記事は、未経験〜初学者が週10時間×2〜3週で到達できるscikit-learnの最短ル ...
-
-
【実務で差がつく】pandas実践:欠損処理・結合・ウィンドウ関数・時系列・品質保証まで“読みやすく速い”型を習得
リード(結論)基礎を終えたら次は実務の現場で頻出する処理を“型”で覚える段階です。本記事は、pandas 2.x を前提に、欠損・外れ値・結合・ウィンドウ関数・時系列・カテゴリ処理・集計の自動化・大規 ...
-
-
はじめてのSQL:SELECT/WHERE/GROUP BYを最短で理解【コピペOK】
データ分析・自動レポート・簡易アプリの土台はSQLです。Pythonだけで押し切るより、前処理の7割をDB側で完結させる方が速く・安定します。本記事は、未経験〜初学者が週10時間×2〜3週で、SELE ...
最近のコメント