当前位置:   article > 正文

波士顿房价预测(终版讲解)

波士顿房价预测

代码段分四个部分:库的引入、加载数据(函数)、配置网络结构(类)、运行部分(获取数据,创建网络,启动训练,作图)

我的是基础版,库只用到了numpy和matplotlib的pyplto两个。

加载数据需要进行将数据作为数组输入,重整成14*N的二维数组,分训练集和测试集并归一化

重点在配置网络结构部分。搭建神经网络:搭建神经网络就像是用积木搭宝塔。在飞桨中,网络层(layer)是积木,而神精网络是要搭建的宝塔 这里通过创建python类的方式完成模型网络的定义,即定义__init__函数和forward函数等。

最后通过调用函数完成模型的训练并作出loss的图

第一部分:库的引入

  1. #加载相关库
  2. import numpy as np
  3. import matplotlib.pyplot as plt

这一部分没什么好说的。paddle版的库引入库可能会比较复杂,这里基础班只用到这两个库。

第二部分:加载数据

  1. #数据预处理
  2. def load_data():
  3. datafile = './data/data108228/housing.data'
  4. data = np.fromfile(datafile,sep=' ') #分隔符:如果一个文件是文本文件,默认空格分隔
  5. feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
  6. feature_num = len(feature_names)
  7. data = data.reshape(data.shape[0]//feature_num,feature_num)
  8. ratio = 0.8
  9. offset=int(data.shape[0]*ratio)
  10. training_data = data[:offset]
  11. maximums, minimums, avge = training_data.max(axis=0), training_data.min(axis=0), training_data.sum(axis=0) / training_data.shape[0]
  12. #记录数据的归一化参数,在预测时对数据归一化
  13. global max_values
  14. global min_values
  15. global avg_values
  16. max_values = maximums
  17. min_values = minimums
  18. avg_values = avge
  19. #有的案例加了有的没加,不明白为什么要加,先加上了
  20. for i in range(feature_num):
  21. data[:, i] = (data[:, i]-avge[i]) / (maximums[i]-minimums[i])
  22. training_data = data[:offset]
  23. test_data = data[offset:]
  24. return training_data, test_data

load_data函数返回训练集和测试集两个数组

首先加载文件,这里的分隔符是空格,所以写sep='  '

然后将十三个预测参数和lable的名字给feature_names,用feature_num记录参数的个数,下面要用到feature_num这个变量。

之后重整数据,读入的是一维的数据,需要将它转换为二维的14*N的二维数据

接下来是分组和归一化。由于所有数据都要用训练集的范围来进行归一化操作,先找到训练集,计算出它的最值和均值(其中的axis=0是对第零维,也就是行进行操作)去对所有数据进行归一化,归一化完成后分成两组输出。

第三步:配置网络结构

  1. #数据预处理
  2. def load_data():
  3. datafile = './data/data108228/housing.data'
  4. data = np.fromfile(datafile,sep=' ') #分隔符:如果一个文件是文本文件,默认空格分隔
  5. feature_names = ['CRIM', 'ZN', 'INDUS', 'CHAS', 'NOX', 'RM', 'AGE','DIS', 'RAD', 'TAX', 'PTRATIO', 'B', 'LSTAT', 'MEDV']
  6. feature_num = len(feature_names)
  7. data = data.reshape(data.shape[0]//feature_num,feature_num)
  8. ratio = 0.8
  9. offset=int(data.shape[0]*ratio)
  10. training_data = data[:offset]
  11. maximums, minimums, avge = training_data.max(axis=0), training_data.min(axis=0), training_data.sum(axis=0) / training_data.shape[0]
  12. #记录数据的归一化参数,在预测时对数据归一化
  13. global max_values
  14. global min_values
  15. global avg_values
  16. max_values = maximums
  17. min_values = minimums
  18. avg_values = avge
  19. #有的案例加了有的没加,不明白为什么要加,先加上了
  20. for i in range(feature_num):
  21. data[:, i] = (data[:, i]-avge[i]) / (maximums[i]-minimums[i])
  22. training_data = data[:offset]
  23. test_data = data[offset:]
  24. return training_data, test_data
  25. In [8]
  26. #配置网络结构
  27. class Network(object):
  28. def __init__(self, num_of_weights):
  29. np.random.seed(0) # 随机产生w的初始值,为了保持程序每次运行结果的一致性,此处设置固定的随机数种子
  30. self.w = np.random.randn(num_of_weights, 1)
  31. self.b = 0.
  32. def forward(self, x):
  33. z = np.dot(x, self.w) + self.b
  34. return z
  35. def loss(self, z, y):
  36. error = z - y
  37. cost = error * error
  38. cost = np.mean(cost)
  39. return cost
  40. def gradient(self, x, y):
  41. z = self.forward(x)
  42. gradient_w = (z-y)*x
  43. gradient_w = np.mean(gradient_w, axis=0)
  44. gradient_w = gradient_w[:, np.newaxis]
  45. gradient_b = (z-y)
  46. gradient_b = np.mean(gradient_b)
  47. return gradient_w, gradient_b
  48. def update(self, gradient_w, gradient_b, eta=0.01):
  49. self.w = self.w - eta * gradient_w
  50. self.b = self.b - eta * gradient_b
  51. def train(self, training_data, num_epochs, batch_size=10, eta=0.01):
  52. n = len(training_data)
  53. losses=[]
  54. for epoch_id in range(num_epochs):
  55. np.random.shuffle(training_data)
  56. mini_batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)]
  57. for iter_id, mini_batch in enumerate(mini_batches):
  58. x = mini_batch[:, :-1]
  59. y = mini_batch[:, -1:]
  60. a = self.forward(x)
  61. loss = self.loss(a, y)
  62. gradient_w, gradient_b = self.gradient(x, y)
  63. self.update(gradient_w, gradient_b, eta)
  64. losses.append(loss)
  65. print('Epoch {:3d} / iter {:3d}, loss = {:4f}'.format(epoch_id, iter_id, loss))
  66. return losses

