线性回归—梯度下降python实现

import numpy as np
import pandas as pd

导入数据

data=pd.read_csv(r"F:\数据集\dataset\boston.csv")
data.head()
Unnamed: 0crimzninduschasnoxrmagedisradtaxptratioblacklstatmedv
010.0063218.02.3100.5386.57565.24.0900129615.3396.904.9824.0
120.027310.07.0700.4696.42178.94.9671224217.8396.909.1421.6
230.027290.07.0700.4697.18561.14.9671224217.8392.834.0334.7
340.032370.02.1800.4586.99845.86.0622322218.7394.632.9433.4
450.069050.02.1800.4587.14754.26.0622322218.7396.905.3336.2

编写线性回归-梯度下降类

class LinearRegression:
    """
    使用python语言实现线性回归算法(梯度下降法)
    """
    def __init__(self,alpha,times):
        """
        初始化方法:
        Parameters:
        ——————————
        alpha:float
               学习率,用来控制步长。(权重调整的幅度)
        times:int
             循环迭代的次数
        """
        self.alpha=alpha
        self.times=times
    
    def fit(self,X,y):
        """
        根据提供的训训练数据,对模型进行训练
        
        Parameters:
        ____________
        X:类数组类型。形状:[样本数量,特征数量]
            待训练的样本特征属性。(特征矩阵)
        y:类数组类型。形状:[样本数量]
           目标值(标签信息)
        """
        X=np.asarray(X)
        y=np.asarray(y)
        #创建权重的向量,初始值是0(或任何其他的值),长度要比特征数量多1个(多出的一个就是截距)
        self.w_=np.zeros(1+X.shape[1])
        #创建损失列表,用来保存每次迭代后的损失值。损失值计算:(预测值-真实值)的平方和除以2
        self.loss_=[]
        
        #进行循环,多次迭代。在每次迭代过程中,不断去调整权重值,是的损失值不断减小
        for i in range(self.times):
            #计算预测值
            y_hat=np.dot(X,self.w_[1:])+self.w_[0]
            #计算真实值与预测值之间的差距
            error=y-y_hat
            #将损失值加入到损失列表当中
            self.loss_.append(np.sum(error**2)/2)
            #根据差距调整权重w_,根据公式;调整为  权重(j)=权重(j)+学习率*sum((y-y_hat) *x(j))
            self.w_[0]+=self.alpha*np.sum(error)
            #注意理解下面这句
            self.w_[1:]+=self.alpha*np.dot(X.T,error)
    def predict(self,X):
        """
        根据参数传递的样本,对样本数据进行预测。
        Parameters:
        _____________
        X:类数组类型,形状:[样本数量,特征数量]
           需要进行测试的样本
        Returns:
        ___________
        result:数组类型
              预测的结果
        """
        X=np.asarray(X)
        result=np.dot(X,self.w_[1:])+self.w_[0]
        return result
        

测试

发现效果并不理想

lr=LinearRegression(alpha=0.001,times=20)
t=data.sample(len(data),random_state=0)
train_X=t.iloc[:400,:-1]
train_y=t.iloc[:400,-1]
test_X=t.iloc[400:,:-1]
test_y=t.iloc[400:,-1]
lr.fit(train_X,train_y)
result=lr.predict(test_X)
display(np.mean((result-test_y)**2))

1.1804176210461773e+210

特征缩放(标准化)–编写标准化类

  • 发现上面的效果并不好,甚至出现损失函数值越来越大的情况,究其原因,发现其各个特征的数量级相差较大,故进行特征缩放,使各个特征相差变小
