Gemini ProでKaggle初心者でもサクッとモデルをつくる

## 自動でこのコードをつくります

このプロンプトで以下のコードを自動生成します。
```py
text = """
# Read csv data as dataset from '/kaggle/input/titanic/train.csv' as train data and '/kaggle/input/titanic/test.csv' as test data.
# Using the dataset, test the Decision Tree, Random Forest, XGBoost and an ensemble of the three models to see which is the most accurate. 
# Before testing, use onehot encoding to categorical data columns.
# Before testing, drop object data columns like 'Name','Ticket' and 'Cabin' columns.
# Before testing, fill in any missing values with representative values
# The validation should be based on the average of the 4-fold cross-validation results.
# Run the generated code, and if an error occurs, repeat the modification until the error disappears
"""
```

<br>

**生成したコード**

```py
import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
import xgboost as xgb

# Read data
train = pd.read_csv('/kaggle/input/titanic/train.csv')
test = pd.read_csv('/kaggle/input/titanic/test.csv')

# Preprocessing
categorical_features = ['Sex', 'Embarked']
numerical_features = ['Age', 'Fare']

# Preprocessing for numerical data
numerical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='mean')),
                                     ('scaler', StandardScaler())])

# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='most_frequent')),
                                     ('onehot', OneHotEncoder(handle_unknown='ignore'))])

# Combine preprocessing for both types of data
preprocessor = ColumnTransformer(transformers=[
    ('numerical', numerical_transformer, numerical_features),
    ('categorical', categorical_transformer, categorical_features)
])

# Create a pipeline for each model
dtc_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                           ('classifier', DecisionTreeClassifier())])

rf_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                          ('classifier', RandomForestClassifier())])

xgb_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                           ('classifier', xgb.XGBClassifier())])

# Create a voting classifier
voting_clf = VotingClassifier(estimators=[('dt', dtc_pipeline), ('rf', rf_pipeline), ('xgb', xgb_pipeline)], voting='hard')

# Evaluate the models
models = [dtc_pipeline, rf_pipeline, xgb_pipeline, voting_clf]
for model in models:
    scores = cross_val_score(model, train.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1), train['Survived'], cv=4)
    print(f'{model.__class__.__name__}: {np.mean(scores)}')
```

## Kaggleのnotebook内でGemini Proを使ってみる
別の記事でOpen Interpreterを使った推論モデルの生成をやりました。この記事ではGemini Proでのモデル生成を試してみます。

https://qiita.com/yutowac/items/e7f5cd156bf3543bd3f4

GeminiはGoogleが開発した生成AIモデルです。Open Interpreter同様、対話形式で簡単に推論モデルを生成することが可能です。以下はそのイメージです。`text`に具体的な指示を書いていきます。

```py
import google.generativeai as genai
model = genai.GenerativeModel('gemini-pro')
text = """
データを解析して
"""
response = model.generate_content(text)
```