这一步是核心拆开来解析:

  1. class Network(object):
  2. def __init__(self, num_of_weights):
  3. np.random.seed(0) # 随机产生w的初始值,为了保持程序每次运行结果的一致性,此处设置固定的随机数种子
  4. self.w = np.random.randn(num_of_weights, 1)
  5. self.b = 0.

创建一个类:Network,这种数据类型中包含两部分,w数组和b,因为自变量有13个,所以它们的系数需要一个数组来存,b就初始化为0就可以

                                                             y=\sum_{i=0}^{12} w_{i}x_{i}+b

  1. def forward(self, x):
  2. z = np.dot(x, self.w) + self.b
  3. return z

forward函数 forward函数是框架指定实现向前计算逻辑的函数,返回预测结果。用当前w和x点乘,返回预测结果y(bar)

  1. def loss(self, z, y):
  2. error = z - y
  3. cost = error * error
  4. cost = np.mean(cost)
  5. return cost

计算损失函数,返回损失值,是个平均数,注意是一个数。

  1. def gradient(self, x, y):
  2. z = self.forward(x)
  3. gradient_w = (z-y)*x
  4. gradient_w = np.mean(gradient_w, axis=0)
  5. gradient_w = gradient_w[:, np.newaxis]
  6. gradient_b = (z-y)
  7. gradient_b = np.mean(gradient_b)
  8. return gradient_w, gradient_b

计算梯度函数,先算出用当前w预测的结果,然后用结果算出梯度并求均值。公式就是求偏导。gradient_w需要按行平均,平均后是[w0,w1,,,,,,w12],shape=(13,),但w是(13,1)所以需要给gradient_w添加新的一维(虚的)。

返回两个梯度,w的是数组,b的是一个数

  1. def update(self, gradient_w, gradient_b, eta=0.01):
  2. self.w = self.w - eta * gradient_w
  3. self.b = self.b - eta * gradient_b

更新函数。完成更新操作,原系数 - 学习率和梯度的乘积

  1. def train(self, training_data, num_epochs, batch_size=10, eta=0.01):
  2. n = len(training_data)
  3. losses=[]
  4. for epoch_id in range(num_epochs):
  5. np.random.shuffle(training_data)
  6. mini_batches = [training_data[k:k+batch_size] for k in range(0, n, batch_size)]
  7. for iter_id, mini_batch in enumerate(mini_batches): #在字典上是枚举的意思
  8. x = mini_batch[:, :-1]
  9. y = mini_batch[:, -1:]
  10. a = self.forward(x)
  11. loss = self.loss(a, y)
  12. gradient_w, gradient_b = self.gradient(x, y)
  13. self.update(gradient_w, gradient_b, eta)
  14. losses.append(loss)
  15. print('Epoch {:3d} / iter {:3d}, loss = {:4f}'.format(epoch_id, iter_id, loss))
  16. return losses

两层循环:

        第一层进行num_epochs(迭代周期)次。每次先打乱数据,将数据分组(,每组长度为batch_size,之后嵌套下一层循环

        第二层遍历mini_batchs。先将它分成参数和label,计算预测值,损失函数和梯度。更新w

输出当前的轮次,索引和损失函数。并记录每一个loss到losses里,方便作图。

enumerate用处:遍历索引和元素。

  1. list1 = ["this", "is", "a", "test"]
  2. for index, item in enumerate(list1):
  3. print index, item
  4. >>>
  5. 0 this
  6. 1 is
  7. 2 a
  8. 3 test

第四步:启动训练

  1. training_data, test_data = load_data()
  2. net = Network(13)
  3. losses = net.train(training_data, num_epochs=50, batch_size=100, eta=0.1)
  4. plot_x = np.arange(len(losses)) #返回有起点和终点的固定步长的排列
  5. plot_y = np.array(losses)
  6. plt.plot(plot_x, plot_y)
  7. plt.show()

很简单,直接看结果:

Epoch   0 / iter   0, loss = 2.467436
Epoch   0 / iter   1, loss = 1.541610
Epoch   0 / iter   2, loss = 1.569710
Epoch   0 / iter   3, loss = 1.853896
Epoch   0 / iter   4, loss = 0.503186
Epoch   1 / iter   0, loss = 1.919441
                   .
                   .
                   .
Epoch  49 / iter   0, loss = 0.093340
Epoch  49 / iter   1, loss = 0.066011
Epoch  49 / iter   2, loss = 0.083206
Epoch  49 / iter   3, loss = 0.096158
Epoch  49 / iter   4, loss = 0.071400

 这样房价预测模型就训练完了

保存模型用到  np.save('w.npy', net.w)

                        np.save('b.npy', net.b)

模型的测试在下一个版本记录

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/不正经/article/detail/585344
推荐阅读
相关标签
  

闽ICP备14008679号