web-dev-qa-db-fra.com

descente en dégradé avec python et 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

Mon thêta du code ci-dessus est 100.2 100.2, mais il devrait être 100.2 61.09 dans matlab qui est correct.

53
Madan Ram

Je pense que votre code est un peu trop compliqué et qu'il a besoin de plus de structure, car sinon vous serez perdu dans toutes les équations et opérations. En fin de compte, cette régression se résume à quatre opérations:

  1. Calculer l'hypothèse h = X * thêta
  2. Calculer la perte = h - y et peut-être le coût au carré (perte ^ 2)/2m
  3. Calculer le gradient = X '* perte/m
  4. Mettre à jour les paramètres thêta = thêta - alpha * gradient

Dans votre cas, je suppose que vous avez confondu m avec n. Ici m indique le nombre d'exemples de votre jeu d'apprentissage, pas le nombre de fonctionnalités.

Jetons un coup d'oeil à ma variante de votre code:

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)

Au début, je crée un petit jeu de données aléatoire qui devrait ressembler à ceci:

Linear Regression

Comme vous pouvez le constater, j'ai également ajouté la ligne de régression générée et la formule calculée par Excel.

Vous devez faire attention à l'intuition de la régression en utilisant la descente en gradient. Lorsque vous passez un lot complet sur vos données X, vous devez réduire les pertes m de chaque exemple à une seule mise à jour de poids. Dans ce cas, il s'agit de la moyenne de la somme sur les gradients, donc la division par m

La prochaine étape à prendre en compte est de suivre la convergence et d’ajuster le taux d’apprentissage. D'ailleurs, vous devriez toujours suivre votre coût à chaque itération, peut-être même l'intrigue.

Si vous exécutez mon exemple, le thêta retourné ressemblera à ceci:

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

Ce qui est en fait assez proche de l'équation calculée par Excel (y = x + 30). Notez que lorsque nous avons passé le biais dans la première colonne, la première valeur thêta indique le poids du biais.

119
Thomas Jungblut

Ci-dessous, vous trouverez mon implémentation de la descente de gradient pour un problème de régression linéaire. 

Au début, vous calculez le dégradé comme X.T * (X * w - y) / N et mettez à jour votre thêta actuel avec ce dégradé simultanément. 

  • X: matrice de caractéristiques 
  • y: valeurs cibles 
  • w: poids/valeurs 
  • N: taille de l'ensemble d'entraînement

Voici le code 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

10
Muatik

Je sais que cette question a déjà été posée, mais j’ai mis à jour la fonction 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)

Cette fonction réduit l'alpha par rapport à l'itération, ce qui rend la fonction trop convergente plus rapide. Voir Estimation de la régression linéaire avec Gradient Descent (Steepest Descent) pour un exemple en R. J'applique la même logique mais en Python.

2
Nico Coallier

Suite à l’implémentation de @ thomas-jungblut en python, j’ai fait de même pour Octave. Si vous trouvez quelque chose qui ne va pas s'il vous plaît faites le moi savoir et je corrigerai + mise à jour.

Les données proviennent d'un fichier txt avec les lignes suivantes:

1 10 1000
2 20 2500
3 25 3500
4 40 5500
5 60 6200

considérez-le comme un échantillon très approximatif de caractéristiques [nombre de chambres] [mts2] et de dernière colonne [prix du loyer], ce que nous voulons prédire.

Voici l'implémentation 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);
0