梯度下降与GradientBoostingRegressor、LinearRegression比较

#_*_coding:utf-8_*_
#建造一个最简单的梯度下降
def regression(data,alpha,lamba):
    import numpy as np
    n=len(data[0])-1  #获取data第一个数据的长度
    theta=np.zeros(n)   #初始化theta  返回的是array([ 0.,  0.,  0.,  0.,  0.])
    for times in range(100):
        for d in data:
            x=d[:-1]
            y=d[-1]
            g=np.dot(theta,x)-y
            theta=theta-alpha*g*x+lamba * theta 
        print(times,theta)
    return theta

# 构造一个完整的梯度下降算法

# 数据校验
def validate(X, Y):
    if len(X) != len(Y):
        raise Exception("参数异常")
    else:
        m = len(X[0])
        for l in X:
            if len(l) != 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:
        result = 0
        for i in range(lx):
            result += x[i] * a[i] #theta1*x1
        return y - result
    elif lx + 1 == la:
        result = 0
        for i in range(lx):
            result += x[i] * a[i]  #theta0+theta1*x1
        result += 1 * a[lx]  # 加上常数项
        return y - result
    else:
        raise Exception("参数异常")


## 要求X必须是List集合,Y也必须是List集合 alphas 是步长 threshold阈值 maxIter最大迭代次数
def fit(X, Y, alphas, threshold=1e-6, maxIter=200, addConstantItem=True):
    import math
    import numpy as np
    ## 校验
    validate(X, Y)
    ## 开始模型构建
    l = len(alphas)
    m = len(Y)
    n = len(X[0]) + 1 if addConstantItem else len(X[0])  # 样本的个数  是否要截距项 ,要就加一
    B = [True for i in range(l)]  # 模型的格式:控制最优模型   [True, True, True, True, True]
    ## 差异性(损失值)
    J = [np.nan for i in range(l)]  # loss函数的值  [nan, nan, nan, nan, nan]
    # 1. 随机初始化0值(全部为0), a的最后一列为常数项
    a = [[0 for j in range(n)] for i in range(l)]  # theta,是模型的系数  [[0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
    # 2. 开始计算
    for times in range(maxIter):  #最大迭代次数
        for i in range(l):  #alphas步长的总个数
            if not B[i]:
                # 如果当前alpha的值已经计算到最优解了,那么不进行继续计算
                continue

            ta = a[i]      # theta,第i个模型的系数
            for j in range(n):
                alpha = alphas[i]
                ts = 0
                for k in range(m):
                    if j == n - 1 and addConstantItem:   # 计算差异值  真实值与预测值的差异  calcDiffe
                        ts += alpha * calcDiffe(X[k], Y[k][0], a[i]) * 1      #迭代公式常数项
                    else:
                        ts = ts + alpha * calcDiffe(X[k], Y[k][0], a[i]) * X[k][j]  #迭代公式
                t = ta[j] + ts
                ta[j] = t
            ## 计算完一个alpha值的0的损失函数
            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:  #判断 true 表示本轮的结果比上次损失小,要保存结果
                J[i] = js  #保存损失
                for j in range(n):
                    a[i][j] = ta[j]   #保存theta
            else:
                # 标记当前alpha的值不需要再计算了
                B[i] = False
                ## 计算完一个迭代,当目标函数/损失函数值有一个小于threshold的结束循环
        r = [0 for j in J if j <= threshold]
        if len(r) > 0:
            break
        # 如果全部alphas的值都结算到最后解了,那么不进行继续计算
        r = [0 for b in B if not b] #看看达到阈值没有
        if len(r) > 0:
            break;
    # 3. 获取最优的alphas的值以及对应的0值
    min_a = a[0]
    min_j = J[0]
    min_alpha = alphas[0]
    for i in range(l):
        if J[i] < min_j:
            min_j = J[i]
            min_a = a[i]
            min_alpha = alphas[i]

    print("最优的alpha值为:", min_alpha)

    # 4. 返回最终的theta值
    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

