Copyright © Microsoft Corporation. All rights reserved. 适用于License版权许可
数据集来自:https://www.kaggle.com/harlfoxem/housesalesprediction
此数据集是King County地区2014年五月至2015年五月的房屋销售信息,适合于训练回归模型。
一些考虑:
所以最后只留下13个字段。
原始数据只有一个数据集,所以需要我们自己把它分成训练集和测试集,比例大概为4:1。此数据集为csv文件格式,为了方便,我们把它转换成了两个扩展名为npz的numpy压缩形式:
train_file = "../../Data/house_Train.npz"
test_file = "../../Data/house_Test.npz"
def LoadData():
dr = HouseDataReader(train_file, test_file)
dr.ReadData()
dr.NormalizeX()
dr.NormalizeY(YNormalizationMethod.Regression)
dr.Shuffle()
dr.GenerateValidationSet(k=10)
return dr
与上面第一个例子的代码相似,但是房屋数据属性繁杂,所以需要做归一化,房屋价格也是至少6位数,所以也需要做归一化。上面代码中的NormalizeX()做属性归一化,NormalizeY(YNormalizationMethod.Regression)做标签数据的归一化。
这里有个需要注意的地方,即训练集和测试集的数据,需要合并在一起做归一化,然后再分开使用。为什么要先合并呢?假设训练集样本中的房屋面积的范围为150到220,而测试集中的房屋面积有可能是160到230,两者不一致。分别归一化的话,150变成0,160也变成0,这样预测就会产生误差。
最后还需要在训练集中用GenerateValidaionSet(k=10)分出一个1:9的验证集。
在不知道一个问题的实际复杂度之前,我们不妨把模型设计得复杂一些。如下图所示,这个模型包含了四组全连接层-Relu层-Dropout层的组合,最后是一个单输出做拟合。
def model():
dr = LoadData()
num_input = dr.num_feature
num_hidden1 = 32
num_hidden2 = 16
num_hidden3 = 8
num_hidden4 = 4
num_output = 1
max_epoch = 10000
batch_size = 16
learning_rate = 0.01
eps = 1e-6
params = CParameters(
learning_rate, max_epoch, batch_size, eps,
LossFunctionName.MSE,
InitialMethod.Xavier,
OptimizerName.Momentum)
net = NeuralNet(params, "HouseSingle")
fc1 = FcLayer(num_input, num_hidden1, params)
net.add_layer(fc1, "fc1")
r1 = ActivatorLayer(Relu())
net.add_layer(r1, "r1")
fc2 = FcLayer(num_hidden1, num_hidden2, params)
net.add_layer(fc2, "fc2")
r2 = ActivatorLayer(Relu())
net.add_layer(r2, "r2")
fc3 = FcLayer(num_hidden2, num_hidden3, params)
net.add_layer(fc3, "fc3")
r3 = ActivatorLayer(Relu())
net.add_layer(r3, "r3")
fc4 = FcLayer(num_hidden3, num_hidden4, params)
net.add_layer(fc4, "fc4")
r4 = ActivatorLayer(Relu())
net.add_layer(r4, "r4")
fc5 = FcLayer(num_hidden4, num_output, params)
net.add_layer(fc5, "fc5")
net.load_parameters()
net.train(dr, checkpoint=10, need_test=True)
先构造一个参数集合CParameters,包括:
net.train()函数是一个阻塞函数,只有当训练完毕后才返回。
output = net.inference(dr.XTest)
real_output = dr.DeNormalizeY(output)
mse = np.sum((dr.YTestRaw - real_output)**2)/dr.YTest.shape[0]/10000
print("mse=", mse)
net.ShowLossHistory()
ShowResult(net, dr)
在train后面的部分,是用测试集来测试该模型的准确度,使用了数据城堡(Data Castle)的官方评测方法,用均方差除以10000,得到的数字越小越好。一般的模型大概是一个7位数的结果,稍微好一些的是6位数。
由于标签数据也做了归一化,变换为都是0至1间的小数,所以均方差的数值很小,需要观察小数点以后的第4位。从上图中可以看到,损失函数值很快就降到了0.0005以下,然后就很缓慢地下降。而精度值在不断的上升,相信更多的迭代次数会带来更高的精度。
再看下面的打印输出部分,用R2_Score法得到的值为0.867,而用数据城堡官方的评测标准,得到的MSE值为1711852,还比较大,说明模型精度还应该有上升的空间。
epoch=9999, total_iteration=9729999
loss_train=0.000029, accuracy_train=0.810638
loss_valid=0.000192, accuracy_valid=0.837924
time used: 2718.652097225189
save parameters
testing...
0.8677652253507482
mse= 1711852.5022083137
ch14, Level2