見出し画像

ChatGPTに教えてもらった短いコードを思った以上に修正した話

※カバー画像は「プログラミングは楽しい! それが伝わるピクトグラムを作成してください。 共通のアイコンにします。」とChatGPT 4に依頼しました。


使用したのは「ChatGPT 3.5」です。
短いプログラムのコードに関する質問だったので3.5で十分だと思いました。

Pythonコードを教えてもらう

まず、ChatGPT 3.5に以下の依頼。

勾配ブースティングを scikit-learnのサンプルデータセットで試したいです。
やさしくコードを教えてください。

何度かやりとりし出来上がったコードが以下です。

(今回、データの内容には触れないのでBoston Housingデータセットを使っていますが、現在では非推奨になっています。scikit-learnの推奨はCalifornia Housingデータセットです。コードに使っているBoston HousingデータセットのURLは、scikit-learnのメッセージから取得しました)

import pandas as pd
from urllib.request import urlopen
from sklearn.model_selection import train_test_split
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.metrics import mean_squared_error
from sklearn.impute import SimpleImputer

# bostonデータセットのURL
url = "http://読み込み先のURL"

# データセットを直接読み込む
# 区切り文字を正規表現\s+(空白文字1つ以上)、ファイルの先頭から22行をスキップ
boston_df = pd.read_csv(url, sep="\s+", skiprows=22, header=None)

# 本来1行のデータが2行に分かれている。その対処
# 奇数行と偶数行のデータを結合して新しいデータフレームを作成
new_boston_df = pd.concat([boston_df.iloc[::2].reset_index(drop=True), boston_df.iloc[1::2].reset_index(drop=True)], axis=1)

# col_15  col_16  col_17  col_18  col_19  col_20 が不要なので削除
new_boston_df = new_boston_df.iloc[:, :14]

