You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
pi4w7f6st c8ff6aeda5
Update README.md
10 months ago
README.md Update README.md 10 months ago

README.md

使用python实现线性回归预测通过梯度下降法实现数据集为波士顿房价数据集。

In [1] import numpy as np import pandas as pd import matplotlib as mpl import matplotlib.pyplot as plt /opt/conda/envs/python35-paddle120-env/lib/python3.7/importlib/_bootstrap.py:219: RuntimeWarning: numpy.ufunc size changed, may indicate binary incompatibility. Expected 192 from C header, got 216 from PyObject return f(*args, **kwds) 波士顿房价数据集字段说明

CRIM 房屋所在镇的犯罪率 ZN 面积大于25000年平方英尺住宅所占的比例 INDUS 房屋所在镇非零售区域所占比例 CHAS 房屋是否位于河边,如果位于河边,则值为1,否则值为0 NOX 一氧化氮的浓度 RM 平均房间数量 AGE 1940年前建成房屋所占的比例 DIS 房屋距离波士顿五大就业中心的加权距离 RAD 距离房屋最近的公路 TAX 财产税额度 PTRATI0房屋所在镇师生比例 B 计算公式1000×(房屋所在镇非美籍人口所在比例-0.63)^2 LSTAT 弱势群体人口所占比例 EDV 房屋的平均价格 In [2] data = pd.read_csv('data/data92436/boston.csv')

data

查看数据的基本信息。同时也可以用来查看各个特征列是否存在缺失值。

data.info()

查看是否具有重复值

data.duplicated().any() False In [3] data.head() crim zn indus chas nox rm age dis rad tax ptratio
0 0.00632 18.0 2.31 0 0.538 6.575 65.2 4.0900 1 296 15.3
1 0.02731 0.0 7.07 0 0.469 6.421 78.9 4.9671 2 242 17.8
2 0.02729 0.0 7.07 0 0.469 7.185 61.1 4.9671 2 242 17.8
3 0.03237 0.0 2.18 0 0.458 6.998 45.8 6.0622 3 222 18.7
4 0.06905 0.0 2.18 0 0.458 7.147 54.2 6.0622 3 222 18.7

black  lstat  medv  

0 396.90 4.98 24.0
1 396.90 9.14 21.6
2 392.83 4.03 34.7
3 394.63 2.94 33.4
4 396.90 5.33 36.2
In [4] class LinearRegression: '''使用python语言实现线性回归算法。梯度下降'''

def __init__(self, alpha, times):
    '''初始化方法。
    
    Parameters
    -----
    alpha : float
            学习率。用来控制步长。(权重调整的幅度)
            
    times : int
            循环迭代的次数。
    '''
    self.alpha = alpha
    self.times = times
    
def fit(self, X, y):
    '''根据提供的训练数据X对模型进行训练。
    
    Parameters
    ------
    X : 类数组类型。形状:[样本数量,特征数量]
        待训练的样本特征属性。(特征矩阵)。
        
    y : 类数组类型,形状: [样本数量]
        目标值(标签信息)。
    '''
    
    X = np.asarray(X)
    y = np.asarray(y)
    # 创建权重的矩阵初始值为0长度比特征数量多1。多出的一个值就是截距
    self.w_ = np.zeros(1 + X.shape[1])
    # 创建损失列表,用来保存每次迭代后的损失值。损失值计算: (预测值 - 真实值)的平方和,使得损失值不断减小。
    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 * 1)     # 与截距相乘的x0都为1
        self.w_[1:] += self.alpha * np.dot(X.T, error)
    
def predict(self, X):
    '''根据参数传递的样本X对样本数据进行预测。
    
    Parameters
    -----
    X  类数组类型。形状:[样本数量,特征数量]
        待预测的样本特征(属性)。
        
    Returns
    ----
    result : 数组类型
             预测的结果。
    '''
    
    X = np.asarray(X)
    result = np.dot(X, self.w_[1:]) + self.w_[0]
    return result

In [5]

数据未进行标准化

lr = LinearRegression(alpha=0.005,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)) display(lr.w_) display(lr.loss_) 2.528374379147838e+234 array([-4.91983295e+111, -2.24266008e+112, -4.88602630e+112, -5.87176682e+112, -3.32127982e+110, -2.77955977e+111, -3.06712887e+112, -3.47971590e+113, -1.79076291e+112, -5.41290922e+112, -2.15392269e+114, -9.17751422e+112, -1.75008714e+114, -6.49730426e+112]) [116831.44, 3.5215413268418916e+16, 1.3578663249157683e+28, 5.2389621806716426e+39, 2.0213194925954355e+51, 7.798744151422259e+62, 3.0089459171760135e+74, 1.1609248049051771e+86, 4.479131362749877e+97, 1.7281582476315742e+109, 6.667656487358543e+120, 2.5725446783790347e+132, 9.925505512774358e+143, 3.8295023799621285e+155, 1.4775155239459885e+167, 5.700615659424077e+178, 2.199436714524765e+190, 8.485963885676548e+201, 3.2740920706402907e+213, 1.26322466504051e+225] 从上面结果就可以看出未进行标准化的数据误差是很大的。

