机器学习------多元线性回归算法


目前为止,我们探讨了 单变量/特征的回归模型,现在我们对房价模型增加 更多的特征,例如房间数楼层等,构成一个含有 多个变量的模型。

多元梯度下降法

模型:
在这里插入图片描述
参数:

θ0,θ1,……θn

损失函数:

在这里插入图片描述

梯度下降公式:同时更新所有参数

在这里插入图片描述

多元批梯度下降

在这里插入图片描述
代码如下:

分析:每一行对应一个输出,每一列为一个特征。每三个特征值确定一个标签,将三类特征作为输入,对应的标签值作为输出。
import numpy as np
from sklearn.linear_model import LinearRegression #在线性模型中导入线性回归
X2 = np.array([3,1,2,1,2]).reshape(-1,1)#x从一维转为二维
X1 = np.array([5,1,2,2,3]).reshape(-1,1)#x从一维转为二维
X3 = np.array([-1*2,2,2,3,4]).reshape(-1,1)#x从一维转为二维
X=np.c_[X2,X1,X3]
Y= np.array([3,4,12,4,13])
#实例化对象
lin_reg= LinearRegression()
#调用fit方法 训练模型找规律
lin_reg.fit(X,Y)
#找到规律 截距与斜率
print(lin_reg.intercept_,lin_reg.coef_)
#预测x=12对应的Y
X_new=np.array([[12,15,17]]) #创建数组
print(lin_reg.predict(X_new))


执行结果:
-7.609756097560967 [10.38617886 -3.14634146  2.38617886]
[110.39430894]

注意:尝试在如下的数值中选择α : 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1,…

三种梯度下降总结

  • 批:一次使用梯度下降公式跑所有的数据。每下降一步,使用所有训练集来计算梯度值。

  • SGD: 一次使用1个数据,每下降一步,使用一条训练集来计算梯度值。

  • Mini-batch:一次使用一批数据,一批是多少,大家可以自己指定。每下降一步,使用一部分训练集来计算梯度值。

  • 代码注意点:以随机梯度下降SGD为例 该怎么做:如下图,使用for循环随机从样本中抽取一条数据也就是xi、yi为一行一列的值,去进行梯度计算、然后循环样本数次,这样整个样本都经过了计算。
    1.

训练集比较小: 使用批梯度下降(小于2000个)
训练集比较大:使用Mini-bitch梯度下降 一般的Mini-batch size 是64,128,256, 512,1024, Mini-batch size要适用CPU/GPU的内存
在这里插入图片描述

随机梯度下降

  • 随机梯度下降思想:随机使用一个数据。把m个样本分成m份,每次用1份做梯度下降;也就是说,当有m个样本时,批梯度下降只能做一次梯度下降,但是随机梯度下降可以做m次。
  • 假设有100个样本,批梯度下降一次使用100个样本更新theta 一次就是epoch,随机梯度下降一次使用1个样本 样本数为m个,m次为一个epoch,如果设置n_epochs=n,theta更新了mn次。
"""
使用衰减学习率的随机梯度下降
"""
import numpy as np
import random
X = 2*np.random.rand(100,1)
Y=4+3*X+np.random.randn(100,1)
X_b=np.c_[np.ones((100,1)),X]
n_epochs=500
a0=0.1
decay_rate=1
m=100
num=[i for i in range(m)]
def learning_schedule(epoch_num): #衰减学习率的公式
    return (1.0/(decay_rate*epoch_num +1))*a0
theta=np.random.randn(2,1)
for epoch in range(n_epochs):#用m个样本做n_epochs个轮代
    rand=random.sample(num,100) #生成100行、100列,每一行都是100个不重复的随机数
    #print(rand)
    for i in range(m):
       random_index=rand[i] #索引
       xi=X_b[random_index:random_index+1]#随机从X_b与Y中找一个数据
       yi=Y[random_index:random_index+1]
       gradients=xi.T.dot(xi.dot(theta)-yi) #只用了一个数据不需要求平均值
       learning_rate=learning_schedule(epoch+i)#每更新一次theta学习率也更新,收敛更准确
       theta= theta - learning_rate * gradients
