NTTドコモR&Dの技術ブログです。

VSCodeにGithubCopilotを導入してデータ分析してみた

はじめに

この記事は2024年ドコモアドベントカレンダー17日目の記事になります。

みなさんこんにちは、NTTドコモ クロステック開発部の島崎正太です。普段の業務では、位置情報データを用いた分析や機械学習モデルの開発を担当しています。

ドコモの研究・開発業務では自分で手を動かしてコーディングすることが多いのですが、業務でたくさんのコードを短時間で書く必要がある中で少しでも効率的にコードを書きたいと思い、巷で噂のGithub Copilotを試してみました。 今回は、機械学習でよく使われるscikit-learnの公開データ「カリフォルニア住宅価格データセット」を使ってGithub Copilotの便利さをお伝えできればと思います。

※Github Copilotはコーディングの効率を大幅に向上させるツールですが、ミスやバグも多いです。使用する場合はコードの品質・ライセンスなどを常に確認し、自分が理解できる範囲で使用しましょう。

対象者

  • Github Copilot導入に悩んでいる方
  • データ分析初学者

内容

  • VSCode上でGithub Copilotに指示を出して、機械学習の回帰モデルを作成(してもらう)
  • 予測精度や結果の可視化などのpythonコーディングを実施(してもらう)

Github Copilotとは

GitHub CopilotはGitHubとOpenAIが共同開発したAIアシスタント(コードエディタ拡張機能)で、コード提案やコード自動生成によってコーディングを効率化するための有料ツールです。

GitHub Copilotの特徴

GithubCopilotはスクリプト中にこれまで自分が定義してきた変数を理解した上で、その変数を使って新たな1.コードの生成や2.コードの補完をしてくれるところが一番の特徴かと思います。
また自身の用意した複雑なデータセットに対して特定のライブラリやフレームワークを使いたい時などは、 Github Copilotが適切なInputに変換してくれるのでかなりの作業効率化に繋がると思います。

1. 自然言語からコード自動生成

コメントとして自然言語(日本語、英語など)で意図を記述すると、それに対応するコードを生成します。
やや複雑な日本語でもすんなりと理解して対応してくれます。
例: 「リストの値を、1番大きい値、次に1番小さい値、その次に2番目に大きい値、次に2番目に小さい値…という順番に並び替えて」と書くだけで、対応するコードを自動生成。

やや複雑な日本語からコードを生成

2. コード自動提案(補完)

開発中のコードに基づいて、次に書くべきコードを提案します。 例えば、関数の続きを自動生成したり、テンプレートコードを補完します。

次に書くであろうコードを提案(灰色のテキストとして表示)

3. 多言語対応

Python、JavaScript、TypeScript、Go、Ruby、Java、C++など、多くのプログラミング言語をサポートしています。

4. 広範なデータベースで学習

GitHubに公開されている多くのコードリポジトリから学習しており、幅広いプログラミングスタイルやタスクに対応。

「カリフォルニア住宅価格データセット」を使った回帰分析

今回はGithub Copilotに自然言語(日本語)で指示を与え、簡単に回帰問題を解いてみたいと思います。

カリフォルニア住宅価格データセット

scikit-learnは無料で使えるPythonのオープンソース機械学習ライブラリです。今回はその中でも「california housing dataset」(カリフォルニア住宅価格データセット)を用いて回帰分析に取り組みます。
実際のデータのカラム構成は以下のようになっています。

カラム 説明
Medlnc 地域の世帯収入の中央値
HouseAge 地域の住宅の築年数の中央値
AveRooms 世帯ごとの平均部屋数
AveBedrms 世帯ごとの平均寝室数
Poplation 地域の人口数
AveOcuup 世帯ごとの平均居住者数
Latitude 地域の緯度
Longitude 地域の経度
MedHouseVal 住宅価格の中央値

問題設定

データセットに含まれるMedInc、HouseAge、AveRooms、AveBedrms、Population、AveOccup、Latitude、Longitudeの変数から、MedHouseVal(住宅価格)を予測することが最終目標です。

※記事内では、コードやプロンプトを画像で表示していますが、記事の最後にコピペできる形式でまとめています。必要に応じてそちらもご参照ください。

データの読み込み

まずはscikit-learnからデータセットを読み込んで中身を確認してみましょう。
これくらいの雑な日本語でも頑張って理解してくれます。

「カリフォルニア住宅データセットを読み込んで中身を教えて」と指示

薄いグリーンのハイライトがかかっている箇所がCopilotの提案してくれたコードになります。
「同意する」をクリックすると、そのコードがスクリプトに反映されます。
実行した結果が以下になります。変数名も自動でつけてくれるので便利ですね。
MedHouseValをtargetというカラム名にして出力してくれましたが、特に問題ないと思います。

出力結果




ちなみにGithub Copilotを導入すると、VSCode上でもChatGPTを使うことができます。
こちらもユーザが定義した変数を理解した上で質問を投げることができるので非常に使いやすいかと思います。

