房价预测
一、读入数据
mport pandas as pd
import torch
import d2l.torch as d2l
from torch import nn
import numpy as np
data_train,data_test=pd.read_csv('C:\\Users\\n\\Desktop\\py.learn.py\\test.csv'),pd.read_csv('C:\\Users\\n\\Desktop\\py.learn.py\\train.csv')
二、预处理
1.将train,test的共同部分集合起来一起处理
all_features=pd.concat((data_train.iloc[:,1:-1],data_test.iloc[:,1:]))#将所有faeture集中起来
处理所有数据
numeric_feature=all_features.dtypes[all_features.dtypes!='object'].index#取出所有数字型的列
all_features[numeric_feature]=all_features[numeric_feature].apply(
lambda x:(x-x.mean())/(x.std())
)#将所有数字型的标准化
all_features[numeric_feature]=all_features[numeric_feature].fillna(0)#缺失值置0
all_features=pd.get_dummies(all_features,dummy_na=True)#离散部分处理
n_train=data_train.shape[0]#训练集的样本数
train_feature=torch.tensor(all_features[:n_train].values,
dtype=torch.float32)#转换成tensor
test_feature=torch.tensor(all_features[n_train:].values,
dtype=torch.float32)
train_label=torch.tensor(data_train.iloc[:,-1].values.reshape(-1,1),
dtype=torch.float32)
三、后续操作(懒得起名字)
2.设置一个简单模型
loss=nn.MSELoss()
num_inputs=train_feature.shape[1]#维度
net=nn.Sequential(nn.Linear(num_inputs,1))#一个简单的模型
3.损失界定
我们关心的是相对数量,而不是绝对数量。因此,我们更关心相对误差 y−y^y ,而不是绝对误差 y−y^ 。例如,如果我们在俄亥俄州农村地区估计一栋房子的价格时,我们的预测偏差了10万美元,在那里一栋典型的房子的价值是12.5万美元,那么我们可能做得很糟糕。另一方面,如果我们在加州豪宅区的预测出现了这个数字的偏差,这可能是一个惊人的准确预测(在那里,房价均值超过400万美元)。
解决这个问题的一种方法是用价格预测的对数来衡量差异。事实上,这也是比赛中官方用来评价提交质量的误差指标。即将 δ for |logy−logy^|≤δ 转换为 e−δ≤y^y≤eδ 。这使得预测价格的对数与真实标签价格的对数之间出现以下均方根误差:
def log_rmse(net,feature,lables):#这里的结果得看相对误差
clinpped_preds=torch.clamp(net(feature),1,float('inf'))#将所有的训练集的预测值限制在1到无穷,小于1的都变成1
rmse=torch.sqrt(loss(torch.log(clinpped_preds),torch.log(lables)))#
return rmse.item()#返回损失值,更高的精度
4、训练模型
#训练模型
def train(net,train_feature,train_label,test_feature,test_label,
num_epochs,lr,wd,batch_size):
train_ls,test_ls=[],[]#每一个epoch的损失都要记录
train_iter=d2l.load_array((train_feature,train_label.reshape(-1,1)),batch_size)#给出训练迭代器
optimizer=torch.optim.Adam(net.parameters(),lr=lr,
weight_decay=wd)#优化器设置
for epoch in range(num_epochs):
for X,y in train_iter:
optimizer.zero_grad()#梯度置零
l=loss(net(X),y)#损失,这里不使用log_rmse是由于太小
l.backward()
optimizer.step()
train_ls.append(log_rmse(net,train_feature,train_label))
if test_label is not None:
test_ls.append(log_rmse(net,test_feature,test_label))
return train_ls,test_ls
5、k折交叉
def get_k_fold_data(k,i,X,y):
assert k>1
fold_size=X.shape[0]//k
X_train,y_train=None,None
for j in range(k):
idx=slice(j*fold_size,(j+1)*fold_size)#提供索引
X_part,y_part=X[idx,:],y[idx]
if j==i:
X_valid,y_valid=X_part,y_part#制定哪一个作为测试集
elif X_train is None:
X_train,y_train=X_part,y_part#第一个自成
else:
X_train=torch.cat([X_train,X_part],0)
y_train=torch.cat([y_train,y_part],0)#0指按行拼接
return X_train,y_train,X_valid,y_valid
def k_fold(k,X_train,y_train,num_epochs,lr,wd,batch_size):
train_l_sum,valid_l_sum=0,0#累积损失
for i in range(k):
data=get_k_fold_data(k,i,X_train,y_train)
train_ls,valid_ls=train(net,*data,num_epochs,lr,wd,batch_size)
train_l_sum+=train_ls[-1]#将每一次k折的训练最终损失加和
valid_l_sum+=valid_ls[-1]
if i==0:
d2l.plot(list(range(1,num_epochs+1)),[train_ls,valid_ls],
xlabel='epoch',ylabel='rmse',xlim=[1,num_epochs],
legend=['train','valid'],yscale='log')
print(f'fold{i+1},train log rmse{float(train_ls[-1]):f},'
f'valid log rmse{float(valid_ls[-1]):f}')
return train_l_sum/k,valid_l_sum/k#k折检测的平均损失
6、给定参数
k,num_epochs,lr,wd,batch_size=5,100,5,0,64
train_l,valid_l=k_fold(k,train_feature,train_label,num_epochs,lr,wd,batch_size)
print(f'{k}-折验证:平均logrmse :{float(train_l):f},'
f'平均log msre:{float(valid_l):f}')
7、给出训练的最终损失和预测值
def train_and_pred(train_feature,test_feature,train_label,test_data,
num_epochs,lr,wd,batch_size):
train_ls,_=train(net,train_feature,train_label,None,None,
num_epochs,lr,wd,batch_size)#之查看训练损失
d2l.plot(np.arange(1,num_epochs+1),[train_ls],xlabel='epoch',
ylabel='log rmse',xlim=[1,num_epochs],yscale='log')
print(f'train log rmse{float(train_ls[-1]):f}')
preds=net(test_feature).detach().numpy()#测试集的预测值
test_data['SalePrice']=pd.Series(preds.reshape(1,-1)[0])
submission=pd.concat([test_data['Id'],test_data['SalePrice']],1)#按列拼接
submission.to_csv('submission.csv',index=False)#存放到一个csv文件
train_and_pred(train_feature,test_feature,train_label,data_test,
num_epochs,lr,wd,batch_size)
总结
这个是一个简单预测问题,但是里面还是有几个小问题没搞明白,一个是为什么训练模型的时候使用的损失函数还是nn,MSEloss(),而不是log_mrse,一个是为什么学习率高得离谱啊。