# prompt: データフレームに列名 CRIM,ZN,INDUS,CHAS,NOX,RM,AGE,DIS,RAD,TAX,PTRATIO,B,LSTAT,MEDV をつけたい
new_boston_df.columns = ["ex_var01", "ex_var02", "ex_var03", "ex_var04", "ex_var05", "ex_var06", "ex_var07", "ex_var08", "ex_var09", "ex_var10, "ex_var11", "ex_var12", "ex_var13", "TARGET"]

# 特徴量とターゲット変数の分割
X = new_boston_df.iloc[:, :-1]
y = new_boston_df.iloc[:, -1]

# データの分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# 欠損値を平均値で補完するImputerのインスタンスを作成
imputer = SimpleImputer(strategy='mean')

# 欠損値の補完
X_train_imputed = imputer.fit_transform(X_train)
X_test_imputed = imputer.transform(X_test)

# ターゲット変数の欠損値を補完
# imputer.fit_transform()関数を使用して、y_trainデータの欠損値を補完
# 以下をトレーニングデータセット、テストデータセットとして使う
y_train_imputed = imputer.fit_transform(y_train.values.reshape(-1, 1)).flatten()
y_test_imputed = imputer.transform(y_test.values.reshape(-1, 1)).flatten()

# 勾配ブースティングのモデルの定義と学習
gb_model = GradientBoostingRegressor(n_estimators=100, learning_rate=0.1, max_depth=3, random_state=42)
gb_model.fit(X_train_imputed, y_train_imputed)

# モデルの評価
# トレーニングデータセット (X_train_imputed, y_train_imputed) を使って学習予測した値と実際のターゲット値間の平均二乗誤差を計算
# テストデータセット (X_test_imputed, y_test_imputed) を使って学習予測した値と実際のターゲット値の間の平均二乗誤差を計算
train_mse = mean_squared_error(y_train_imputed, gb_model.predict(X_train_imputed))
test_mse = mean_squared_error(y_test_imputed, gb_model.predict(X_test_imputed))

print("Train MSE:", train_mse)
print("Test MSE:", test_mse)

勾配ブースティングには「GradientBoostingRegressor」を使っています。
xgBoost」というライブラリもあります。
最後に少し触れておきます。

Rのコードを教えてもらう

スムーズに進んだので、R言語でも30分もかからないかと思い、
上記コードをコピペして、

以下コードをR言語で実行できるようにしたいです。

とChat GPT3.5に投げました。
回答はすぐでした。

# 必要なライブラリをインストール
install.packages("data.table")
install.packages("imputeTS")
install.packages("caret")
install.packages("gbm")

# 必要なライブラリを読み込み
library(data.table)
library(imputeTS)
library(caret)
library(gbm)

# BostonのデータセットのURL
url <- "http://読み込み先のURL"

# データセットを直接読み込む
boston_df <- fread(url)

# 奇数行と偶数行を分割
odd_rows <- boston_df[seq(1, nrow(boston_df), by=2), ]
even_rows <- boston_df[seq(2, nrow(boston_df), by=2), ]

# 列名を設定
colnames(odd_rows) <- colnames(even_rows) <- c("ex_var01", "ex_var02", "ex_var03", "ex_var04", "ex_var05", "ex_var06", "ex_var07", "ex_var08", "ex_var09", "ex_var10, "ex_var11", "ex_var12", "ex_var13", "TARGET")


# 特徴量(説明変数)とターゲット変数の分割
X <- odd_rows[, -14]
y <- odd_rows[, 14]

# データの分割
set.seed(42)
train_index <- createDataPartition(y, p = 0.8, list = FALSE)
X_train <- X[train_index, ]
X_test <- X[-train_index, ]
y_train <- y[train_index]
y_test <- y[-train_index]

# 欠損値を平均値で補完
X_train_imputed <- na_mean(X_train)
X_test_imputed <- na_mean(X_test)

# 勾配ブースティングのモデルの定義と学習
gb_model <- gbm(TARGET ~ ., data = odd_rows, distribution = "gaussian", n.trees = 100, interaction.depth = 3, shrinkage = 0.1, verbose = FALSE)

# モデルの評価
train_pred <- predict(gb_model, X_train_imputed, n.trees = 100)
test_pred <- predict(gb_model, X_test_imputed, n.trees = 100)
train_mse <- mean((y_train - train_pred)^2)
test_mse <- mean((y_test - test_pred)^2)

print(paste("Train MSE:", train_mse))
print(paste("Test MSE:", test_mse))

しかし、このままでは動かきません。
以下を修正しました。

  • データ読み込み時のskip

  • 奇数行と偶数行を分割した後の結合

  • 不要な列の削除

  • 特徴量(説明変数)の設定

  • 勾配ブースティングのモデルの定義と学習の設定

skipの修正

元のデータはデータの上に項目の説明などが入っているので、20行近くスキップする必要があります。
それが抜けていました。
ChatGPTにPythonのコードを教えてもらった時は自動でスキップの値が入りました。

データフレーム結合の修正

本来1行に収まるはずのデータが、2行に分かれていました。
ChatGPTに「偶数行と奇数行のデータフレームに分けて、偶数行のデータフレームの右側に奇数行のデータフレームを結合」する方法を教えてもらい、Pythonコードでは対処しています。
その処理がRのコードでは入っていません。
このため、以降の処理も分割したデータフレームの一方だけを使う記述になっていました。

不要な列の削除処理の修正

上記のデータフレームの結合の際、後ろに不要な列(欠損値NAしかない列)ができてしまいます。
削除する必要がありました。

特徴量(説明変数)のデータフレーム生成の設定修正

特徴量のトレーニングデータとテストデータのデータフレームの設定は、
X_train <- X[train_index, ]
X_test <- X[-train_index, ]
という記述になっています。
しかし、「X」は説明変数なのでトレーニングデータとテストデータにはなりません(目的変数が抜けています)。

勾配ブースティングのモデルの定義と学習の設定修正

上記のように修正が必要な箇所があったので、最後の仕上げである勾配ブースティングモデルの構築式も間違っていました。

修正を反映したRのコードです。
### ●xxxxx ### という記述が主な修正箇所です。

# 必要なライブラリをインストール
# imputeTS: 欠損値を補完するためのパッケージです。時間系列データの欠損値を補完する機能を提供します。
# caret: 機械学習モデリングのためのパッケージで、さまざまな機械学習アルゴリズムを簡単に使用できるようにするためのツールセットを提供します。モデルのトレーニング、評価、チューニングなどをサポートします。
# gbm: 勾配ブースティングマシン(Gradient Boosting Machine)の実装であるパッケージです。このパッケージを使用すると、勾配ブースティングに基づく回帰および分類モデルを構築できます。
install.packages("tidyverse")
install.packages("imputeTS")
install.packages("caret")
install.packages("gbm")

# 必要なライブラリを読み込み
library(tidyverse)
library(imputeTS)
library(caret)
library(gbm)

# BostonのデータセットのURL
url <- "http://読み込み先のURL

# データセットを直接読み込む
# read_csvはカンマ区切り用なのでread_tableを使う
### ●skipの設定を追記 ###
boston_df <- read_table(url, skip = 21)

# 奇数行と偶数行を分割
#odd_rows <- boston_df %>% slice(seq(1, n(), by = 2))
#even_rows <- boston_df %>% slice(seq(2, n(), by = 2))
#filter 関数を使用して奇数行と偶数行を分割することもできます。以下はその方法です。
odd_rows <- boston_df %>% filter(row_number() %% 2 != 0) # %% 演算子は剰余を計算
even_rows <- boston_df %>% filter(row_number() %% 2 == 0)

# even_rowsをodd_rowsの後ろに連結
### ●データフレームの結合処理を追記 ###
boston_df <- bind_rows(odd_rows, even_rows)

# 15列目以降は不要
### ●不要な列を削除する処理を追記 ###
boston_df <- boston_df[,-c(15,16,17,18,19,20,21,22)]

# 列名を設定
colnames(boston_df)<- c("ex_var01", "ex_var02", "ex_var03", "ex_var04", "ex_var05", "ex_var06", "ex_var07", "ex_var08", "ex_var09", "ex_var10, "ex_var11", "ex_var12", "ex_var13", "TARGET")

# 特徴量とターゲット変数の分割
X <- boston_df %>% select(-TARGET)
y <- boston_df$MTARGET

# データの分割
# list = FALSEは、分割されたインデックスをリストではなくベクトルで返すことを指定します。
# これにより、インデックスのみが返され、トレーニングセットやテストセットのデータが直接返されるわけではありません
set.seed(42)
train_index <- createDataPartition(y, p = 0.8, list = FALSE)
### ●トレーニング、テストデータを「X」からでなく「boston_df」から生成するように変更 ###
X_train <- boston_df[train_index, ]
X_test <- boston_df[-train_index, ]
y_train <- y[train_index]
y_test <- y[-train_index]

# 欠損値を平均値で補完
# na_mean()関数は、欠損値を含むデータの各列の欠損値をその列の平均値で補完する関数
# 上記はimputeTSパッケージ
X_train_imputed <- na_mean(X_train)
X_test_imputed <- na_mean(X_test)

# 勾配ブースティングのモデルの定義と学習
### ●学習に使うデータが「data = odd_rows」となっていたので「data = X_train_imputed」 に ###
gb_model <- gbm(MEDV ~ ., data = data = X_train_imputed, distribution = "gaussian", n.trees = 100, interaction.depth = 3, shrinkage = 0.1, verbose = FALSE)

# モデルの評価
train_pred <- predict(gb_model, X_train_imputed, n.trees = 100)
test_pred <- predict(gb_model, X_test_imputed, n.trees = 100)
# 平均二乗誤差
train_mse <- mean((y_train - train_pred)^2)
test_mse <- mean((y_test - test_pred)^2)

print(paste("Train MSE:", train_mse))
print(paste("Test MSE:", test_mse))

Rでは、なんだかんだで1時間半程度かかりました。
プロンプトの内容を工夫すればもっとスムーズに進んだかもしれません。
ただ、普段使わないPythonとR、これまた滅多に使わない機械学習のコード。
これらを思いつきでを試そうとして数時間で済んだのですから、生成AIには敬服します。


xgboost と GradientBoostingRegressor は違いますか?(ChatGPTに質問)

ChatGPT
はい、xgboost(eXtreme Gradient Boosting)とGradientBoostingRegressorは異なるライブラリやフレームワークであり、異なる実装を提供していますが、基本的なアルゴリズムは類似しています。以下にそれぞれの特徴を説明します。

  1. GradientBoostingRegressor:

    • GradientBoostingRegressorは、scikit-learnライブラリに含まれる機械学習モデルの一つです。

    • GradientBoostingRegressorは、勾配ブースティングと呼ばれるアンサンブル学習アルゴリズムを実装しています。

    • 勾配ブースティングは、弱い学習器(通常は決定木)を組み合わせて強力なモデルを構築します。各決定木は前の決定木の誤差を修正するようにトレーニングされます。

    • データセットが小さい場合や特徴量の数が比較的少ない場合に適しています。

  2. xgboost:

    • xgboostは、eXtreme Gradient Boostingの略で、勾配ブースティングを高速かつ効率的に実装したライブラリです。

    • xgboostは、C++で実装された高速な勾配ブースティングライブラリであり、Pythonなどのさまざまなプログラミング言語から利用できます。

    • xgboostは、勾配ブースティングの効率的な実装やハイパーパラメータのチューニング機能、特徴量の重要度の計算など、多くの機能を提供しています。

    • 大規模なデータセットや高次元の特徴空間において、高速でスケーラブルなモデルの構築が可能です。

両方のライブラリは勾配ブースティングを実装していますが、xgboostは一般にパフォーマンスや機能面で優れていると考えられています。ただし、使用する状況や要件によって、どちらを選択するかが異なる場合があります。

この記事が気に入ったらサポートをしてみませんか?