In [6]

对数据进行标准化

class StandardScaler: '''该类对数据进行标准化处理。'''

def fit(self, X):
    '''根据传递的样本,计算每个特征值的均值与标准差。
    
    ParameterS
    -----
    X : 类数组类型
        训练数据,用来计算均值与标准差。
    '''
    X = np.asarray(X)
    self.mean_ = np.mean(X, axis=0)
    self.std_ = np.std(X, axis=0)
    
def transform(self, X):
    '''对给定的数据X进行标准化处理。将X的每一列都变成标准正态分布的数据
    
    Parameters
    -----
    result : 类数组类型。
            参数X转换成标准正态分布的结果。
    '''
    return (X - self.mean_) / self.std_

def fit_transform(self, X):
    '''对数据进行训练,并转换,返回转换之后的结果。
    
    Parameters
    -----
    X : 类数组类型。
        带转换的数据。
        
    Returns
    ----
    result : 类数组类型。
            参数X转换成标准正态分布后的结果。
    '''
    self.fit(X)
    return self.transform(X)

In [7]

为了避免每个特征数量级的不同,从而在梯度下降的过程中带来影响

我们现在考虑对每个特征值进行标准化处理

lr = LinearRegression(alpha=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.transform(test_X)

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

lr.fit(train_X, train_y) result = lr.predict(test_X) display(np.mean((result - test_y) ** 2)) display(lr.w_) display(lr.loss_) 0.203353146171921 array([ 1.45661261e-16, -7.82096101e-02, 3.27417218e-02, -4.18423834e-02, 7.23915815e-02, -1.22422484e-01, 3.18709730e-01, -9.44094559e-03, -2.09320117e-01, 1.04023908e-01, -5.20477318e-02, -1.82216410e-01, 9.76133507e-02, -3.94395606e-01]) [200.0, 107.18106695239439, 88.90466866295792, 79.78035025519532, 74.3187880885867, 70.90417512718284, 68.69155318506807, 67.20013197881178, 66.15079837015878, 65.37902020765745, 64.78625525603303, 64.31246996531246, 63.9204121068791, 63.58650021098897, 63.29547926726484, 63.03724485771134, 62.80493063951664, 62.5937408804752, 62.40022787877571, 62.22183840063286] In [ ]

如果想显示中文的话可以看这一段默认情况下matplotlib不支持中文显示进行以下设置

设置字体为黑体,以支持中文显示

mpl.rcParams['font.family'] = 'SimHei'

设置在中文字体时,能够正常的显示负号(-

mpl.rcParams['axes.unicode_minus'] = False In [8] plt.figure(figsize=(10, 10))

绘制预测值

plt.plot(result, 'ro-', label='Predictive value')

绘制真实值

plt.plot(test_y.values, 'go--', label='Actual value') plt.title('Linear regression-Gradient descent') plt.xlabel('Number') plt.ylabel('House price') plt.legend() plt.show()

In [10] # 绘制累计误差值 plt.plot(range(1, lr.times + 1), lr.loss_, 'o-') plt.xlabel('times') plt.ylabel('loss') plt.show()
In [11] # 因为房价分析涉及多个维度,不方便进行可视化显示,为了实现可视化 # 我们只选取其中的一个维度RM并画出直线实现拟合 lr = LinearRegression(alpha=0.0005, times=50) t = data.sample(len(data), random_state=0) train_X = t.iloc[:400, 5:6] train_y = t.iloc[:400, -1] test_X = t.iloc[400:, 5:6] test_y = t.iloc[400:, -1]

对数据进行标准化处理

s = StandardScaler() train_X = s.fit_transform(train_X) test_X = s.transform(test_X) s2 = StandardScaler() train_y = s2.fit_transform(train_y) test_y = s2.transform(test_y)

lr.fit(train_X, train_y) result = lr.predict(test_X) display(np.mean((result - test_y) ** 2)) 0.46071758937162166 In [12] plt.scatter(train_X['rm'], train_y)

查看方程系数

display(lr.w_)

构建方程y = -2.78221890e-16 + 6.54984608e-01 * x

x = np.arange(-5, 5, 0.1) y = -2.78221890e-16 + 6.54984608e-01 * x

plt.plot(x, y, 'r')

也可以这样做

plt.plot(x, lr.predict(x.reshape(-1, 1)), 'r') plt.show() array([-3.07753822e-16, 6.54984608e-01])