print(theta)


执行结果:
[[4.16191884]
 [2.84624263]]

Mini-batch梯度算法优化

随机梯度下降会丧失向量带来的加速,所以我们不会太用随机梯度下降。
如果 mini-batch 大小 = m : 那他就是批梯度下降
如果 mini-batch 大小 = 1 : 那他就是随机梯度下降
如果 mini-batch 1 < 大小 < m :那他就是‘Mini-batch’随机梯度下降

优化: 学习率衰减
在做Mini-batch的时候,因为噪声的原因,可能训练结果不是收敛的,而是在最低点周围晃动,如果我们要解决这个问题,那我们就需要减少学习率,让他在尽量小的范围内晃动
1 epoch = 1 次遍历所有的数据
学习率衰减公式:
在这里插入图片描述

Mini-batch梯度下降:将100个数据分成5份 每份20个,一次执行20个数据

import numpy as np
import random

X = 2 * np.random.rand(100, 1)
y = 4 + 3 * X + np.random.randn(100, 1)
X_b = np.c_[np.ones((100, 1)), X]
# print(X_b)

n_epochs = 500
t0, t1 = 5, 50

m = 100
num = [i for i in range(100)]

def learning_schedule(t):
    return float(t0) / (t + t1)

theta = np.random.randn(2, 1)

batch_num = 5
batch_size = m // 5

# epoch 是轮次的意思,意思是用m个样本做一轮迭代
for epoch in range(n_epochs):
    # 生成100个不重复的随机数
    for i in range(batch_num):
        start = i*batch_size
        end = (i+1)*batch_size
        xi = X_b[start:end]
        yi = y[start:end]
        gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi)
        learning_rate = learning_schedule(epoch*m + i)
        theta = theta - learning_rate * gradients

print(theta)

执行结果:
[[4.07699116]
 [2.9148502 ]]

多项式回归

我们一般的线性回归只能处理线性的数据,如果遇到数据形状是曲线这样的,那不是就没办法了?

多项式回归其实就是对线性回归升维的过程。比如:

y = w0x0 + w1x1 这个公式是一个二元一次方程,一次就代表了他是一条直线

对y升维: y = v0x0 +v1x1 + v2x0x0 + v3x1x1 + v4x1x2

转变
y_新 = v0a0 + v1a1 + v2a2 + v3a3 + v4a4 (其中a0 = x0, a1 = x1, a2 = x0x0, a3 = x1x1, a4 = x0x1)
做了转变以后,我们的新函数又变回了线性回归了

不同维度绘制的图形


"""
多项式拟合:一阶x组成二阶生维数据 改变原始数据特征 再当作一阶的数据做线性回归求参
"""
import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures #导入预处理包中的多项式特征提取
from sklearn.linear_model import LinearRegression
m=100
X=6*np.random.rand(m,1)-3
Y=0.5*X**2+X+2+np.random.randn(m,1)
d={1:'g-',2:'r+',10:'y*'}
for i in d:
    poly_features=PolynomialFeatures(degree=i,include_bias=False)#include_bias=False表示不要偏差,截距为0
    X_poly=poly_features.fit_transform(X) #对原数据生维产生新的数据特征
    print(X_poly)
    #当作一阶的数据做线性回归
    lin_reg=LinearRegression()
    lin_reg.fit(X_poly,Y) #求参
    y_predict=lin_reg.predict(X_poly) #对生维的数据预测曲线结果
    plt.plot(X_poly[:, 0],y_predict,d[i])  #X_poly[:,0]取第一列的值
plt.show()

在这里插入图片描述
对于已知数据进行多项式拟合:心电波形的绘制
X扩充如下才可以对应每一个Y:
[11111111111111111111] #XYshape相同,X与Y的每一个位置都要一一对应
[222222222222222222]
[333333333333333333]

[23 23 23 23 23 … 23]

