21

Sto cercando di implementare questo algoritmo per trovare l'intercetta e la pendenza per la sola variabile:regressione lineare semplice in Python

ALGORITHM OF THE LINEAR REGRESSION

Ecco il mio codice Python per aggiornare l'intercetta e pendenza. Ma non sta convergendo. RSS sta aumentando con Iterazione piuttosto che diminuendo e dopo qualche iterazione sta diventando infinita. Non sto riscontrando alcun errore nell'implementazione dell'algoritmo. Come posso risolvere questo problema? Ho allegato anche il file CSV. Ecco il codice.

import pandas as pd 
import numpy as np 

#Defining gradient_decend 
#This Function takes X value, Y value and vector of w0(intercept),w1(slope) 
#INPUT FEATURES=X(sq.feet of house size) 
#TARGET VALUE=Y (Price of House) 
#W=np.array([w0,w1]).reshape(2,1) 
#W=[w0, 
# w1] 

def gradient_decend(X,Y,W): 
    intercept=W[0][0] 
    slope=W[1][0] 

    #Here i will get a list 
    #list is like this 
    #gd=[sum(predicted_value-(intercept+slope*x)), 
    #  sum(predicted_value-(intercept+slope*x)*x)] 
    gd=[sum(y-(intercept+slope*x) for x,y in zip(X,Y)), 
     sum(((y-(intercept+slope*x))*x) for x,y in zip(X,Y))] 
    return np.array(gd).reshape(2,1) 

#Defining Resudual sum of squares 
def RSS(X,Y,W): 
    return sum((y-(W[0][0]+W[1][0]*x))**2 for x,y in zip(X,Y)) 


#Reading Training Data 
training_data=pd.read_csv("kc_house_train_data.csv") 

#Defining fixed parameters 
#Learning Rate 
n=0.0001 
iteration=1500 
#Intercept 
w0=0 
#Slope 
w1=0 

#Creating 2,1 vector of w0,w1 parameters 
W=np.array([w0,w1]).reshape(2,1) 

#Running gradient Decend 
for i in range(iteration): 
    W=W+((2*n)* (gradient_decend(training_data["sqft_living"],training_data["price"],W))) 
    print RSS(training_data["sqft_living"],training_data["price"],W) 

Here è il file CSV.

+0

; P è presso l'University of Washington di classe macchina leanring, l'ho preso troppo, è stato molto divertente e illuminante. Ti suggerisco di usare il forum su coursera e puoi ottenere ottime risposte da mentori, volontari e compagni di studio. https://www.coursera.org/learn/ml-regression/discussions – alvas

risposta

3

Ho risolto il mio problema!

Ecco il modo risolto.

import numpy as np 
import pandas as pd 
import math 
from sys import stdout 

#function Takes the pandas dataframe, Input features list and the target column name 
def get_numpy_data(data, features, output): 

    #Adding a constant column with value 1 in the dataframe. 
    data['constant'] = 1  
    #Adding the name of the constant column in the feature list. 
    features = ['constant'] + features 
    #Creating Feature matrix(Selecting columns and converting to matrix). 
    features_matrix=data[features].as_matrix() 
    #Target column is converted to the numpy array 
    output_array=np.array(data[output]) 
    return(features_matrix, output_array) 

def predict_outcome(feature_matrix, weights): 
    weights=np.array(weights) 
    predictions = np.dot(feature_matrix, weights) 
    return predictions 

def errors(output,predictions): 
    errors=predictions-output 
    return errors 

def feature_derivative(errors, feature): 
    derivative=np.dot(2,np.dot(feature,errors)) 
    return derivative 


def regression_gradient_descent(feature_matrix, output, initial_weights, step_size, tolerance): 
    converged = False 
    #Initital weights are converted to numpy array 
    weights = np.array(initial_weights) 
    while not converged: 
     # compute the predictions based on feature_matrix and weights: 
     predictions=predict_outcome(feature_matrix,weights) 
     # compute the errors as predictions - output: 
     error=errors(output,predictions) 
     gradient_sum_squares = 0 # initialize the gradient 
     # while not converged, update each weight individually: 
     for i in range(len(weights)): 
      # Recall that feature_matrix[:, i] is the feature column associated with weights[i] 
      feature=feature_matrix[:, i] 
      # compute the derivative for weight[i]: 
      #predict=predict_outcome(feature,weights[i]) 
      #err=errors(output,predict) 
      deriv=feature_derivative(error,feature) 
      # add the squared derivative to the gradient magnitude 
      gradient_sum_squares=gradient_sum_squares+(deriv**2) 
      # update the weight based on step size and derivative: 
      weights[i]=weights[i] - np.dot(step_size,deriv) 

     gradient_magnitude = math.sqrt(gradient_sum_squares) 
     stdout.write("\r%d" % int(gradient_magnitude)) 
     stdout.flush() 
     if gradient_magnitude < tolerance: 
      converged = True 
    return(weights) 


#Example of Implementation 
#Importing Training and Testing Data 
# train_data=pd.read_csv("kc_house_train_data.csv") 
# test_data=pd.read_csv("kc_house_test_data.csv") 

# simple_features = ['sqft_living', 'sqft_living15'] 
# my_output= 'price' 
# (simple_feature_matrix, output) = get_numpy_data(train_data, simple_features, my_output) 
# initial_weights = np.array([-100000., 1., 1.]) 
# step_size = 7e-12 
# tolerance = 2.5e7 
# simple_weights = regression_gradient_descent(simple_feature_matrix, output,initial_weights, step_size,tolerance) 
# print simple_weights 
9