①を押すと②ChatGPTのプロンプト入力画面が表示される

基礎集計

次にscikit-learnから読み込んだデータセット(california_housing_df)の基礎集計をお願いしてみましょう。

「基礎集計と可視化」を指示

出力した結果は以下になります。
基本統計量(データ数、平均値、標準偏差、最小値、パーセンタイル値、最大値)を出してくれて、その結果をboxplotで出力してくれました。

基本統計量

summary_statsのboxplot

今回はデータの傾向がパッと確認できれば十分なので、各プロットにキャプションがついているだけでOKかなと思います。プロットの指示は細かく出せば、文字サイズや色の変更までしてくれます。
基礎集計やプロットの結果から外れ値などを検出し、必要に応じてデータセットから取り除くこともありますが今回は割愛します。
(例えばAveRoomsが100を超えているものは外れ値として取り除いた方が良いかもしれないですね。Copilotに指示するとやってくれると思います。)

ついでに、変数同士の相関も確認しておきましょう。

「変数同士の相関係数のプロット」を指示
出力結果

小数点2桁までを表示するなど、細かい設定も配慮してくれてますね。優秀!
相関行列への考察もCopilotにお願いしてみました。

相関行列からわかることを考察します。

考察
1.強い相関関係:

  • 相関行列の値が1に近い場合、2つの特徴量間には強い正の相関があります。例えば、MedInc(Median Income)とAveRooms(Average Rooms per Household)などが強い相関を示す場合があります。これは、収入が高い地域では、一般的に部屋数が多い家が多いことを示唆しています。

2.弱い相関関係:

  • 相関行列の値が0に近い場合、2つの特徴量間にはほとんど相関がありません。例えば、AveOccup(Average Occupancy)とHouseAge(House Age)などが弱い相関を示す場合があります。これは、家の年齢と平均占有率には直接的な関係がないことを示唆しています。

3.負の相関関係:

  • 相関行列の値が-1に近い場合、2つの特徴量間には強い負の相関があります。例えば、AveRooms(Average Rooms per Household)とAveOccup(Average Occupancy)が負の相関を示す場合があります。これは、部屋数が多い家では、平均占有率が低いことを示唆しています。

4.ターゲット変数との相関:

  • ターゲット変数(MedHouseVal)と他の特徴量との相関を確認することで、住宅価格に最も影響を与える特徴量を特定できます。例えば、MedInc(Median Income)とMedHouseVal(Median House Value)が強い正の相関を示す場合、収入が高い地域では住宅価格も高いことを示唆しています。 これらの考察を基に、回帰分析の前処理や特徴量選択を行うことで、モデルの性能を向上させることができます。

それっぽいことを言っているような気がしますが、ここでは深く触れないでおきます。

モデリング~簡易精度評価

重回帰モデルの作成を指示
まずは重回帰のモデルを作成してもらいました。データのクレンジングや特徴選択などもしていないので、精度は以下のような結果に。

Mean Squared Error: 0.5558915986952443  
R^2 Score: 0.5757877060324508

比較のためにLightGBMでも予測してみました。
MSEとR2スコアの値だけだと直感的にわかりづらいので、散布図も書いてもらうことにします。

LightGBMモデルの作成を指示

LightGBM Mean Squared Error: 0.18744789596572572
LightGBM R^2 Score: 0.8569546614238275

LightGBMの方が明らかに精度が良いですね。

散布図(重回帰モデル vs LightGBMモデル)

散布図はy軸が重回帰分析とLightGBMで異なっています。 Copilotは非常に優れたツールですが、稀にミスが発生することもあるため、全てを任せるのは危険かもしれないですね。人のチェックは必須かと思います。

最後に、特徴量の重要度を可視化してみましょう。

「特徴量重要度の確認」を指示

出力結果は以下になります。

feature_importance(split)

ここではLightGBMのfeature_importance(各特徴量が決定木分割に使用された回数)を特徴量の重要度としているようです。

使用したプロンプトとコード

今回は6行の自然言語(日本語)のみですべてのコードの生成を行いました。
雑なプロンプトでも想像以上にコーディングの助けになると思います。
グラフの軸のずれなどたまにうまくいかないこともありますが、あくまでCopilot(副操縦士)なのでコードの品質などはしっかりとチェックした上で使用することをお勧めします。

  • prompt①:データセット取得
### prompt: カリフォルニア住宅価格データセットを読み込んで、中身を教えて ###

from sklearn.datasets import fetch_california_housing
import pandas as pd

# カリフォルニア住宅価格データセットを読み込む
california_housing = fetch_california_housing()

# データセットの中身を表示する
print(california_housing.DESCR)

# データをDataFrameに変換する
california_housing_df = pd.DataFrame(california_housing.data, columns=california_housing.feature_names)
california_housing_df['target'] = california_housing.target

# DataFrameの最初の5行を表示する
california_housing_df.head()



  • prompt②:基礎集計を実施
