あなたのコードは少し複雑すぎて、もっと構造が必要だと思います。最終的に、この回帰は 4 つの操作に要約されます。
- 仮説 h = X * シータを計算します
- 損失 = h - y を計算し、コストの 2 乗 (損失 ^2)/2m を計算します。
- 勾配を計算する = X' * 損失 / m
- パラメータを更新します theta = theta - alpha * gradient
m
あなたの場合、 と混同していると思いますn
。ここでm
は、特徴の数ではなく、トレーニング セット内の例の数を示します。
あなたのコードの私のバリエーションを見てみましょう:
import numpy as np
import random
# m denotes the number of examples here, not the number of features
def gradientDescent(x, y, theta, alpha, m, numIterations):
xTrans = x.transpose()
for i in range(0, numIterations):
hypothesis = np.dot(x, theta)
loss = hypothesis - y
# avg cost per example (the 2 in 2*m doesn't really matter here.
# But to be consistent with the gradient, I include it)
cost = np.sum(loss ** 2) / (2 * m)
print("Iteration %d | Cost: %f" % (i, cost))
# avg gradient per example
gradient = np.dot(xTrans, loss) / m
# update
theta = theta - alpha * gradient
return theta
def genData(numPoints, bias, variance):
x = np.zeros(shape=(numPoints, 2))
y = np.zeros(shape=numPoints)
# basically a straight line
for i in range(0, numPoints):
# bias feature
x[i][0] = 1
x[i][1] = i
# our target variable
y[i] = (i + bias) + random.uniform(0, 1) * variance
return x, y
# gen 100 points with a bias of 25 and 10 variance as a bit of noise
x, y = genData(100, 25, 10)
m, n = np.shape(x)
numIterations= 100000
alpha = 0.0005
theta = np.ones(n)
theta = gradientDescent(x, y, theta, alpha, m, numIterations)
print(theta)
最初に、次のような小さなランダム データセットを作成します。
ご覧のとおり、生成された回帰直線と、Excel で計算された数式も追加しました。
勾配降下法を使用した回帰の直感に注意する必要があります。データ X に対して完全なバッチ パスを実行する場合、すべての例の m 損失を 1 回の重み更新に減らす必要があります。この場合、これは勾配全体の合計の平均であるため、 で除算されm
ます。
次に注意する必要があるのは、収束を追跡し、学習率を調整することです。さらに言えば、反復ごとに常にコストを追跡し、プロットすることもできます。
私の例を実行すると、返される theta は次のようになります。
Iteration 99997 | Cost: 47883.706462
Iteration 99998 | Cost: 47883.706462
Iteration 99999 | Cost: 47883.706462
[ 29.25567368 1.01108458]
これは実際には、Excel で計算された式 (y = x + 30) に非常に近いものです。バイアスを最初の列に渡したので、最初の theta 値はバイアスの重みを示していることに注意してください。