In primo luogo, trovo che quando si scrive codice machine learning, è meglio NON da usare lista complessa di comprensione perché tutto ciò che si può iterare,

  • è più facile da leggere se scritta quando i cicli normali e indentazione e/o
  • può essere fatto con numpy broadcasting

e l'utilizzo di nomi di variabili adeguata può aiutare a capire meglio il codice. Usare Xs, Ys, Ws come mano corta è bello solo se sei bravo in matematica. Personalmente, non li uso nel codice, specialmente quando scrivo in python. Da import this: esplicito è meglio di implicito.

La mia regola empirica è ricordare che se scrivo codice non riesco a leggere 1 settimana dopo, è un codice errato.


In primo luogo, cerchiamo di decidere quale sia la parametri di input per la discesa del gradiente, è necessario:

  • feature_matrix (Il X matrice, tipo: numpy.array, una matrice di N dimensioni * D, dove N è il no di righe/datapoints e D è il no di colonne/caratteristiche)
  • uscita (il Y vettore, tipo:.. numpy.array, un vettore di dimensione N)
  • initial_weights (tipo: numpy.array, un vettore di dimensione D).

Inoltre, per verificare la presenza di una convergenza è necessario:

  • step_size (l'entità del cambiamento quando iterazione attraverso di modificare i pesi; Tipo: float, di solito un piccolo numero)
  • Tolleranza (i criteri per interrompere le iterazioni, quando la magnitudine della sfumatura è inferiore alla tolleranza, presupporre che i pesi siano stati convessi, digitare: float, in genere un numero piccolo ma molto più grande della st dimensione ep).

Ora al codice.

def regression_gradient_descent(feature_matrix, output, initial_weights, step_size, tolerance): 
    converged = False # Set a boolean to check for convergence 
    weights = np.array(initial_weights) # make sure it's a numpy array 

    while not converged: 
     # compute the predictions based on feature_matrix and weights. 
     # iterate through the row and find the single scalar predicted 
     # value for each weight * column. 
     # hint: a dot product can solve this easily 
     predictions = [??? for row in feature_matrix] 
     # compute the errors as predictions - output 
     errors = predictions - output 
     gradient_sum_squares = 0 # initialize the gradient sum of squares 
     # while we haven't reached the tolerance yet, update each feature's weight 
     for i in range(len(weights)): # loop over each weight 
      # Recall that feature_matrix[:, i] is the feature column associated with weights[i] 
      # compute the derivative for weight[i]: 
      # Hint: the derivative is = 2 * dot product of feature_column and errors. 
      derivative = 2 * ???? 
      # add the squared value of the derivative to the gradient magnitude (for assessing convergence) 
      gradient_sum_squares += (derivative * derivative) 
      # subtract the step size times the derivative from the current weight 
      weights[i] -= (step_size * derivative) 

     # compute the square-root of the gradient sum of squares to get the gradient magnitude: 
     gradient_magnitude = ??? 
     # Then check whether the magnitude is lower than the tolerance. 
     if ???: 
      converged = True 
    # Once it while loop breaks, return the loop. 
    return(weights) 

Spero che lo pseudo-codice esteso ti aiuti a capire meglio la discesa del gradiente. Non compilerò il ??? in modo da non rovinare i tuoi compiti.


Nota che il codice RSS è anche illeggibile e impossibile da mantenere. E 'più facile fare proprio:

>>> import numpy as np 
>>> prediction = np.array([1,2,3]) 
>>> output = np.array([1,1,5]) 
>>> residual = output - prediction 
>>> RSS = sum(residual * residual) 
>>> RSS 
5 

Passando attraverso basi NumPy andrà un lungo cammino per l'apprendimento della macchina e matrice-vettore di manipolazione senza andare dadi con iterazioni: http://docs.scipy.org/doc/numpy-1.10.1/user/basics.html

+0

È possibile modificare facilmente il codice di tolleranza su no. di iterazione (per ciclo), è sufficiente modificare la modalità di controllo del ciclo esterno. Ma la mia preferenza è quella di andare per la convergenza della tolleranza (while loop). – alvas

0

è così semplice

def mean(values): 
    return sum(values)/float(len(values)) 

def variance(values, mean): 
    return sum([(x-mean)**2 for x in values]) 

def covariance(x, mean_x, y, mean_y): 
    covar = 0.0 
    for i in range(len(x)): 
     covar+=(x[i]-mean_x) * (y[i]-mean_y) 
    return covar 
def coefficients(dataset): 
    x = [] 
    y = [] 

    for line in dataset: 
     xi, yi = map(float, line.split(',')) 

     x.append(xi) 
     y.append(yi) 

    dataset.close()        

    x_mean, y_mean = mean(x), mean(y) 

    b1 = covariance(x, x_mean, y, y_mean)/variance(x, x_mean) 
    b0 = y_mean-b1*x_mean 

    return [b0, b1] 

dataset = open('trainingdata.txt') 

b0, b1 = coefficients(dataset) 

n=float(raw_input()) 

print(b0+b1*n) 

di riferimento: www.machinelearningmastery.com/implement-simple-linear-regression-scratch-python/

Problemi correlati