### prompt: california_housing_dfの各カラムを基礎集計をして、その結果を各カラムごとにboxplotで可視化して ###

# 各カラムの基礎集計を表示
summary_stats = california_housing_df.describe()
display(summary_stats)

# 各カラムごとにboxplotを作成
california_housing_df.plot(kind='box', subplots=True, layout=(3, 3), figsize=(15, 15), sharex=False, sharey=False)
plt.tight_layout()
plt.show()



  • prompt③:変数同士の相関係数をプロット
### prompt: 各変数の相関をプロットして ###

import seaborn as sns

import matplotlib.pyplot as plt

# 各変数の相関を計算
correlation_matrix = california_housing_df.corr()

# ヒートマップをプロット
plt.figure(figsize=(10, 8))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', fmt='.2f')
plt.title('Correlation Matrix of California Housing Dataset')
plt.show()



  • prompt④:重回帰分析モデルの作成
### prompt: MedHouseValを予測する重回帰分析モデルを作成して ###

from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
from sklearn.metrics import mean_squared_error, r2_score

# 特徴量とターゲットに分ける
X = california_housing_df.drop('MedHouseVal', axis=1)
y = california_housing_df['MedHouseVal']

# 訓練データとテストデータに分割
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

# モデルの作成と訓練
model = LinearRegression()
model.fit(X_train, y_train)

# 予測
y_pred = model.predict(X_test)

# モデルの評価
mse = mean_squared_error(y_test, y_pred)
r2 = r2_score(y_test, y_pred)

print(f'Mean Squared Error: {mse}')
print(f'R^2 Score: {r2}')



  • prompt⑤:LightGBMモデルの作成と比較
### prompt: LightGBMでもモデルを作って精度を比較して。両方散布図でプロットして ###

import lightgbm as lgb

# LightGBMのデータセットを作成
train_data = lgb.Dataset(X_train, label=y_train)
test_data = lgb.Dataset(X_test, label=y_test, reference=train_data)

# LightGBMのパラメータ
params = {
    'objective': 'regression',
    'metric': 'rmse',
    'boosting_type': 'gbdt',
    'num_leaves': 31,
    'learning_rate': 0.05,
    'feature_fraction': 0.9
}

# LightGBMモデルの訓練
lgb_model = lgb.train(params, train_data, valid_sets=[test_data], num_boost_round=1000)

# LightGBMモデルの予測
y_pred_lgb = lgb_model.predict(X_test, num_iteration=lgb_model.best_iteration)

# LightGBMモデルの評価
mse_lgb = mean_squared_error(y_test, y_pred_lgb)
r2_lgb = r2_score(y_test, y_pred_lgb)

print(f'LightGBM Mean Squared Error: {mse_lgb}')
print(f'LightGBM R^2 Score: {r2_lgb}')

# 両方のモデルの予測結果を散布図でプロット
plt.figure(figsize=(12, 6))

# Linear Regressionの予測結果
plt.subplot(1, 2, 1)
plt.scatter(y_test, y_pred, alpha=0.3)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('Linear Regression')

# LightGBMの予測結果
plt.subplot(1, 2, 2)
plt.scatter(y_test, y_pred_lgb, alpha=0.3)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('Actual')
plt.ylabel('Predicted')
plt.title('LightGBM')

plt.tight_layout()
plt.show()



  • prompt⑥:特徴量重要度の可視化
### prompt: 何が予測に重要な変数だったか教えて ###

# 特徴量の重要度を取得
importance = lgb_model.feature_importance()
feature_names = X_train.columns

# 特徴量の重要度をデータフレームに変換
importance_df = pd.DataFrame({'Feature': feature_names, 'Importance': importance})

# 特徴量の重要度を降順にソート
importance_df = importance_df.sort_values(by='Importance', ascending=False)

# 特徴量の重要度を表示
print(importance_df)

# 特徴量の重要度をプロット
plt.figure(figsize=(10, 6))
sns.barplot(x='Importance', y='Feature', data=importance_df)
plt.title('Feature Importance')
plt.show()

まとめ

本記事ではVSCode上で機能するGithubCopilotを紹介しました。 GithubCopilotはスクリプト中にこれまで自分が定義してきた変数を理解した上で、その変数を使って新たな1.コードの生成や2.コードの補完をしてくれるところが一番の特徴かと思います。
自身の用意した複雑なデータセットに対してライブラリやフレームワークを当てはめたい時、どうやって前処理したら良いかわからない時などは ライブラリやフレームワークの使用法を簡単に習得できると思います。

また今回はさらっと紹介しましたが、コード補完の的確さは凄まじいです。次に書きたかったコードを予測して提案してくれるので、かなりの効率化につながっています。ぜひ皆様もお試しください!

※Github Copilotはコーディングの効率を大幅に向上させるツールですが、ミスやバグも多いです。使用する場合はコードの品質・ライセンスなどを常に確認し、自分が理解できる範囲で使用しましょう。

それでは、良いクリスマスを🎅