Local LLMでのデータ分析を試してみた
こんにちは
AIチームの戸田です
最近、Coding Agentを使った開発体験がかなり変わってきています。ファイルを読ませ、コードを書かせ、テストを実行させ、エラーを直させる、という流れはすでに日常的に使える水準になってきました。
一方で、Agentに任せられる範囲はコーディングだけではありません。データ分析も、ファイルを読む、前処理を書く、評価指標を出す、結果をレポートにまとめる、という意味ではかなりAgent向きのタスクです。
例えばデータ分析コンペティションのKaggleでも、EDA(Exploratory Data Analysis)にAIを使う流れは見え始めています。
ここで気になるのが、業務で顧客データを分析するときにも、同じようにAI Agentを使えるのか?という点です。
LLMが業務でも一般化してきたとはいえ、実務ではLLMにデータを投げること自体に抵抗のある方が少なくありません。ドメインによっては、契約や規制上の理由で外部APIに渡すこと自体がNG、というケースも普通にあります。クラウドのフロンティアモデルは強力ですが、どの案件でもそのまま使えるわけではない、というのが現状です。
もしLocal LLMでデータ分析Agentを組めればデータを外に出さずに、手元の環境でEDA、特徴量設計、モデル評価、レポート作成まで回せます。
そこで今回は、まず小さな題材としてTitanicデータセットを使い、以下の2構成を比較してみました。
| 構成 | モデル | harness |
|---|---|---|
| クラウドモデル | GPT-5.5 | Codex |
| Local LLM | Qwen3.6 27B MTP GGUF | Qwen Code |
最初はCodexを共通harnessにしてQwen3.6も評価しようとしたのですが、Responses APIとtool schemaの相性でうまくはまりませんでした。短いtool probeまでは通ったものの、Titanic分析を完走するところまでは安定しなかったため、Qwen側はQwen Codeに切り替えています。
本記事では、その検証結果を共有します。
検証設定
実行環境
検証は以下の環境で実施しました。
| 項目 | 内容 |
|---|---|
| マシン | MacBook Pro M3 Max / 64GB |
| Codex CLI | 0.128.0 |
| Qwen Code | 0.16.2 |
| 推論サーバ | LM Studio OpenAI互換API |
| データセット | seaborn-dataのTitanic |
Qwen Codeについて
Qwen CodeはAlibabaのQwenチームが公開しているOSSのCoding Agent CLIで、QwenモデルのTool Call向けに最適化されています。Apache 2.0ライセンスで、ツール自体は無料で使えます。
ポイントは、モデルの動かし方が2通りあることです。
- Local実行: 今回のように手元のLM Studio / Ollamaなどを OpenAI互換APIとして繋ぐ。モデルが手元で動くので、APIコストはかからず、データも外に出ません。
- API経由: Alibaba CloudのDashScopeなどのクラウドAPIに繋ぐ。Qwen Code経由だと一定の無料枠(OAuth認証で1日あたりのリクエスト枠)が用意されています。
つまり「ローカルにモデルを置いて完全無料で回す」「クラウドの大きいモデルを無料枠で試す」のどちらも選べます。手元のマシンスペックに合わせて使い分けられるので、Codexの有料プランに手を出しづらい学生の方などには、こちらがメインの選択肢になり得ると思います。
Qwen CodeからはOpenAI互換APIとしてLM Studioに接続しています。
qwen \
--bare \
--auth-type openai \
--openai-base-url http://127.0.0.1:1234/v1 \
--openai-api-key lm-studio \
--model qwen3.6-27b-mtp \
--yolo
タスク
タスクはTitanicデータセットを使った生存予測です。
Agentには、単に分析方針を説明するだけでなく、report.mdに結果を書き出すように指示しました。
Agentへの指示
あなたはデータ分析Agentです。Titanicデータセットを使って、
生存予測に関する探索的データ分析、前処理、モデル構築、評価、
レポート作成を行ってください。
前提:
- 外部データを追加で使わず、与えられたTitanicデータのみを使う
- 実行可能性と再現性を重視する
- 入力データは data/titanic.csv
- Python実行ファイルはプロジェクト内の .venv/bin/python を使う
- alive は survived と同義の派生列なので、予測特徴量から除外する
要件:
1. データの形状、型、欠損値、基本統計量を確認する
2. 目的変数 survived との関係をEDAする
3. 欠損値処理とカテゴリ変数処理の方針を説明する
4. ベースラインモデルを作成する
5. 少なくとも1つの特徴量改善を試す
6. AccuracyとROC AUCを評価する
7. データリークを避ける
8. 実行可能なPythonコードを作成する
9. 最終レポートをMarkdownで作成する
10. 判断理由、限界、次に試すべきことも書く
成果物:
- analysis.py または analysis.ipynb
- report.md
- metrics.json
- notes.md
analysis.py を作る場合は、最後に自分で実行し、
成功したことを notes.md に記録する。
GPT-5.5 + Codex
まず、GPT-5.5 + Codexの結果です。実行時間は148.06sでした。
今回見たいのは「モデル精度が何点か」よりも、Data Scientistが最初にやるEDAをどれくらい任せられるかです。その観点では、Codex + GPT-5.5はかなり素直に期待した動きをしてくれたと思います。
Codexがreport.mdにまとめた主なEDA結果は以下です。
| 観点 | 結果(生存確率) |
|---|---|
| 性別 | female 0.742、male 0.1889 |
| 客室クラス | 1等 0.6296、2等 0.4728、3等 0.2424 |
| 乗船地 | C 0.5536、Q 0.3896、S 0.337 |
| 数値特徴量 | 生存者は平均運賃が高い |
加えて、単に集計するだけでなく、「性別は強い予測特徴量」「客室クラスは社会経済的proxy」といった解釈まで書けています。
report.md
Titanic Survival Prediction Report
1. Executive Summary
Titanicデータ data/titanic.csv の891行・15列を用いて、生存フラグ survived を予測する二値分類モデルを作成した。alive は survived と同義の派生列であるため、全モデルの特徴量から除外した。
同一の層化train/test分割(test_size=0.2, random_state=42)で比較した結果、ベースラインLogistic RegressionはAccuracy 0.7933、ROC AUC 0.8381、改善版はAccuracy 0.8045、ROC AUC 0.8469 だった。
2. Data Overview
- 形状: 891 rows x 15 columns
- 目的変数:
survived - 生存率: 0.3838
- 目的変数分布: 0=549, 1=342
Column Types
| index | value |
|---|---|
| survived | int64 |
| pclass | int64 |
| sex | str |
| age | float64 |
| sibsp | int64 |
| parch | int64 |
| fare | float64 |
| embarked | str |
| class | str |
| who | str |
| adult_male | bool |
| deck | str |
| embark_town | str |
| alive | str |
| alone | bool |
Missing Values
| index | value |
|---|---|
| deck | 688 |
| age | 177 |
| embarked | 2 |
| embark_town | 2 |
Numeric Summary
| index | survived | pclass | age | sibsp | parch | fare |
|---|---|---|---|---|---|---|
| count | 891 | 891 | 714 | 891 | 891 | 891 |
| mean | 0.3838 | 2.3086 | 29.6991 | 0.523 | 0.3816 | 32.2042 |
| std | 0.4866 | 0.8361 | 14.5265 | 1.1027 | 0.8061 | 49.6934 |
| min | 0 | 1 | 0.42 | 0 | 0 | 0 |
| 25% | 0 | 2 | 20.125 | 0 | 0 | 7.9104 |
| 50% | 0 | 3 | 28 | 0 | 0 | 14.4542 |
| 75% | 1 | 3 | 38 | 1 | 0 | 31 |
| max | 1 | 3 | 80 | 8 | 6 | 512.3292 |
Categorical Summary
| index | sex | embarked | class | who | adult_male | deck | embark_town | alive | alone |
|---|---|---|---|---|---|---|---|---|---|
| count | 891 | 889 | 891 | 891 | 891 | 203 | 889 | 891 | 891 |
| unique | 2 | 3 | 3 | 3 | 2 | 7 | 3 | 2 | 2 |
| top | male | S | Third | man | True | C | Southampton | no | True |
| freq | 577 | 644 | 491 | 537 | 537 | 59 | 644 | 549 | 537 |
3. EDA Findings
Survival by Sex
| sex | count | survival_rate |
|---|---|---|
| female | 314 | 0.742 |
| male | 577 | 0.1889 |
女性の生存率は男性より大きく、sex は強い予測特徴量と判断した。
Survival by Passenger Class
| pclass | count | survival_rate |
|---|---|---|
| 1 | 216 | 0.6296 |
| 2 | 184 | 0.4728 |
| 3 | 491 | 0.2424 |
客室クラスが上がるほど生存率が高い傾向があり、pclass は重要な社会経済的 proxy として扱った。
Survival by Embarked
| embarked | count | survival_rate |
|---|---|---|
| C | 168 | 0.5536 |
| Q | 77 | 0.3896 |
| S | 644 | 0.337 |
| 2 | 1 |
乗船地によって生存率に差がある。ただし欠損は2件のみなので、学習データ内の最頻値で補完する方針にした。
Numeric Means by Target
| survived | age | fare | sibsp | parch |
|---|---|---|---|---|
| 0 | 30.6262 | 22.1179 | 0.5537 | 0.3297 |
| 1 | 28.3437 | 48.3954 | 0.4737 | 0.4649 |
生存者は平均運賃が高く、fare は生存と関連している。age は177件欠損しており、中央値補完で扱った。
4. Preprocessing Design
- 数値変数: train foldで中央値補完し、Logistic Regression向けに標準化した。
- カテゴリ変数: train foldで最頻値補完し、未知カテゴリを許容するOneHotEncoderを使った。
- リーク対策:
survivedと同義のaliveは除外した。classはpclass、embark_townはembarkedと重複するため使わず、ベースラインでは重複を避けた。 - 欠損の多い
deck: 生のカテゴリとしては使わず、改善版では「deck情報が記録されているか」を表すhas_known_deckのみ使った。これは乗客データ内から作れる特徴量であり、目的変数を参照しない。 - 評価設計: 前処理はscikit-learn Pipeline内に入れ、imputer/encoder/scalerは学習データだけでfitされるため、test data leakageを避けている。
5. Models
Baseline
- Model: LogisticRegression
- Features: pclass, age, fare, sex
- Accuracy: 0.7933
- ROC AUC: 0.8381
Improved Feature Set
- Model: LogisticRegression
- Features: pclass, age, fare, sibsp, parch, family_size, is_alone_engineered, fare_log, has_known_deck, sex, embarked, age_group
- Added feature ideas: family size, engineered alone flag, log fare, known deck flag, age group, sibling/parent counts, embarked.
- Accuracy: 0.8045
- ROC AUC: 0.8469
6. Interpretation
改善版では、家族人数、運賃の歪みを抑えた fare_log、年齢帯、乗船地、deck記録有無を追加した。AccuracyとROC AUCの変化を見ることで、単なる閾値分類だけでなく順位性能も比較した。
このデータでは性別と客室クラスの説明力が大きい。改善版の特徴量はドメイン上妥当だが、テスト行数は179行と小さいため、単一分割の差は過信しない。
7. Limitations
- 単一のholdout評価であり、分割に依存する可能性がある。
- Titanicデータは小規模で、欠損や派生列が多い。
-
deckの欠損は非常に多く、欠損そのものが記録バイアスを含む可能性がある。 -
who,adult_male,aloneは既存列として便利だが、今回は特徴量改善の意図を明確にするため、独自に再計算できるものを中心に使った。
8. Next Steps
- Stratified K-Fold cross-validationで分割依存性を確認する。
- 正則化強度や木系モデル(RandomForest, GradientBoosting)を比較する。
- 年齢欠損の指示変数や、性別・クラス・年齢帯の交互作用を試す。
- 閾値を業務目的に合わせて調整し、混同行列やprecision/recallも確認する。
また以下のような可視化も行ってくれました。