class StandardScaler:
    """
    该类对数据进行标准化处理
    """
    def fit(self,X):
        """
        根据传递的样本,计算每个特征列的均值与标准差。 
        Parameters:
        ______________
        X:类数组类型
          训练数据,用来计算均值与标准差。
        """
        X=np.array(X)
        #按列计算标准差
        self.std_=np.std(X,axis=0)
        #按列计算均值
        self.mean_=np.mean(X,axis=0)
        
    def transform(self,X):
        """
        对给定的数据X ,进行标准化处理(将X 的每一列都变成标准正态分布的数据)
        Parameters:
        ——————————————
        X:类数组类型
           带转换的数据
        Return:
        _________
        result:类数组类型。
             参数X转换成标准正态分布后的结果
        """
        return (X-self.mean_)/self.std_
    
    def fit_transform(self,X):
        """
        对数据进行训练,并转换,返回转换之后的结果。
        Parameters:
        ____________
        X:类数组类型
            待转换的数据
        Return:
        ————————————
        result:类数组类型
            参数X转换成标准正态分布后的结果。
        """
        self.fit(X)
        return self.transform(X)
        

测试标准化类

  • 发现效果好很多
# 为了避免由每个特征数量级的不同而带来的梯度下降过程中的影响
#我们现在考虑对每个特征进行标准化处理
lr=LinearRegression(0.0005,times=20)
t=data.sample(len(data),random_state=0)
train_X=t.iloc[:400,:-1]
train_y=t.iloc[:400,-1]
test_X=t.iloc[400:,:-1]
test_y=t.iloc[400:,-1]
#对数据进行标准化处理
s=StandardScaler()
train_X=s.fit_transform(train_X)
test_X=s.fit_transform(test_X)

s2=StandardScaler()
train_y=s2.fit_transform(train_y)
test_y=s2.fit_transform(test_y)


lr.fit(train_X,train_y)
result=lr.predict(test_X)
display(np.mean((result-test_y)**2))
0.14911890500740144

可视化

#导入可视化库
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rcParams["font.family"]="SimHei"
mpl.rcParams["axes.unicode_minus"]=False

1. 绘制预测值

plt.figure(figsize=(10,10))
#绘制预测值
plt.plot(result,"ro-",label="预测值")
plt.plot(test_y.values,"go--",label="真实值")
plt.title("线性回归预测--梯度下降")
plt.xlabel("样本序号")
plt.ylabel("房价")
plt.legend()
plt.show()

在这里插入图片描述

2.绘制累计误差值

# 绘制累计误差值
plt.plot(range(1,lr.times+1),lr.loss_,"o-")
[<matplotlib.lines.Line2D at 0xa2b7870888>]

在这里插入图片描述

3.绘制 直线拟合 散点图

# 因为房价分析涉及多个维度,不方便进行可视化显示,为了实现可视化,我们只选取其中的一个维度(RM)
#并画出直线,实现拟合
lr=LinearRegression(alpha=0.0005,times=50)
t=data.sample(len(data),random_state=0)
#注意,下面不能写成train_X=t.iloc[:400,5],虽然这样同样是截取RM列,但是它是一个series类型(一维),而train_X本来是一个特征矩阵(二维)
#所以要写成train_X=t.iloc[:400,5:6]形式,这样返回一个dataframe结构(二维)  test_X同理
train_X=t.iloc[:400,6:7]
train_y=t.iloc[:400,-1]
test_X=t.iloc[400:,6:7]
test_y=t.iloc[400:,-1]
#display(train_X)
#对数据进行标准化处理
s=StandardScaler()
train_X=s.fit_transform(train_X)
test_X=s.fit_transform(test_X)
#display(train_X)
s2=StandardScaler()
train_y=s2.fit_transform(train_y)
test_y=s2.fit_transform(test_y)
lr.fit(train_X,train_y)
result=lr.predict(test_X)
display(np.mean(result-test_y**2))

-1.0000000000000002
plt.scatter(train_X["rm"],train_y)
#查看方程系数
lr.w_
#构建方程y=-3.07531778e-16+6.54984608e-01*x
x=np.arange(-5,5,0.1)
#display(x)
y=-3.07531778e-16+6.54984608e-01*x
plt.plot(x,y,"r")

#也可以这样做 ,但要注意,由于x是一维的,而predict(X)的参数是二维的,所以要用x.reshape(-1,1)将其转换为二维的形式
#plt.plot(x,lr.predict(x.reshape(-1,1)),"r")
[<matplotlib.lines.Line2D at 0xa2b2775048>]

在这里插入图片描述


  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值