"""
拟合心电信号,每一个输出要对应一个输入。每一列是一个数据,共8965列,共8965个数据
Y,X要扩充
数据大小为23x8965 要让输入输出shape相同 输入输出均为n行一列
由于数据格式的特殊性:即每一列为一个输出。每一类特征值的数量要与输出值(样本数)的数量相同。Y有23行8965列,表示有8965个样本数,因此每一类特征值的数量也应该为8965个,
本案例X只有一个特征:时间。为1-23秒  Y为23行8965列的所有值,所有行轮回一次为一个输出波形
 """
 import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures #导入预处理包中的多项式特征提取
from sklearn.linear_model import LinearRegression
import pandas as pd

data = pd.read_excel('C:/Users/scq/Desktop/pycharmprodect/机器学习code/dataSet/rb.xlsx')
Y=np.array(data) #转成2维数组
#count=Y.shape[0] #打印多少行多少列(23,8965)
X=[]
for item in range(np.array(data).shape[0]): 
    x=[item for  j in range(np.array(data).shape[1])] #每一个Y对应一个X
    X.extend(x)
X=np.array(X).reshape(-1,1) #8965行1列
Y=Y.reshape(-1,1) #8965行1列
lin_reg=LinearRegression()
poly_features=PolynomialFeatures(degree=10,include_bias=False)#include_bias=False表示不要偏差,截距为0
X_poly=poly_features.fit_transform(X) #对原数据生维求值得出新的数据特征
#当作一阶的数据做线性回归
lin_reg.fit(X_poly,Y) #求参
X_predict=np.array([i for i in range(23)]).reshape(-1,1) #随意输入一组时间,的出一组预测值连成一条线
X_poly1=poly_features.fit_transform(X_predict) #把X_predict生成10维
y_predict=lin_reg.predict(X_poly1) #对生维的预测数据预测曲线结果
plt.plot(X_predict,y_predict,'b-')
plt.show()

在这里插入图片描述
保险保费的多元线性回归模型案例
数据信息如下图:
在这里插入图片描述
我们已经获取到保险公司部分数据,文件名为insurance.csv,文件内容如下。
我们可以看出数据中共有六个维度:age(年龄),sex(性别),bmi(肥胖指数),children(孩子数量),smoker(是否吸烟),region(居住地)。charges则是当前数据人上年度在保险的额度。
所以我们可以构建一个六维高维空间来求解这个模型。

相对于年龄来说, 年龄越大, 购买保险的金额应该越大;
相对于性别来说,整体女性的寿命大于男性寿命大约10年, 因此男性的保险额度应该更大。
相对于肥胖指数来说, 肥胖指数越小, 身体状况越不好, 购买保险的金额应该越大;
相对于孩子的数量来说, 孩子的数量越多, 压力越大, 越劳累, 购买保险的金额应该越大;
相对于是否吸烟来说, 吸烟的人寿命远少于不吸烟的寿命, 因此 购买保险的金额应该越大;
相对于地区来说, 地区环境越差, 有雾霾, 则越容易生病, 那么购买保险的金额应该越大;

实战:
如何从训练数据中估计统计量。
如何从数据估计线性回归系数。
如何使用线性回归预测新数据

import numpy as np
import matplotlib.pyplot as plt
from sklearn.preprocessing import PolynomialFeatures #导入预处理包中的多项式特征提取
from sklearn.linear_model import LinearRegression
import pandas as pd
data = pd.read_csv('C:/Users/scq/Desktop/pycharmprodect/机器学习code/dataSet/insurance.csv')
reg=LinearRegression()
x=data[['age','sex','bmi','children','smoker','region']]
x=x.apply(pd.to_numeric,errors='coerce') #将文字转为0
y=data['charges']
y=y.apply(pd.to_numeric,errors='coerce')
x.fillna(0,inplace=True)
y.fillna(0,inplace=True)
poly_features=PolynomialFeatures(degree=10,include_bias=False)#include_bias=False表示不要偏差,截距为0
X_poly=poly_features.fit_transform(x)
reg.fit(X_poly,y)
y_predict=reg.predict(X_poly)
plt.plot(X_poly[:,0],y_predict,'r.') #看年龄与金钱的关系
plt.plot(x['age'],y,'b.')
plt.show()

在这里插入图片描述

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值