[英]gradient descent using python and numpy
def gradient(X_norm,y,theta,alpha,m,n,num_it):
temp=np.array(np.zeros_like(theta,float))
for i in range(0,num_it):
h=np.dot(X_norm,theta)
#temp[j]=theta[j]-(alpha/m)*( np.sum( (h-y)*X_norm[:,j][np.newaxis,:] ) )
temp[0]=theta[0]-(alpha/m)*(np.sum(h-y))
temp[1]=theta[1]-(alpha/m)*(np.sum((h-y)*X_norm[:,1]))
theta=temp
return theta
X_norm,mean,std=featureScale(X)
#length of X (number of rows)
m=len(X)
X_norm=np.array([np.ones(m),X_norm])
n,m=np.shape(X_norm)
num_it=1500
alpha=0.01
theta=np.zeros(n,float)[:,np.newaxis]
X_norm=X_norm.transpose()
theta=gradient(X_norm,y,theta,alpha,m,n,num_it)
print theta
上面代碼中的 theta 是100.2 100.2
,但在 matlab 中它應該是100.2 61.09
這是正確的。
我認為你的代碼有點過於復雜,需要更多的結構,否則你將失去所有方程和操作。 最后,這個回歸歸結為四個操作:
在你的情況下,我猜你和n
混淆了m
。 這里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-loss減少到單個權重更新。 在這種情況下,這是梯度上的總和的平均值,因此除以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)。 請注意,當我們將偏差傳遞到第一列時,第一個θ值表示偏置權重。
下面你可以找到我對線性回歸問題的梯度下降的實現。
首先,您計算梯度,如XT * (X * w - y) / N
並同時使用此漸變更新當前的θ。
這是python代碼:
import pandas as pd
import numpy as np
from matplotlib import pyplot as plt
import random
def generateSample(N, variance=100):
X = np.matrix(range(N)).T + 1
Y = np.matrix([random.random() * variance + i * 10 + 900 for i in range(len(X))]).T
return X, Y
def fitModel_gradient(x, y):
N = len(x)
w = np.zeros((x.shape[1], 1))
eta = 0.0001
maxIteration = 100000
for i in range(maxIteration):
error = x * w - y
gradient = x.T * error / N
w = w - eta * gradient
return w
def plotModel(x, y, w):
plt.plot(x[:,1], y, "x")
plt.plot(x[:,1], x * w, "r-")
plt.show()
def test(N, variance, modelFunction):
X, Y = generateSample(N, variance)
X = np.hstack([np.matrix(np.ones(len(X))).T, X])
w = modelFunction(X, Y)
plotModel(X, Y, w)
test(50, 600, fitModel_gradient)
test(50, 1000, fitModel_gradient)
test(100, 200, fitModel_gradient)
這些答案中的大多數都遺漏了一些關於線性回歸的解釋,而且代碼在我看來有點復雜。
問題是,如果您有一個包含“m”個樣本的數據集,每個樣本稱為“x^i”(n 維向量),以及一個結果向量 y(m 維向量),您可以構建以下矩陣:
現在,目標是找到“w”(n+1 維向量),它描述了線性回歸的直線,“w_0”是常數項,“w_1”等等是每個維度(特征)的系數在輸入樣本中。 所以本質上,你想要找到“w”使得“X*w”盡可能接近“y”,即你的線預測將盡可能接近原始結果。
另請注意,我們在每個“x^i”的開頭添加了一個額外的組件/維度,它只是“1”,以說明常數項。 此外,“X”只是您通過將每個結果“堆疊”為一行而獲得的矩陣,因此它是一個(m x n+1)矩陣。
一旦你構建了它,梯度下降的 Python 和 Numpy 代碼實際上非常簡單:
def descent(X, y, learning_rate = 0.001, iters = 100):
w = np.zeros((X.shape[1], 1))
for i in range(iters):
grad_vec = -(X.T).dot(y - X.dot(w))
w = w - learning_rate*grad_vec
return w
瞧,它返回向量“w”。 或您的預測線的描述。
但是它是如何工作的呢? 在上面的代碼中,我找到成本 function 的梯度向量(在本例中為平方差),然后我們“逆流”,找到最佳“w”給出的最小成本。 實際使用的公式在行中
grad_vec = -(X.T).dot(y - X.dot(w))
有關完整的數學解釋和包括創建矩陣的代碼,請參閱這篇關於如何在 Python 中實現梯度下降的帖子。
編輯:為了說明,上面的代碼估計了一條線,您可以使用它來進行預測。 下圖顯示了來自 Kaggle 的“魚市”數據集的“學習”梯度下降線(紅色)和原始數據樣本(藍色散點)的示例。
我知道這個問題已經回答了,但我對GD功能進行了一些更新:
### COST FUNCTION
def cost(theta,X,y):
### Evaluate half MSE (Mean square error)
m = len(y)
error = np.dot(X,theta) - y
J = np.sum(error ** 2)/(2*m)
return J
cost(theta,X,y)
def GD(X,y,theta,alpha):
cost_histo = [0]
theta_histo = [0]
# an arbitrary gradient, to pass the initial while() check
delta = [np.repeat(1,len(X))]
# Initial theta
old_cost = cost(theta,X,y)
while (np.max(np.abs(delta)) > 1e-6):
error = np.dot(X,theta) - y
delta = np.dot(np.transpose(X),error)/len(y)
trial_theta = theta - alpha * delta
trial_cost = cost(trial_theta,X,y)
while (trial_cost >= old_cost):
trial_theta = (theta +trial_theta)/2
trial_cost = cost(trial_theta,X,y)
cost_histo = cost_histo + trial_cost
theta_histo = theta_histo + trial_theta
old_cost = trial_cost
theta = trial_theta
Intercept = theta[0]
Slope = theta[1]
return [Intercept,Slope]
res = GD(X,y,theta,alpha)
此函數在迭代過程中減少alpha,使得函數過於快速收斂,請參閱使用梯度下降(最速下降)估算線性回歸,以獲得R中的示例。我在Python中應用相同的邏輯。
在python中執行@ thomas-jungblut之后,我為Octave做了同樣的事情。 如果您發現錯誤請告訴我,我將修復+更新。
數據來自包含以下行的txt文件:
1 10 1000
2 20 2500
3 25 3500
4 40 5500
5 60 6200
把它想象成一個非常粗略的特征樣本[卧室數量] [mts2]和最后一列[租金價格]這是我們想要預測的。
這是Octave實現:
%
% Linear Regression with multiple variables
%
% Alpha for learning curve
alphaNum = 0.0005;
% Number of features
n = 2;
% Number of iterations for Gradient Descent algorithm
iterations = 10000
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% No need to update after here
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
DATA = load('CHANGE_WITH_DATA_FILE_PATH');
% Initial theta values
theta = ones(n + 1, 1);
% Number of training samples
m = length(DATA(:, 1));
% X with one mor column (x0 filled with '1's)
X = ones(m, 1);
for i = 1:n
X = [X, DATA(:,i)];
endfor
% Expected data must go always in the last column
y = DATA(:, n + 1)
function gradientDescent(x, y, theta, alphaNum, iterations)
iterations = [];
costs = [];
m = length(y);
for iteration = 1:10000
hypothesis = x * theta;
loss = hypothesis - y;
% J(theta)
cost = sum(loss.^2) / (2 * m);
% Save for the graphic to see if the algorithm did work
iterations = [iterations, iteration];
costs = [costs, cost];
gradient = (x' * loss) / m; % /m is for the average
theta = theta - (alphaNum * gradient);
endfor
% Show final theta values
display(theta)
% Show J(theta) graphic evolution to check it worked, tendency must be zero
plot(iterations, costs);
endfunction
% Execute gradient descent
gradientDescent(X, y, theta, alphaNum, iterations);
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.