机器学习中线性回归算法python实现

线性回归算法python实现(单变量)

先来回顾一下相关公式:

1.正规方程

机器学习中线性回归算法python实现
机器学习中线性回归算法python实现 是不可逆时,称为奇异阵或退化阵,也称伪逆阵。
原因:
 多余的功能(线性相关性),一个特征是平方英尺,一个特征是平方米。
 特征太多,删除一些特征, 或使用正则化

theta=np.linalg.inv(X.T.dot(X)).dot(X.T).dot(Y)

2.代价函数

机器学习中线性回归算法python实现

J = (1.0/(2*m))*np.sum(np.square(X.dot(theta)-y))	
J = (1.0/(2*m))*(X.dot(theta)-y).T.dot(X.dot(theta)-y)
3.梯度下降

机器学习中线性回归算法python实现

deltaTheta = (1.0/m)*(X.T.dot(X.dot(theta)-y))
 theta = theta-alpha*deltaTheta
或  Theta = theta-alpha*(1.0/m))*X.T.dot(X.dot(theta)-y)

求得最优线性回归一般有两种方式,一种是正解方程,一种是梯度下降
代码里都有相关解释,两种方式都有实现

import numpy as np
import matplotlib.pyplot as plt
import matplotlib as mpl
mpl.rcParams['font.sans-serif'] = ['SimHei']  # 在图中正确显示中文

# 数据预处理
x = np.array([1.5,0.8,2.6,1.0,0.6,2.8,1.2,0.9,0.4,1.3,1.2,2.0,1.6,1.8,2.2])
y = np.array([3.1,1.9,4.2,2.3,1.6,4.9,2.8,2.1,1.4,2.4,2.4,3.8,3.0,3.4,4.0])
x = np.c_[np.ones((len(x), 1)), x.T]       # 按列方向组合,X=[[1, x(1)], [1, x(2)]…]
y = np.c_[y.T]    # 按列方向组合, y=[[y(1)],[y(2)]…]

# 模型
def model(x, theta):
    h = x.dot(theta)  # 预估值h
    return h

# 代价函数
def cost(h, y):
    m = len(h)  # 计算样本数
    e = h - y   # 误差
    J = 1.0/(2*m)*np.sum(e.T.dot(e))  # 计算代价
    return J

#梯度下降求最优解
# alpha=0.001学习率
# count_iter=15000迭代次数
def gradDesc(x, y, alpha=0.01, count_iter=15000):
    m, n = x.shape  # sharp返回值是元组(行,列)并赋值给m,n
    theta = np.zeros((n, 1))  # 定义theta初始值,theta为矩阵(从初始值开始,沿着初始值下降)
    jarr = np.zeros(count_iter)  # 代价数组(多维数组<class 'numpy.ndarray'>)[0. 0. 0. ... 0. 0. 0.]
    # 对theta进行更新
    for i in range(count_iter):
        h = model(x, theta)  # 计算预估值
        jarr[i] = cost(h, y)  # 计算代价并存入数组
        e = h - y  # 计算误差
        deltatheta = (1.0/m)*x.T.dot(e)  # 计算deltatheta(梯度下降)
        theta -= alpha*deltatheta  # 更新deltatheta(迭代)

    return jarr, theta

# 正解方程
def eqution(x, y):
    theta = np.dot(np.linalg.inv(x.T.dot(x)),x.T.dot(y))
    return theta

#模型得分,精度(看模型的准确性,越接近1越准确)
def score(h, y):
    u = np.sum((h-y)**2)   # 误差平方和
    v = np.sum((y-y.mean())**2)   # 方差  mean()求平均数
    return 1-u/v

# 训练模型
# 调用正解方程得到最优模型
# theta=  eqution(x ,y)

# 调用梯度下降得到最优模型
jarr, theta = gradDesc(x, y)

# 预估值
h = model(x,theta)

print("线性回归精度:", score(h, y))

# 画代价曲线
# plt.plot(jarr)
# plt.title("代价曲线")
# plt.show()

# 画样本数据散点图和线性模型图
plt.figure('单变量线性回归')          # 定义图形窗口(名称)
plt.scatter(x[:,-1], y, c='b',marker='x', label='原值')   # 画样本数据的散点图 (默认线形 ’·’,marker定义散点样式)
plt.plot(x[:,-1], h, c='r')  # 画模型
plt.title('线性回归和散点图')  # 定义图形标题
plt.legend(loc='upper left')  # 显示图例
plt.show()   # 显示图形
代价函数图

机器学习中线性回归算法python实现
代价函数曲线值越接近0,说明越接近标准值

单变量线性回归图

机器学习中线性回归算法python实现

梯度下降与正规方程的比较
梯度下降 正规方程
需要选择学习率α 不需要
需要多次迭代 一次运算得出
当特征数量n大时也能较好的shi适用 特征数量n较大则运算代价大,因为矩阵逆的计算时间复杂度为o(n³),通常来说当n小于10000时还是可以接受的
适用于各种类型模型 只适用于线性模型,不适合逻辑回归模型等其他模型
梯度下降(批量梯度下降)

梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出代价函数J(θ0,θ1) 的最小值。
梯度下降背后的思想是:开始时我们随机选择一个参数的组合(θ0,θ1),计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。

 α是学习率(learning rate),大于0的一个很小经验值,它决定沿着能让代价函数下降的程度有多大。
 每一次都同时让所有的参数减去学习速率乘以代价函数的导数。
 “批量梯度下降”,指的是在梯度下降的每一步中,都要用到了所有的训练样本,因为代价函数是所有训练样本估计误差的平方和。

如果 α 太小,梯度下降就会变慢。
如果α太大,梯度下降法可能会越过最低点。甚至可能无法收敛,或者偏离。