import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
import pandas as pd
import warnings  #仅用于提示,而不中断执行
import sklearn
from sklearn.linear_model import LinearRegression,Ridge, LassoCV, RidgeCV, ElasticNetCV
from sklearn.preprocessing import PolynomialFeatures #可以理解为专门生成多项式特征,并且多项式包含的是相互影响的特征集
from sklearn.pipeline import Pipeline #管道机制实现了对全部步骤的流式化封装和管理
from sklearn.linear_model.coordinate_descent import ConvergenceWarning
#其实就是迭代了200次但是还是没达到最佳拟合,只需要在创建MLPRegressor的时候加一个

## 设置字符集,防止中文乱码
mpl.rcParams['font.sans-serif']=[u'simHei']
mpl.rcParams['axes.unicode_minus']=False

# warnings.filterwarnings(action = 'ignore', category=ConvergenceWarning)
## 创建模拟数据
np.random.seed(0) #random.seed(something)只能是一次有效
np.set_printoptions(linewidth=1000, suppress=True)
# 当ndarray里面的存放的数据维度过大时,
# 在控制台会出现不能将ndarray完全输出的情况,
# 中间部分的结果会用省略号打印出来。
# 这时就需要用到numpy里面的set_printoptions()方法。
# set_printoptions(precision=None,
#                  threshold=None,
#                  edgeitems=None,
#                  linewidth=None,
#                  suppress=None,
#                  nanstr=None,
#                  infstr=None,
#                  formatter=None)
# precision:输出结果保留精度的位数
# threshold:array数量的个数在小于threshold的时候不会被折叠
# edgeitems:在array已经被折叠后,开头和结尾都会显示edgeitems个数
# formatter:这个很有意思,像python3里面str.format(),就是可以对你的输出进行自定义的格式化
N = 10
x = np.linspace(0, 6, N) + np.random.randn(N) #返回10个标准正态分布样本值。
y = 1.8*x**3 + x**2 - 14*x - 7 + np.random.randn(N)
x.shape = -1, 1
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)
s1 = calcRScore(y, model.predict(x))
print(model.score(x,y)) ## 自带R^2输出
print ("模块自带实现===============")
print ("参数列表:", model.coef_)
print ("截距:", model.intercept_)


## 自模型
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)
plt.plot(x_hat, y_hat, color='#b624db', lw=2, label=u'Python模型,$R^2$:%.3f' % s1)
plt.plot(x_hat, y_hat2, color='#6d49b6', lw=2, label=u'自己实现模型,$R^2$:%.3f' % s2)
plt.legend(loc = 'upper left')
plt.grid(True)
plt.xlabel('X', fontsize=16)
plt.ylabel('Y', fontsize=16)

plt.suptitle(u'自定义的线性模型和模块中的线性模型比较', fontsize=22)
plt.show()

from sklearn.ensemble import GradientBoostingRegressor
clf = GradientBoostingRegressor()
y1 = y.ravel()
clf.fit(x,y1)
print ("自带梯度下降法R方:", clf.score(x,y1))
y_hat3=clf.predict(x_hat)
s3=calcRScore(y, clf.predict(x))

# 开始画图
plt.plot(x, y, 'ro', ms=10)
plt.plot(x_hat, y_hat, color='#b624db', lw=2, label=u'Python模型,$R^2$:%.3f' % s1)
plt.plot(x_hat, y_hat2, color='#6d49b6', lw=2, label=u'自己实现模型,$R^2$:%.3f' % s2)
plt.plot(x_hat, y_hat3, color='#6daaba', lw=2, label=u'自带梯度下降方法,$R^2$:%.3f' % s3)
plt.legend(loc = 'upper left')
plt.grid(True)
plt.xlabel('X', fontsize=16)
plt.ylabel('Y', fontsize=16)

plt.suptitle(u'自定义的线性模型和模块中的线性模型比较', fontsize=22)
plt.show()

你可能感兴趣的:(python)