hhh_ml

导航

梯度下降法求解线性回归问题--波士顿房价问题【python】

import numpy as np
import pandas as pd
import matplotlib as mpl
import matplotlib.pyplot as plt
 
 
#数据导入
data = pd.read_csv(r'D:\Anaconda\ana\envs\python32\Lib\site-packages\sklearn\datasets\data\boston_house_prices.csv')
# print(data.head()) #数据集的简单显示
 
class LinerRegression:
    # alpha: 学习率
    # times: 迭代次数
    def __init__(self,alpha,times): # 初始化方法
        self.alpha = alpha
        self.times = times
 
    def fit(self,X,y):  # 训练方法
        X = np.array(X)
        y = np.array(y)
 
        #初始化权重向量(初始值为0或任意其他值)
        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[0]即偏置值需要单独处理
            self.w_[0] += self.alpha * np.sum(error)
            self.w_[1:] += self.alpha * np.dot(X.T , error)
 
    def predict(self,X):
        X = np.array(X)
        result = np.dot(X,self.w_[1:]) + self.w_[0]
        return result
 
#标准化数据,如果数据范围相差太大则会导致梯度下降异常,甚至梯度上升
class StandarScaler:
    def fit(self,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的列数据已经为按照一般正态分布分布好的数据
        因此只需要根据 X~N(μ,θ)转化为标准正态分布的方法进行转换即可
        即:X = (x - μ) / θ
        """
        return (X - self.mean_)/self.std_
 
    # 合并fit和transform函数简化主函数
    def fit_transform(self,X):
        self.fit(X)
        return self.transform(X)
 
 
 
lr = LinerRegression(alpha = 0.0007,times = 50)
ssx = StandarScaler()
tData = data.sample(len(data),random_state = 0)
train_X = ssx.fit_transform(tData.iloc[:400,:-1])
test_X = ssx.transform(tData.iloc[400:,:-1])
 
ssy = StandarScaler()
# train_y = ssy.fit_transform(tData.iloc[:400,-1])
# test_y = ssy.transform(tData.iloc[400:,-1])
train_y = tData.iloc[:400,-1]
test_y = tData.iloc[400:,-1]
lr.fit(train_X,train_y)
result = lr.predict(test_X)
np.savetxt(r"C:\Users\Y_ch\Desktop\result.txt",result,fmt = "%.2lf")
np.savetxt(r"C:\Users\Y_ch\Desktop\testy.txt",test_y,fmt = "%.2lf")
 
 
# 可视化
mpl.rcParams["font.family"] = "sans-serif"
mpl.rcParams["axes.unicode_minus"] = False
plt.figure(figsize = (10,10))
plt.plot(result,"ro-",label = "predict")
# 注意是test_y的value而不是test_y test_y是panda的数据类型
# 而test_y.values是numpy的数组类型,二者不是同一类型,最后显示在画布上的应为数组类型而不是数据
plt.plot(test_y.values,"go--",label = "real")
plt.xlabel("Sample")
plt.ylabel("Price")
plt.title("Gradient Descent To Solve Liner Reression")
plt.legend()
plt.savefig(r"C:\Users\Y_ch\Desktop\HousePrice\GradientDescent.png")
plt.show()
 
 
 
 
 
 
 
 
 
 

 

posted on 2021-02-04 17:18  hhh_ml  阅读(386)  评论(0编辑  收藏  举报