Qwen3.6 + Qwen Code
次に、Qwen3.6 + Qwen Codeです。
実行時間はreal 601.76sで完走できたものの、EDAの中身として見ると、Codex + GPT-5.5とはかなり差がありました。
report.mdはデータサイズとモデル結果の要約が中心で、EDAの集計や解釈はほぼ書かれていませんでした。
report.md
Titanic Survival Analysis Report
Dataset Summary
- Rows: 891
- Columns: 15
Models Evaluated
Baseline Model
- Features: pclass, sex, age, fare
- Accuracy: 0.7877
- ROC AUC: 0.8383
Improved Model
- Additional features: female_1st (interaction), age_bin (binned age), log_fare (log transform)
- Accuracy: 0.7877
- ROC AUC: 0.8299
Conclusion
The improved model matched the baseline on accuracy (0.7877 vs 0.7877) and was slightly lower on ROC AUC (0.8299 vs 0.8383).
可視化も行なってくれましたが、Codex + GPT-5.5に比べると物足りなさが否めません。

結果比較
EDAを一覧で比較してみると、差が分かりやすくなりました。
| 観点 | Codex + GPT-5.5 | Qwen3.6 + Qwen Code |
|---|---|---|
| データ概要 | 形状、型、欠損、目的変数分布まで整理 | rows/columnsのみ |
| リーク検知 |
aliveを明示的に除外 |
report上では言及なし |
| 欠損理解 |
deck, age, embarked, embark_townを整理し、処理方針も説明 |
可視化時にSimpleImputerを追加 |
| EDA集計 | 性別、客室クラス、乗船地、運賃、年齢を数値で説明 | 図は生成するが、report内の数値解釈は薄い |
| 可視化の選択 | 5枚。sex x pclass、age、fare、family size、age missingness | 4枚。sex x pclass、age、fare、family size |
| 可視化の作り | fareはlog変換boxplot、family sizeにn表示、図ごとにkey findingあり | raw fare hist、別subplot age histなど素朴 |
| report品質 | Data Scientistが読める分析レポートに近い | 図とモデル結果の一覧に近い |
差は「図を作れるかどうか」よりも、「図から何を読み取るか」「次の前処理や特徴量設計にどうつなげるか」で大きく出ています。Codex + GPT-5.5は欠損、リーク、カテゴリ別の生存率、外れ値、特徴量設計までを一つの分析としてつないでいます。Qwen3.6 + Qwen Codeも図の生成とモデル実行はできていますが、図から読み取った内容のreport.mdへの反映は薄めです。
実行時間にも差がありました。Codex + GPT-5.5が 148.06s、Qwen3.6 + Qwen Codeが 601.76s で、4倍ほど開きがあります。複数回の試行錯誤を任せる場合、この差はそれなりに効きそうです。
まとめ
本記事では、Titanicデータを題材に、EDAをAI Agentに任せられるかという観点で、Codex + GPT-5.5とQwen Code + Qwen3.6を比較しました。
今回一番感じたのは、EDAをAgentに任せるときは「コードが動くか」だけでなく、「データを見て、解釈して、次の判断につなげられるか」を見ないといけない、ということです。
Codex + GPT-5.5は、可視化・考察・レポートまで一通り安定して任せられる印象でした。Qwen3.6 + Qwen Codeも、Local LLMとして可視化を含むEDAをローカルで最後まで完走できた点は意義があります。外部APIに出しにくいデータを扱う場面で、ローカル環境だけで図と最低限のレポートを出せるのは大きいと思います。ただし、report.mdはモデル結果の記述に寄りがちで、EDA結果の解釈はCodex + GPT-5.5より明らかに薄く、「動かせる」と「実務で任せられる」の間にはまだ距離がある、というのが正直なところです。
結論としては、可能であればフロンティアモデル(Codex + GPT-5.5など)を使うのが素直に良い、というのが今回の所感です。Local LLMでのEDA Agentも「できなくはない」水準には来ていますが、安定して任せるにはまだ厳しく、データを外に出せないなどの制約がある場合の現実的な選択肢、という位置づけだと感じました。
最後までお読みいただきありがとうございました!
Discussion