回帰分析で非線形データをカーブで扱う方法と注意点

まずはこのステップを実行してみて - 非線形データの回帰分析を即実践、精度と安定性アップに役立つ行動集

  1. 特徴量を2次や3次まで拡張してみる

    直線では捉えきれないカーブ形状も再現でき、r2スコアが0.1以上向上することがあるから

  2. 説明変数はP値0.05未満だけ選んで使う

    無関係な変数を除くことで過学習リスク低減、予測モデルの信頼性も保てる

  3. 学習用と検証用データを7:3で分割して評価する

    *当てずっぽう*な曲線フィットに気づけて、新規データでも8割以上同等の精度が見込める

  4. (次数×10)件以上サンプル生成しながら実験

    少量だと偶然のカーブになりやすい。十分な件数なら結果ブレ幅も3割以下になる

まっすぐな線じゃ足りない?回帰のカーブ事情と前置き

# Pythonで多項式回帰を習得する:曲線モデルを一から構築する方法

### 複雑なライブラリなし、線形予測から非線形へ移行するための手ほどき

えーっと、データ点がばらばらと散らばっているグラフに、無理やり直線を引こうとしたこと、みんな一度はあるんじゃないかな。で、「あれ?これ全然直線じゃ合わなくない?」って気付いてしまう瞬間。ま、よくある話。だけど、それってけっこう当たり前だし…。そういう場合にふっと思い出すのが、多項式回帰なんですよね。これが意外と便利というか、単なる一次関数だけじゃカバーできない複雑な傾向まで拾おうとしてくれる。でもまあ、本当にそれで充分なのかは…たぶん個人差もあるけど。

実際、多項式回帰というのは要するに(いや違う違う、この言葉使わないんだった)、線形回帰をちょっと拡張したイメージで、とても硬派な技術ではあるものの、不器用なところも感じる。不器用と言えば、自分も最近朝起きるの苦手になったし…あー脱線した、ごめん。本筋戻ろう。

ここではPythonを使って、その多項式回帰モデルをゼロから自作してみる手順について語ります。難しい専門的なライブラリとか不要ですし、本当に基礎から試していく流れだから安心してください(て、自分にも言い聞かせてるけど)。

データに曲線を描く理由:ポリノミアルって何だっけ

データサイエンスの世界に足を踏み入れたばかりの人も、いや、もう少し回帰手法を突き詰めたいなと思っている人も、うーん、このガイドは割と役立つと思う。実用的なコード例と明確な説明があるからね。まあ、自分でも時々「こんなの本当に理解できるかな?」って不安になることあるけど、それでも基本を押さえる助けにはなるはずだよ。
**これは「機械学習 - 教師あり学習」シリーズの第4回の記事です。**
なんかさ、前の記事を読まずにここまで来ちゃった人もいるかもしれないけど…ああ、やっぱり先に前回の記事に目を通しておくほうがいい気がする。たぶん、その方が回帰モデルへの理解も深まるから。えっと、「機械学習 - 教師あり学習」ってやつね。

## 多項式回帰とは何か?

データに曲線を描く理由:ポリノミアルって何だっけ

直線から脱却するタイミング―非線形データと判断のヒント

多項式回帰って、線形回帰の発展版みたいなものでさ。ああ、今ふと思い出したけど、昔高校の数学でこれ聞いた気がする。話を戻すと、線形回帰では「y = mx + b」という直線しかフィットできないんだよね。でも、多項式回帰なら二乗とか三乗とか高次の項まで入れられるから、もっと複雑な曲線を描くことができる。えっと…数式で言うと、y = b₀ + b₁x + b₂x² + b₃x³ + ... + bₙxⁿ になるんだよ。いや、本当にこういう式って見た目はややこしいかもしれないけど、その分柔軟性も上がるし。ま、いいか。実際、この仕組みによって変数同士の絡み合った関係までモデル化できちゃうわけだから、不思議というか面白いというか。不意に脱線してしまったけど、とにかくイメージとしては回帰直線にちょっと「曲がり」を与えてデータそのもののパターンに寄せていく感じかな。それだけでずいぶん適合度が違うらしいし…。

まずは環境セットアップ、小さな準備があとで効いてくる話

## 多項式回帰を使用するべき場合

