import numpy as npimport pandas as pd
波士顿房价数据集字段说明
CRIM:房屋所在镇的犯罪率ZN:面积大于25000平方英尺住宅所占的比例INDUS :房屋所在镇非零售区域所占比例CHAS:房屋是否位于河边 若位于河边,值为1,否则为0NOX:一氧化氮的浓度RM:平均房间的数量AGE:1940年前建成房屋所占比例DIS:房屋距离波斯顿五大就业中心的加权距离RAD:距离房屋最近的公路TAX:财产税额度PIRATIO:房屋所在镇师生比例B:计算公式(房屋所在镇非美籍人口所占比例):1000*(房屋所在镇非美籍人口所占比例-0.63)**2LSTAT:弱势群体人口所占比例MEDV:房间的平均价格data=pd.read_csv(r"F:\数据集\dataset\boston.csv")#data#查看数据的基本信息,同时也可以用来查看,各个特征列是否存在缺失值data.info()#查看是否有重复值data.duplicated().any()
<class 'pandas.core.frame.DataFrame'>RangeIndex: 506 entries, 0 to 505Data columns (total 15 columns):# ColumnNon-Null Count Dtype --- -------------------- ----- 0 Unnamed: 0 506 non-null int64 1 crim 506 non-null float642 zn506 non-null float643 indus 506 non-null float644 chas 506 non-null int64 5 nox 506 non-null float646 rm506 non-null float647 age 506 non-null float648 dis 506 non-null float649 rad 506 non-null int64 10 tax 506 non-null int64 11 ptratio506 non-null float6412 black 506 non-null float6413 lstat 506 non-null float6414 medv 506 non-null float64dtypes: float64(11), int64(4)memory usage: 59.4 KBFalse
定义线性回归类
利用正规方程解出向量θ\thetaθ:θ=(XTX)−1XTY\theta=(X^{T}X)^{-1}X^{T}Yθ=(XTX)−1XTY
class linearRegression:"""使用python实现的线性回归。(最小二乘法)"""def fit(self,X,y):"""根据提供的训练数据X ,对模型进行训练。Parameters:_________X:类数组类型。形状:[样本数量,特征数量]特征矩阵,用来对模型进行训练。y: 类数组类型,形状:[样本数量]"""# 将X转换成矩阵格式,注意:这里的X必须是一个完整的数组格式,不能是数组的一部分。所以这里用到X.copy()#说明:如果X是数组对象的一部分,而不是完整的对象数据(例如,X是其他对象通过切片传递过来),这是则无法完成矩阵的转换 #这里创建X的拷贝对象,避免转换矩阵的时候失败X=np.asmatrix(X.copy())# y 是一维结构(行向量或列向量),对于一维结构可以不用进行拷贝#注意:我们现在需要进行矩阵的计算,因此需要二维的结构,我们通过reshape方法进行转换#reshape(-1,1)表示根据实际情况转换成多少行(-1),一列。y=np.asmatrix(y).reshape(-1,1)#通过最小二乘公式求戒除最佳的权重值self.w_=(X.T*X).I*X.T*ydef predict(self,X):"""根据参数传递的样本X,对样本数据进行预测。Parameters:___________X:类数组类型。形状:[样本数量,特征数量]待预测的样本特征(属性)Returns:________result:数组类型预测的结果"""#将X转换成矩阵,注意,需要对X进行拷贝(理由同上)X=np.asmatrix(X.copy())result=X*self.w_#result是一个矩阵,且是二维的,所以将result转化为ndarray数组,进行扁平化(result.ravel())处理,然后返回结果#使用ravel()可以将数组进行扁平化处理return np.array(result).ravel()
不考虑截距的情况
#不考虑截距的情况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=linearRegression()lr.fit(train_X,train_y)result=lr.predict(test_X)display(np.mean((result-test_y)**2))#查看模型的权重值display(lr.w_)
16.892575069960635matrix([[-2.25548227e-03],[-9.36187378e-02],[ 4.57218914e-02],[ 3.67703558e-03],[ 2.43746753e+00],[-2.96521997e+00],[ 5.61875896e+00],[-4.94763610e-03],[-8.73950002e-01],[ 2.49282064e-01],[-1.14626177e-02],[-2.50045098e-01],[ 1.49996195e-02],[-4.56440342e-01]])
考虑截距的情况
#考虑截距:增加一列,使该列的所有值都是1t=data.sample(len(data),random_state=0)#可以这样增加一列#t["intercept"]=1,这是在最右边增加intercept列,且该列所有值都取1#按照习惯,截距作为w0,我们为之而配上一个x0,x0列放在最前面#t.columns 返回所有列的信息;insert(0,"Intercept"):将Intercept增加到第一列new_columns=t.columns.insert(0,"Intercept")#重新安排列的信息,如果值为空,则使用fail_value参数指定的值进行填充t=t.reindex(columns=new_columns,fill_value=1)#tt=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=linearRegression()lr.fit(train_X,train_y)result=lr.predict(test_X)#不知为何lr.w_的值为“nan”display(np.mean((result-test_y)**2))#display(lr.w_)
16.892575069960635
可视化
import matplotlib as mplimport matplotlib.pyplot as plt#设置字体为黑体,以支持中文显示mpl.rcParams["font.family"]="SimHei"#设置在中文字体是,能正常显示负号(-)mpl.rcParams["axes.unicode_minus"]=False
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()