使用Python实现梯度下降法处理回归问题

使用Python实现梯度下降法处理回归问题

我们这将使用[sklearn][6] 框架和手动方式实现梯度下降法对数据的回归操作
- 使用sklearn 框架
首先我们要导入sklearn 的包,代码如下:

    import numpy as np
    import pandas as pd
    import matplotlib.pyplot as plt
    import time
    from sklearn.linear_model import LinearRegression,Ridge,LassoCV,RidgeCV,ElasticNetCV
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.pipeline import Pipeline

我们导入了sklearn中常用的包,如LinearRegression,用来实现线性回归。

    np.random.seed(0)
    N = 10
    x = np.linspace(0,6,N)+np.random.randn(N)          #随机生成x
    y = 1.8 * x**3 + x**2 + 14*x -7 +np.random.randn(N)#将x映射到y
    x.shape = -1,1                                     #将x,y变成列向量
    y.shape = -1,1

为了简单起见,我们使用随机产生的简单数据

    plt.figure(figsize=(12,6),facecolor='w')
    x_hat = np.linspace(x.min(),x.max(),num=100)
    x_hat.shape = -1,1

    #线性模型
    model = LinearRegression()  #定义好一个线性回归的类
    model.fit(x,y)              #对模型进行拟合
    y_hat = model.predict(x_hat)#预测x_hat相对应的y,命名为y_hat
    s1 = calcRScore(y,model.predict(x))   #calcRScore是手写的评价函数,不是sklearn中的函数,在下面会提出
    print(model.score(x,y))
    print('模块自带输出实现=======================')
    print('参数列表:',model.coef_)
    print('截距:',model.intercept_)

这样操作之后,我们实现了利用sklearn 的线性回归,画出拟合直线观察:
使用Python实现梯度下降法处理回归问题_第1张图片
- 手动实现梯度下降
首先我们介绍一下梯度下降法的基本思想,如果要求某个函数的极值,最好的方法就是沿着该函数的梯度方向探寻,如果将函数的梯度记为 ,则函数 f(x,y) f ( x , y ) 的梯度有下表示:

f(x,y)=f(x,y)xf(x,y)y ∇ f ( x , y ) = ( ∂ f ( x , y ) ∂ x ∂ f ( x , y ) ∂ y )

在数学中,梯度方向可以理解为当前点向极值位置移动最快的点。所以我们在求拟合直线的目标可以看成是求直线的权重 w w ,(因为直线方程在广义上的定义: wTx=0 w T ∗ x = 0 ),因此我们使用梯度下降法来更新,

#手动实现梯度下降法
def validate(X,Y):                #判断输入X,Y,的数量是否相等
    if(len(X) != len(Y)):
        raise Exception("参数异常")
    else:
        m =len(x[0])             #判断X数据内部特征量是否异常
        for i in X:
            if len(i) !=m:
                raise Exception("参数异常")
        if len(Y[0]) != 1:        #判断Y
            raise Exception("参数异常")
def calcDiffe(x,y,a):               #计算损失
    lx = len(x)
    la = len(a)
    if lx ==la:                    #如果权重量和X的行数(也就是数据量)相等
        result = 0
        for i in range(lx):
            result += x[i]*a[i]    #则对应相乘
        return y-result
    elif lx +1 ==la:               #若是不等(X 有偏置,也就是存在常数项)
        result = 0
        for i in range(lx):
            result += x[i]*a[i]
        result +=1*a[lx]           #在对应相乘的基础上加上常数项
        return y-result
    else:
        raise Exception("参数异常")
def fit(X,Y,alphas,thresh=1e-16,maxIter=20,addConstantItem=True):       #训练函数
    import math
    import numpy as np
    validate(X,Y)
    l = len(alphas)                                                     #alpha数,我们在l个alpha中寻找最好的alpha
    m = len(Y)                                                          #可以理解成数据量
    n = len(x[0])+1 if addConstantItem else len(x[0])                   #X的特征量(当addConstantItem 为True 时,给X 加上偏置量) 
    B = [True for i in range(l)]                                        #判断alpha是否已最优
    J = [np.nan for i in range(l)]                                      #存放对应alpha的损失
    a = [[0 for j in range(n)] for i in range(l)]                       #存放对应alpha的权重(w)
    #开始计算
    for times in range(maxIter):                                                                          
        for i in range(l):                                              #遍历alpha
            if not B[i]:                                                #如果当前alphas已经找到最优值,则不进行计算
                continue
            ta = a[i]                                                   
            for j in range(n):                                          #遍历特征
                alpha = alphas[i]        
                ts = 0  
                for k in range(m):                                      #遍历数据
                    if j == n -1 and addConstantItem:
                        ts += alpha*calcDiffe(X[k],Y[k][0],a[i])*1      #梯度(无偏置)
                    else:
                        ts += alpha*calcDiffe(X[k],Y[k][0],a[i])*X[k][j]#梯度(有偏置)
                t = ta[j] +ts                                           
                ta[j] = t                                                #更新权重
                                                                         #所有特征遍历完毕
            flag = True
            js = 0
            for k in range(m):                                           #这个循环是计算损失
                js += math.pow(calcDiffe(X[k],Y[k][0],a[i]),2)
                if js > J[i]:                                            #如果
                    flag = False
                    break
            if flag:
                J[i] = js
                for j in range(n):
                    a[j][j] = ta[j]
            else:
                B[i] = False
        #计算完一个循环,当目标函数小于一个阈值,则结束循环
        r = [0 for j in J if j <= thresh]
        if len(r) >0:
            break
        r = [0 for b in B if not b]
        if len(r)>0:
            break

    min_a = a[0]
    min_j = J[0]
    min_alpha = alphas[0]
    for i in range(l):
        if J[i] '最优的alpha值为:',min_alpha)

    return min_a
def predict(X,a):
    Y=[]
    n =len(a) - 1
    for x in X:
        result = 0
        for i in range(n):
            result += x[i]*a[i]
        result += a[n]
        Y.append(result)
    return Y
def calcRScore(y,py):
    if len(y) != len(py):
        raise Exception("参数异常")
    import math
    import numpy as np
    avgy = np.average(y)
    m = len(y)
    rss = 0.0
    tss = 0
    for i in range(m):
        rss += math.pow(y[i]-py[i],2)
        tss += math.pow(y[i]-avgy,2)
    r = 1.0 - 1.0*rss/tss
    return r
#自模型
print('y: ',y)
ma = fit(x,y,np.logspace(-4,-2,100),addConstantItem=True)
y_hat2 = predict(x_hat,ma)
s2 = calcRScore(y,predict(x,ma))
print('自定义参数==============================')
print('参数列表',ma)

#开始画图
plt.plot(x,y,'ro',ms=10,zorder = 3)
plt.plot(x_hat,y_hat,color='#b624db',lw=2,alpha=0.75,label='thc01 $R:%.3f'%s1,zorder=2)
# plt.plot(x_hat,y_hat2,color='#6d49b6',lw=2,alpha=0.75,label='thc01 $R:%.3f'%s2,zorder=1)
plt.legend('upper left')
plt.grid(True)
plt.xlabel('X',fontsize=16)
plt.ylabel('Y',fontsize=16)

plt.suptitle('The Change',fontsize=22)
plt.show()

使用Python实现梯度下降法处理回归问题_第2张图片

你可能感兴趣的:(机器学习)