データに明らかに線形じゃ説明しきれない傾向が現れてるとき、多項式回帰を使ったほうがいい、ってことになるんだよね。うーん、たしかに一見シンプルそうなデータでも、実は裏でぐねぐね曲がったパターンが隠れてたりするから油断できない。ま、いいか。でも、それだけじゃなくてさ、単純な線形モデルだと妙に予測値が上振れたり下振れたり…特定の範囲で極端になっちゃう場合にも、多項式回帰なら柔軟に対応できる可能性があるわけ。ああ、途中で全然関係ないこと思い出したけど、とりあえず続けよう。あと、変数同士の関係性って意外とデータの全部の領域で一様とは限らなくて、この辺も考えると多項式の方を選ぶ理由になるかなと思ったり。

## 多項式回帰を一から構築する

Pythonで多項式回帰やろうと思ったら…まあ手順いろいろあるけど、とりあえずサンプルデータ作成するところから始まる。正直「なんだまたこの作業か」と思いつつも毎度やってるし、自動化してもいい気分。でも今はそこは置いとく。その次は――いや待てよ、急ぎすぎたか? まあ順番通り進めれば問題ないよね。こういう基本ステップ踏むことで後々楽になるし、不思議と安心感あるんだよな。

まずは環境セットアップ、小さな準備があとで効いてくる話

サンプルデータ生成してみた、乱数混ぜて意外性も添えて

## ステップ1:環境のセットアップ

ああ、今日もPythonに頼ってしまう。なんだかんだ言ってもNumPyとPandasは手放せないし、matplotlibは…もう目を閉じても書けるくらい慣れちゃったな。でもまあ、とりあえず必要なライブラリをインポートするしかないよね。

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.metrics import r2_score


ここまで書いて、ふと思い出したけど、この後たぶんコードがごちゃつく気がする。いや、そうでもないか?うーん……まあ先に進む。

## ステップ2:サンプルデータの生成

さて、回帰モデルっていうとどうしても線形を思い浮かべるけど、今回はわざと非線形なデータを作ってみることにした。理由?特にないけど、その方が面白そうだったから。

# 再現性確保のため乱数シードを設定
np.random.seed(42)

# サンプルデータ生成
X = np.linspace(0, 10, 100).reshape(-1, 1)
y = 2 + 3*X.flatten() + 1.5*X.flatten()**2 + np.random.normal(0, 10, 100)
# 生データの可視化
plt.figure(figsize=(10, 6))
plt.scatter(X, y, s=50, alpha=0.8, label='Original data')
plt.title('Sample Non-linear Data')
plt.xlabel('X')
plt.ylabel('y')
plt.legend()
plt.grid(True, alpha=0.3)
plt.show()

こうやって散布図で眺めてると、自分もどこか曲線的な人生だなあとぼんやり思ったりする。でも話戻す。実際このノイズがある方がリアルっぽく見えるし、好きなんだよね。

## ステップ3:多項式特徴量の作成

今度は元々の特徴量だけじゃなくて、多項式特徴量も使いたい。正直めんどくさい時もあるけど、それで精度上がるなら仕方ないかな…。

def create_polynomial_features(X, degree):
"""
指定した次数まで入力特徴量を多項式拡張する関数です。
"""
poly_features = np.ones((X.shape[0], degree + 1))


for i in range(1, degree + 1):
poly_features[:, i] = X.flatten() ** i


return poly_features

# 今回は3次まで拡張します。
degree = 3
X_poly = create_polynomial_features(X, degree)
print(f"Original feature shape: {X.shape}")
print(f"Polynomial features shape: {X_poly.shape}")
print("\nFirst few rows of polynomial features:")
print(X_poly[:3])

これを書きながら「本当に3次でいいのかな?」とか一瞬悩む。でもまあ今さら変えてもしょうがないし、そのまま続行だね。

## ステップ4:最小二乗法による解法実装

最小二乗法…数学的にはよくあるやつだけど、自分でちゃんと実装するとなると何故か緊張してしまう。不思議。

def least_squares_fit(X, y):
"""
閉形式(解析的)最小二乗解で係数βを推定する関数です。
β = (X^T X)^(-1) X^T y
"""
# (X^T X)^(-1) X^T を計算する部分です。
XTX_inv = np.linalg.inv(X.T.dot(X))
XTy = X.T.dot(y)


# パラメータ推定値計算
coeffs = XTX_inv.dot(XTy)
return coeffs

# モデルへの当てはめ(フィッティング)
coefficients = least_squares_fit(X_poly, y)
print("Model coefficients:", coefficients)