実際のコンペの動きを仮定して、Kaggleのチュートリアルとも言われる[**Titanicのコンペ**](https://www.kaggle.com/competitions/titanic)でGeminiを動かしてみます。

<br>

コンペのwebサイトからnotebookを作成し、Titanicデータにアクセスできる状態でスタートします。Inputにtrain.csvやtest.csvがある状態です。

<br>

<img width="80%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/e4fe2dce-e794-d75f-074f-43df02068d2b.png">

### Gemini Proについて
#### Geminiの概要
GeminiはGoogle ResearchやDeepMind、Brain TeamなどのGoogle傘下の組織で開発された生成AIモデルです。
以下のような特徴が挙げられます。
- Ultra、Pro、Nanoの3つのサイズがあり、UltraはOpenAIのGPT-4Vとの性能比較で圧勝した
- 文章・音声・画像・動画などマルチモーダルに対応


<img width="55%" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/986141/a178e666-d029-4351-9195-712052bb03a3.png">

https://youtu.be/jV1vkHv4zq8

### Gemini Pro
UltraとNanoの間にある中規模モデルで性能とコストのバランスが良いとされています。

## APIキーの取得
[Google AI Studio](https://ai.google.dev/?hl=en)でAPIキーを取得できます。

https://ai.google.dev/?hl=en

## 簡単なプロンプトでコーディング
パッケージのimportなどの準備段階です。
```py
#必要なパッケージの取得
import pathlib
import textwrap
import google.generativeai as genai
from IPython.display import display
from IPython.display import Markdown
def to_markdown(text):
    text = text.replace('•', '  *')
    return Markdown(textwrap.indent(text, '> ', predicate=lambda _: True))
# 自身のOpenAIのAPI-keyの入力
api_key = "API_KEY"
genai.configure(api_key=api_key)
# モデルの選択。他にもclaude-2やcommand-nightlyなど
model = genai.GenerativeModel('gemini-pro')
```

そして、指示内容です。この内容を大規模言語モデルが解釈し、プログラムを作成し実行します。**「データを読み込み、決定木分析・ランダムフォレスト・XGboostでアンサンブル学習を行い、k-fold交差検証をし、最も精度の高いモデルとそのコードを保存して」** という内容です。
```py
# プロンプト入力例
text = """
# Read csv data as dataset from '/kaggle/input/titanic/train.csv' as train data and '/kaggle/input/titanic/test.csv' as test data.
# Using the dataset, test the Decision Tree, Random Forest, XGBoost and an ensemble of the three models to see which is the most accurate. 
# Before testing, use onehot encoding to categorical data columns.
# Before testing, drop object data columns like 'Name','Ticket' and 'Cabin' columns.
# Before testing, fill in any missing values with representative values
# The validation should be based on the average of the 4-fold cross-validation results.
# Run the generated code, and if an error occurs, repeat the modification until the error disappears
"""

# resultで結果を受け取る
result = model.generate_content(text)
```

生成されるコードと上記のプロンプトの対応関係を解説していきます！

## 解説
### データの読み込み

:::note info
`# Read csv data as dataset from '/kaggle/input/titanic/train.csv' as train data and '/kaggle/input/titanic/test.csv' as test data.`
ディレクトリやどのファイルが学習データ、テストデータなのかを明記した方が良いです。
:::

<details><summary>生成したコード</summary>

```py
import pandas as pd
# Read data
train = pd.read_csv('/kaggle/input/titanic/train.csv')
test = pd.read_csv('/kaggle/input/titanic/test.csv')
```
</details>

:::note warn
`# Read Titanic dataset`
これでも読み込むことができる場合がありますが、作業しているのnotebookにあるtrain.csvやtest.csvを解釈しているわけではありません。汎用的にコンペで利用する場合は、ディレクトリを指定するようにしましょう。
:::



### 学習・検証
:::note info
`# Using the dataset, test the Decision Tree, Random Forest, XGBoost and an ensemble of the three models to see which is the most accurate.  `
`# Before testing, use onehot encoding to categorical data columns.`
`# Before testing, drop object data columns like 'Name','Ticket' and 'Cabin' columns.`
`# Before testing, fill in any missing values with representative values.`
`# The validation should be based on the average of the 4-fold cross-validation results.`
ここでは決定木分析とランダムフォレスト、XGBoostで最も精度の高いモデルを選ぶ指示を出しています。LightBGM、CatBoostなどもOKです。バリデーション手法も明記すると良いです。前処理に関してはエラーを上手く修正しなかったので具体的に情報を与えました。
:::

<details><summary>生成したコード</summary>

```py
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.compose import ColumnTransformer
from sklearn.pipeline import Pipeline
from sklearn.impute import SimpleImputer
from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier, VotingClassifier
import xgboost as xgb

# Preprocessing
categorical_features = ['Sex', 'Embarked']
numerical_features = ['Age', 'Fare']

# Preprocessing for numerical data
numerical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='mean')),
                                     ('scaler', StandardScaler())])

# Preprocessing for categorical data
categorical_transformer = Pipeline(steps=[('imputer', SimpleImputer(strategy='most_frequent')),
                                     ('onehot', OneHotEncoder(handle_unknown='ignore'))])

# Combine preprocessing for both types of data
preprocessor = ColumnTransformer(transformers=[
    ('numerical', numerical_transformer, numerical_features),
    ('categorical', categorical_transformer, categorical_features)
])

# Create a pipeline for each model
dtc_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                           ('classifier', DecisionTreeClassifier())])

rf_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                          ('classifier', RandomForestClassifier())])

xgb_pipeline = Pipeline(steps=[('preprocessor', preprocessor),
                           ('classifier', xgb.XGBClassifier())])

# Create a voting classifier
voting_clf = VotingClassifier(estimators=[('dt', dtc_pipeline), ('rf', rf_pipeline), ('xgb', xgb_pipeline)], voting='hard')

# Evaluate the models
models = [dtc_pipeline, rf_pipeline, xgb_pipeline, voting_clf]
for model in models:
    scores = cross_val_score(model, train.drop(['PassengerId', 'Name', 'Ticket', 'Cabin'], axis=1), train['Survived'], cv=4)
    print(f'{model.__class__.__name__}: {np.mean(scores)}') 
```
</details>

:::note warn
`# Using the dataset, make one accurate model. `
`# The validation method is k-fold cross-validation.`
モデルを一つしか試さないなど性能面で問題があったり、何度もエラーに対して修正を加えたりなど、うまく生成しないことがあるので、確定できる要素は具体的に書きましょう。
:::

## どれくらいの性能だったか
3つのモデルからアンサンブルで1つのモデルをつくりました。Kaggle内で公開されているモデルよりは低いスコアですが、エラーのなく、調整もしやすいコードが生成されました。ここまでをサッと作れるとしたら非常に強力です。
```
Pipeline: 0.7418949218276573 # 決定木分析
Pipeline: 0.7744162323758736 # ランダムフォレスト
Pipeline: 0.7834050418131135 # XGBoost
VotingClassifier: 0.7733002060356321
```

## つまづきポイント
欠損値補完が思うようにいきませんでした。データ型に関わらず平均値補完をして、文字列のデータが保管できないなどがありました。そういった列は、dropする、もしくは代表値で埋める、無意味な文字列で埋めるなどを検討しましたが、いずれも実行されませんでした。プロンプトの上手い書き方を工夫すれば解決するかもしれません。