40
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 của tôi từ các mã trên là 100.2 100.2, nhưng nó phải là 100.2 61.09 trong matlab đó là chính xác.gradient descent sử dụng python và NumPy

+5

dấu chấm phẩy bị bỏ qua trong python và thụt đầu dòng nếu cơ bản. –

Trả lời

101

Tôi nghĩ rằng mã của bạn hơi phức tạp và cần nhiều cấu trúc hơn, vì nếu không bạn sẽ bị mất trong tất cả các phương trình và hoạt động. Cuối cùng hồi quy này nắm để bốn hoạt động:

  1. Tính giả thuyết h = X * theta
  2. Tính mất = h - y và có thể chi phí bình phương (lỗ^2)/2m
  3. tính gradient = X' * mất/m
  4. cập nhật các thông số theta = theta - alpha * gradient

Trong trường hợp của bạn, tôi đoán bạn đã nhầm lẫn m với n. Ở đây m biểu thị số lượng ví dụ trong tập huấn luyện của bạn, không phải số lượng đối tượng địa lý.

Hãy có một cái nhìn tại sự thay đổi của tôi về mã của bạn:

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) 

Lúc đầu, tôi tạo ra một tập dữ liệu ngẫu nhiên nhỏ mà nên xem xét như thế này:

Linear Regression

Như bạn có thể thấy tôi cũng đã thêm dòng hồi quy được tạo ra và công thức được tính bằng excel.

Bạn cần phải quan tâm đến trực giác của hồi quy bằng cách sử dụng độ dốc gốc. Khi bạn thực hiện một đợt hoàn thành vượt qua dữ liệu X của mình, bạn cần phải giảm m-loss của mỗi ví dụ xuống một bản cập nhật trọng lượng duy nhất. Trong trường hợp này, đây là mức trung bình của tổng trên các gradient, do đó chia cho m.

Điều tiếp theo bạn cần quan tâm là theo dõi sự hội tụ và điều chỉnh tốc độ học tập. Cho rằng vấn đề bạn nên luôn luôn theo dõi chi phí của bạn mỗi lần lặp lại, thậm chí có thể âm mưu nó.

Nếu bạn chạy ví dụ của tôi, theta trả lại sẽ trông như thế này:

Iteration 99997 | Cost: 47883.706462 
Iteration 99998 | Cost: 47883.706462 
Iteration 99999 | Cost: 47883.706462 
[ 29.25567368 1.01108458] 

Đó là thực sự khá gần với phương trình đó đã được tính toán bằng excel (y = x + 30). Lưu ý rằng khi chúng ta chuyển thiên vị vào cột đầu tiên, giá trị theta đầu tiên biểu thị trọng số thiên vị.

+3

Trong gradientDescent, là '/ 2 * m' được cho là'/(2 * m) '? – physicsmichael

+1

@ vgm64 ouch, vâng bạn đã đúng! Sửa chữa nó. –

+2

Sử dụng 'mất' cho sự khác biệt tuyệt đối không phải là một ý tưởng rất hay vì "mất mát" thường là một từ đồng nghĩa của "chi phí". Bạn cũng không cần phải vượt qua 'm' chút nào, các mảng NumPy biết hình dạng của chúng. –

8

Dưới đây, bạn có thể tìm thấy việc triển khai mẫu gốc của mình cho vấn đề hồi quy tuyến tính.

Lúc đầu, bạn tính toán độ dốc như X.T * (X * w - y)/N và cập nhật theta hiện tại của bạn với gradient này cùng một lúc.

  • X: Tính năng ma trận
  • y: mục tiêu giá trị
  • w: trọng lượng/giá trị
  • N: kích thước của đào tạo thiết

Đây là mã 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) 

test1 test2 test2

+3

Tuyên bố nhập khẩu không cần thiết: nhập gấu trúc làm pd – fviktor

+0

@Muatik Tôi không hiểu làm cách nào bạn có thể lấy gradient w/sản phẩm bên trong của lỗi và tập huấn luyện: 'gradient = x.T * error/N' Logic đằng sau điều này là gì? – eggie5

1

Tôi biết câu hỏi này đã có được câu trả lời nhưng tôi đã thực hiện một số cập nhật cho các chức năng GD:

### COST FUNCTION 

def cost(theta,X,y): 
    ### Evaluate half MSE (Mean square error) 
    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) 

Chức năng này làm giảm alpha so với lần lặp làm cho chức năng quá tụ nhanh hơn thấy Estimating linear regression with Gradient Descent (Steepest Descent) cho một ví dụ trong R. Tôi áp dụng cùng một logic nhưng trong Python.

Các vấn đề liên quan