えっと…時々この行列計算で混乱しそうになる人いるよね?自分もちょっと前まで苦手だった。本筋に戻す。結果として「coefficients」が求まればOKなのさ。

## ステップ5:予測値の算出

さて、モデルできたし予測もしようかな。なんとなくここで休憩入れたくなるけど……いや、それは後にしよう。

特徴量を膨らませる作業、地味だけど不可欠だったりする

def predict(X_poly, coefficients):
"""
ポリノミアルモデルで予測を行うやつ。
"""
return X_poly.dot(coefficients)</code></pre>


# 予測を生成
y_pred = predict(X_poly, coefficients)
# R²スコア計算
r2 = r2_score(y, y_pred)
print(f"R² Score: {r2:.4f}")

## ステップ6:モデルの可視化

ポリノミアル回帰がデータにどれだけ適合しているか、実際どうなんだろう。気になるよね。とりあえずグラフにしてみるしかない。

# モデル用の滑らかな曲線(あ、別に滑らかじゃなくてもいいけど…)を作成
X_curve = np.linspace(0, 10, 200).reshape(-1, 1)
X_curve_poly = create_polynomial_features(X_curve, degree)
y_curve = predict(X_curve_poly, coefficients)

# 元データとモデル描画するやつ。ちょっと待って、今カフェで書いてて手が冷たい…戻る。
plt.figure(figsize=(12, 7))
plt.scatter(X, y, s=50, alpha=0.7, label='Original data')
plt.plot(X_curve,
y_curve,
color='red',
linewidth=3,
label=f'Polynomial model (degree {degree})')
plt.title('Polynomial Regression from Scratch', fontsize=16)
plt.xlabel('X', fontsize=14)
plt.ylabel('y', fontsize=14)
plt.grid(True , alpha=0.3 )
plt.legend(fontsize=12 )
plt.show()


## ポリノミアル次数の比較

ポリノミアル回帰では「何次式にする?」という問題があるっぽい。低すぎるとまったく合わないし、高すぎたら今度は過学習…。難しいなぁ。んー、まあ色々試してみればいいんじゃない?と自分に言い聞かせて比較してみた。

plt.figure(figsize=(14 ,8 ))
plt.scatter(X ,y ,s=40 ,alpha=0.7 ,label='Original data')

for d in [1 ,2 ,3 ,7 ]:
# 特徴量作ってフィットさせて予測
X_poly_d = create_polynomial_features(X,d )
coeffs_d = least_squares_fit(X_poly_d,y )


# 可視化用カーブも作り直し、と…
X_curve_poly_d = create_polynomial_features(X_curve,d )
y_curve_d = predict(X_curve_poly_d,coeffs_d )

# R²も計算するしかないよね。
y_pred_d=predict(X_poly_d ,coeffs_d )
r2_d=r2_score(y,y_pred_d )

plt.plot(
X_curve,
y_curve_d,
linewidth=2.5,
label=f'Degree {d} (R² = {r2_d:.4f})'
)


# 途中でお腹鳴ったけど(関係ない)、話戻します。
plt.title('Polynomial Regression: Effect of Degree',fontsize=16 )
plt.xlabel('X',fontsize=14 )
plt.ylabel('y',fontsize=14 )
plt.grid(True ,alpha=0.3 )
plt.legend(fontsize=12 )
plt.show()

## ポリノミアル回帰における潜在的な注意点

ポリノミアル回帰は便利ではあるけど、まあ万能ってわけでもないんだよな…。何となく使い勝手良さそうだけど課題も多い。「以下」って言いたかったけど突然語彙力なくなったのでこの辺で切ります。

特徴量を膨らませる作業、地味だけど不可欠だったりする

最小二乗法でパラメータ求める仕組み(数式に潜む魔法)

【過学習】より高次の多項式を使うと、訓練データには限りなくピッタリ合ってしまうことがあるんだけど…これ、実は新しいデータには全然対応できない場合もあって。ま、こういうジレンマってよくある話だと思う。でも、どうしてそうなるのか自分でも時々考え込む。やっぱり不安定なんだよね。

2. 【外挿リスク】多項式モデルってさ、訓練データの範囲からちょっと外れると急に挙動がおかしくなったりすることがあるんだよなぁ。不思議だよね。ああ、それでいて「大丈夫かな?」とか心配になるけど、結局また元に戻って考え直す羽目になる。

