【Scikit-learn】単回帰分析を行う方法

Pythonライブラリ「scikit-learn」で単回帰分析を行う方法についてサンプルコード付きで解説します。

単回帰分析とは

以下の図は、VTuberの「チャンネル登録者数」から「視聴者数」を予測する単回帰モデルを作成するイメージです。

単回帰分析(Simple Linear Regression)では、1つの特徴量($x$)から1つのターゲット変数($y$)を予測するモデルを作成します。数学的には以下の式で表されます。

予測値を計算する式:$ \hat{y} = ax + b $ 実測値の関係:$ y = ax + b + \varepsilon $

各変数の意味をまとめると以下表になります。例は、VTuberの「チャンネル登録者数」から「視聴者数」を予測する場合です。

変数 説明
$ \hat{y} $ モデルが計算したターゲット変数(目的変数)の推定値 視聴者数(予測値)
$ y $ 実際に観測されたターゲット変数(目的変数)の値 視聴者数(実測値)
$ x $ 特徴量(予測したい値に影響を与えるもの。説明変数ともいう) チャンネル登録者数(実測値)
$ a $ 傾き($x$が1増えると$y$がどれだけ増えるか。重み、回帰係数ともいう) 登録者数が1人増えたときの視聴者数の増加量
$ b $ 切片($x=0$のときの$y$の値) 登録者数が0人のときの理論的な視聴者数
$ ε $ 誤差項(予測と実際のズレ) 「モデルが説明できない部分」であり、ノイズや他の未考慮の要因を含みます。

予測値を計算する式 $ \hat{y} = ax + b $は、「$x$に比例して$\hat{y}$が変化する関係」を表す、傾き$a$、切片$b$の一次関数です。グラフにすると以下のようなまっすぐな直線になります。この直線を「回帰直線」といいます。

単回帰分析で高い予測精度を出すには、例えば登録者数が2倍になったら視聴者数も2倍になるような比例関係があることが前提となります。

単回帰分析の仕組みについては、以下ページで別途解説しています。

【単回帰分析とは】計算式の仕組みをわかりやすく解説
単回帰分析とは?計算式の仕組みや求め方、決定係数による性能検証方法などをVTuberの視聴者数予測を例をわかりやすく解説します。

動画で見る

サンプルコード① 単回帰モデルの作成

Pythonライブラリ「Scikit-learn」を用いて、単回帰分析によりVTuberの「チャンネル登録者数」から「視聴者数」を予測してみましょう。

以下のような4名のVTuberの初回配信における「チャンネル登録者数」と「視聴者数」の実測値のデータがあるとします。

配信回 チャンネル登録者数(x) 視聴者数(y)
兎野ぴこり#1 150,000 4,000
港あくび#1 120,000 3,100
星空スバリ#1 100,000 2,500
修士みより#1 80,000 1,700

scikit-learnのLinearRegression クラスを使って、「チャンネル登録者数」から「視聴者数」を予測する回帰直線を求めるPythonプログラムを作成すると、以下のようになります。


傾き a: 0.03242990654205607 切片 b: -823.3644859813076 予測視聴者数: 5662.616822429906

実行結果の解説

小数第4位で切り捨てすると、回帰直線の式は以下のように求まります。

$ \hat{y} = 0.0324x – 823.3644 $

上式の$ \hat{y} $は視聴者数の推測値、$x$はチャンネル登録者数となります。 よって、例えばチャンネル登録者数20万人の視聴者数は以下の計算により、約5656人と推定できます。

$ \hat{y} = 0.0324 \times 200,000 – 823.3644 = 5656.6356$

なお、どのような計算により回帰直線を求めているかなど、数理的な仕組みについては、以下ページで学ぶことができます。

【単回帰分析とは】計算式の仕組みをわかりやすく解説
単回帰分析とは?計算式の仕組みや求め方、決定係数による性能検証方法などをVTuberの視聴者数予測を例をわかりやすく解説します。

コード解説

from sklearn.linear_model import LinearRegression
import numpy as np
  • LinearRegressionは、線形回帰モデルを使うためのクラス
  • numpyは、数値配列を扱うためのライブラリ
# 特徴量(説明変数): VTuberのチャンネル登録者数
X = np.array([[150000], [120000], [100000], [80000]])

# ターゲット変数(目的変数): 視聴者数
y = np.array([4000, 3100, 2500, 1700])
  • X特徴量(チャンネル登録者数)で、2次元配列(shape = (4, 1))にしているのは、sklearnの仕様に合わせるためです。
  • yターゲット変数(視聴者数)で、1次元配列。
# 線形回帰モデルを用いて、登録者数と視聴者数の関係を学習
model = LinearRegression()
model.fit(X, y)
  • model = LinearRegression()線形回帰モデルのクラス(LinearRegression)からインスタンスを生成(model)。
  • model.fit(X, y) で、訓練データ(X:特徴量、y:ターゲット変数)でモデルが学習します。fitメソッドは、最小二乗法で最も誤差が少ない直線を求めています。
# 回帰直線の傾き(登録者数が1人増えるごとの視聴者数の増加量)を出力
print("傾き a:", model.coef_[0])

# 回帰直線の切片(登録者数が0人のときの理論的な視聴者数)を出力
print("切片 b:", model.intercept_)
  • model.coef_属性(プロパティ)は、学習後に得られる 回帰係数(重み) がNumPy配列で格納されています。
    • model.coef_[0] は単回帰直線の傾き$a$(登録者数が1人増えると、視聴者数がどれだけ増えるか)。
    • 傾き$a$ ≈ 0.0324 → 登録者数が1万人増えると、視聴者数は約324人増える。
  • model.intercept_学習後に得られる切片$b$が「float型の数値(単回帰)」または「NumPy配列(重回帰)」で格納されています(登録者数が0人だった場合の理論的な視聴者数)。
    • 切片 ≈ -823 → 実際には「視聴者数がマイナスになる」ということはありえません。これは、モデルがデータの外側まで予測しようとしたために、現実とは合わない結果が出ています。こうした「データの外側での予測」は、正しくないことが多く、これを「外挿の限界」と呼びます。

コメント

  1. you より:

    youtubeからこちらのサイトに来ました。
    貴重な情報ありがとうございます。

    【Scikit-learn】単回帰分析の所で質問なんですが、

    # 説明変数xに “x1″のデータを使用
    x = data.loc[:, [‘x1’]].values

    # 目的変数yに “x2″のデータを使用
    y = data[‘x2’].values

    にするとあります。
    locでx1のデータを抜き出すのと、x2のデータではデータの型が違うのですか?
    どちらもSeries型となって、valuesでnumpy配列にしていると思うのですが。

    xが2次元配列、yが1次元配列というところまで勉強している程度なんで、
    基礎的な質問で申し訳ないですが、どのような意図でこのようにしているのか教えて下さい。

    • 管理人 より:

      fit()にXとyを代入する際、説明変数Xは行列(2次元配列)を与える必要があります。
      data[‘x2’].valuesだと、1次元配列として1つの配列を取得するため、二次元配列に変換してやるコードを追加する必要があります。
      その手間を省く意味と、重回帰の場合はlocを使わないといけないという理由でdata.loc(複数のカラムを2次元配列で取得)としています。

      https://scikit-learn.org/stable/modules/generated/sklearn.linear_model.LinearRegression.html

      fit(self, X, y, sample_weight=None)[source]
      
      X{array-like, sparse matrix} of shape (n_samples, n_features)
      Training data
      
      yarray-like of shape (n_samples,) or (n_samples, n_targets)
      Target values. Will be cast to X’s dtype if necessary