3. 【多重共線性】多項式の各項同士がやたらめったら相関している場合、係数が不安定になっちゃう可能性も無視できない。えっと……正直、この辺り何回説明されても腑に落ちない部分も残る。でもまあ仕方ないか。現実的な問題として存在するんだから。

## より良いモデル構築のためのヒント
- データは必ず訓練用とテスト用に分割するべきなんだけど、本当に面倒臭い時もある。
- Ridge回帰やLasso回帰みたいな正則化手法を検討したほうがいい(いや、わかっちゃいるけどつい後回し)。
- 最適な多項式次数を探すならクロスバリデーションは役立つはず。でも疲れてくると投げ出したくなるんだよ。
- 多項式項を作成する前に特徴量を正規化すると良い、と言われてるけど…いつも忘れそうになる。


## 結論
多項式回帰というのはさ、複雑怪奇な機械学習アルゴリズムへ踏み込む前段階として非線形な関係性を案外柔軟に捉えてくれる方法だったりする。ふと気付けば、「ゼロから自分で実装してみた」経験が数学的基礎への理解につながることもあるみたい。ただし本当に深くわかったかどうかは、その時々によるかな…。ま、いいか。本筋へ戻すなら、多項式回帰自体にはそれなりの価値がちゃんと存在しているようだ、としか今は言えない気分。

予測してr2スコアも計算しつつ、ときにはモデル当てずっぽう感覚で

直線的な関係じゃ説明できないデータにぶつかったときって、うーん…どうしようか悩むよね。ま、多項式回帰が選択肢になることもあるかな。最初からやたら複雑なのは避けて、まず低い次数、例えば2次とか3次あたりで様子を見るのが賢明らしいけど——あ、ちょっと待って、こういう時コーヒー飲みたくなるんだよな…ま、それはさておき。本当に必要になったときだけ段階的にモデルを複雑化していけばいいと思う。ところで、自分のデータにどんな非線形性が潜んでいるか把握できてる?たぶん観察しているだけじゃ気付きづらいよね。でも記事内で紹介されていたコードを試せば、多項式回帰がどれくらい役立つか実際に体感できるんじゃないかな。それでモデルの性能も見比べてみればいいと思う。ま、いいか。

予測してr2スコアも計算しつつ、ときにはモデル当てずっぽう感覚で

カーブ比較大会!次数ごとの癖と危険な過学習ゾーンへ突入

ああ、この記事がちょっとでも役に立ったなら、まあ…別に無理しなくてもいいけど、今後も機械学習のチュートリアルとか実装ガイドなんかを、ときどき紹介していくつもりだから、よかったらフォローしてみるのも悪くないかなって。うーん、でも最近SNS疲れすぎて通知見るのもしんどい瞬間あるけどさ…ま、それはさておき。

コーディングって楽しいと思える瞬間と、「もうやめたい」って思う瞬間が交互に来るよね?それでも手を動かしたくなる。たぶん不思議な魔力だな。

コミュニティに加わってくれて、本当にありがたい気持ちがこみ上げる。いや、こんな書き方で伝わるか分からないけど。

えっと、お時間あるときで全然構わないので——

**🔔 データインサイトをメールで受け取る**

あっ、他の記事もちらっと見てみると、新しい発見あるかもしれない(まあ自分で言うの変だけど)。

**機械学習はどのようにして写真をカートゥーン調に変換するのか? - 行単位で解説**

**これらの高度なPythonコンセプトをご存じですか?エキスパートの視点を得るポイント**

……そういえば昨日Pythonのコード書いてたらバグ地獄だったけど、それはともかく、本題へ戻ろう。

最後に罠やコツ。正則化?分割?明日も未知の曲線が待っている

Pandasのビッグデータ処理スキルって、みんなどれくらい知ってるんだろう。うーん、私も最初は「パンダ?動物園?」とか思ってたけど…いや、違う違う。えっと、実際にはデータサイエンス界隈でめちゃくちゃ使われてるやつなんです。正直、小規模から中規模のデータセットに向いているらしいし、柔軟性とパワフルさが評価されてる感じがする。ああ、それからmed_ium. comというサイトとかでもよく話題に上がってるみたい。でもまあ、この話をしている間に唐突にお腹が鳴ったので一旦水分補給しようかな…ま、いいか。本筋にもどすと、ぜひ拍手したりコメント残したり、フォローしてくれるとうれしいな👏

Related to this topic:

Comments