使用神经网络进行预测(python)

前沿:

先学习本篇文章之前,建议大家先学习我编写的上一篇“使用Python从头实现一个神经网络”,再来学习学习本篇使用神经网络进行房价预测。


介绍:

本次使用神经网络进行房价的预测,利用数据样本学习,得到相关因素预测房价。

数据介绍:

数据来源:

使用爬虫工具爬取广州某小区的售房信息。爬取到的数据如下:

选取变量

共有380条数据,七项指标,选取其中五项指标,分别为总价,面积、房间数量、客厅数量、建造年份。

选取房子总价为预测变量,面积、房间数量、客厅数量、建造年份为输入变量。

数据处理

对数据进行标准化,标准化方程如下:

x'=\frac{x-x_{mean}}{x_{max}}

其中,x'为标准化后的数值,x为原数值,x_{mean}为该变量的平均值,x_{max}为变量的最大值。

例如:x代表总价变量,x_{mean}为所有总价的平均值,也就是Excel中第一列的平均值,x_{max}为最高的总价。

神经网络结构:

本次的选用的神经网络结构如下:

我们的神经网络结构较为简单,隐藏层为一层,隐藏层节点数为2,两个偏置单元。

函数说明:

输入层到隐藏层(sigmoid):

y=\frac{1}{1+e^{-\theta x}}

隐藏层到输出层(回归函数):

y=w_{1}h_{1}+w_{2}h_{2}+b_{3}

代价函数:

cost=\frac{1}{m}\sum _{_{}}(y-y')^{2}

之所以隐藏层到输出层的函数改为回归函数,是因为我们不再使用神经网络进行分类,而是预测。

分类问题得到的输出结果是[0,1]之间,因此使用sigmoid函数;而我们预测的结果是一个大范围的值。

比如我们预测到的房价可能是100万,也可能是500万,因此使用多元回归函数。

这么做的意义,在于我们将原先的四个变量,重新转化为了隐藏层中的两个节点。再利用两个节点,进行多元线性回归。不再使用原先的四个变量直接多元回归,这也是隐藏层的意义。

ps:有人可能看过吴恩达的机器学习视频(强烈推荐),代价函数使用的是另一种形式。那是因为神经网络用于分类时,输出节点在[0,1]之间,使用那种形式可以学习的更好。

反向传播和梯度下降:

由于上一篇已经将反向传播和梯度下降讲的很清楚了,因此不再重复。我们使用学习率为α=0.01时,将380条数据迭代1000次,每10次输出一次代价函数值,得到损失值和迭代次数如下图:

可以看到,损失值在下降,说明学习率选取较好(几次中比较好的一次)。

预测房价和实际房价对比

以380个数据样本为横座标,房子总价为纵座标。下图中红色散点为数据样本中真实房价,蓝色散点为预测房价,得到如下所示的散点图。

可以看到,预测房价和实际房价大致呈现吻合关系,说明模型大致正确。

最后:

由于本人为神经网络的初学者, 可能存在解释不清楚甚至错误的地方,希望大家多多指教。

如果大家想深入机器学习,可以观看吴恩达的机器学习视频,或者周志华的机器学习西瓜书(个人推荐)

我将我的数据和代码放在了我的github上,大家如果需要数据和代码,可以前往下载。

数据和代码下载

 

附件:代码

  1. import numpy as np  
  2. import pandas as pd  
  3. from matplotlib import pyplot as plt  
  4.   
  5.   
  6. def sigmoid(x):  
  7.     第一层到第二层的激活函数  
  8.     return 1 / (1 + np.exp(-x))  
  9.   
  10.   
  11. def deriv_sigmoid(x):  
  12.     第一层到第二层的激活函数的求导函数  
  13.     fx = sigmoid(x)  
  14.     return fx * (1 - fx)  
  15.   
  16.   
  17. def mse_loss(y_true, y_pred):  
  18.     使用方差作为损失函数  
  19.     return ((y_true - y_pred) ** 2).mean()  
  20.   
  21.   
  22. class OurNeuralNetwork:  
  23.   
  24.     def __init__(self):  
  25.         第一层到第二层的函数  
  26.         self.w11 = np.random.normal()  
  27.         self.w12 = np.random.normal()  
  28.         self.w13 = np.random.normal()  
  29.         self.w14 = np.random.normal()  
  30.         self.w21 = np.random.normal()  
  31.         self.w22 = np.random.normal()  
  32.         self.w23 = np.random.normal()  
  33.         self.w24 = np.random.normal()  
  34.         第二层到第三层的函数  
  35.         self.w1 = np.random.normal()  
  36.         self.w2 = np.random.normal()  
  37.         截距项,Biases  
  38.         self.b1 = np.random.normal()  
  39.         self.b2 = np.random.normal()  
  40.         self.b3 = np.random.normal()  
  41.   
  42.     def feedforward(self, x):  
  43.         前向传播学习  
  44.         h1 = sigmoid(self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1)  
  45.         h2 = sigmoid(self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b1)  
  46.         o1 = self.w1 * h1 + self.w2 * h2 + self.b3  
  47.         return o1  
  48.     #训练函数  
  49.     def train(self, data, all_y_trues):  
  50.         learn_rate = 0.01  学习率  
  51.         epochs = 1000  训练的次数  
  52.         画图数据  
  53.         self.loss = np.zeros(100)  
  54.         self.sum = 0;  
  55.         开始训练  
  56.         for epoch in range(epochs):  
  57.             for x, y_true in zip(data, all_y_trues):  
  58.                 计算h1  
  59.                 h1 = sigmoid(self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1)  
  60.                 计算h2  
  61.                 h2 = sigmoid(self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b2)  
  62.                 #计算输出节点  
  63.                 y_pred = self.w1 * h1 + self.w2 * h2 + self.b3  
  64.                 反向传播计算导数  
  65.                 d_L_d_ypred = -2 * (y_true - y_pred)  
  66.                 d_ypred_d_w1 = h1  
  67.                 d_ypred_d_w2 = h2  
  68.                 d_ypred_d_b3 = 0  
  69.                 d_ypred_d_h1 = self.w1  
  70.                 d_ypred_d_h2 = self.w2  
  71.                 sum_1=self.w11 * x[0] + self.w12 * x[1] + self.w13 * x[2] + self.w14 * x[3] + self.b1  
  72.                 d_h1_d_w11 = x[0] * deriv_sigmoid(sum_1)  
  73.                 d_h1_d_w12 = x[1] * deriv_sigmoid(sum_1)  
  74.                 d_h1_d_w13 = x[2] * deriv_sigmoid(sum_1)  
  75.                 d_h1_d_w14 = x[3] * deriv_sigmoid(sum_1)  
  76.                 d_h1_d_b1 = deriv_sigmoid(sum_1)  
  77.                 sum_2 = self.w21 * x[0] + self.w22 * x[1] + self.w23 * x[2] + self.w24 * x[3] + self.b2  
  78.                 d_h1_d_w21 = x[0] * deriv_sigmoid(sum_2)  
  79.                 d_h1_d_w22 = x[1] * deriv_sigmoid(sum_2)  
  80.                 d_h1_d_w23 = x[2] * deriv_sigmoid(sum_2)  
  81.                 d_h1_d_w24 = x[3] * deriv_sigmoid(sum_2)  
  82.                 d_h1_d_b2 = deriv_sigmoid(sum_2)  
  83.   
  84.                 梯度下降法  
  85.                 self.w11 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w11  
  86.                 self.w12 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w12  
  87.                 self.w13 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w13  
  88.                 self.w14 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_w14  
  89.                 self.b1 -= learn_rate * d_L_d_ypred * d_ypred_d_h1 * d_h1_d_b1  
  90.                 self.w21 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w21  
  91.                 self.w22 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w22  
  92.                 self.w23 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w23  
  93.                 self.w24 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_w24  
  94.                 self.b2 -= learn_rate * d_L_d_ypred * d_ypred_d_h2 * d_h1_d_b2  
  95.                 self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_w1  
  96.                 self.w1 -= learn_rate * d_L_d_ypred * d_ypred_d_w2  
  97.                 self.b3 -= learn_rate * d_L_d_ypred * d_ypred_d_b3  
  98.   
  99.             if epoch % 10 == 0:  
  100.                 y_preds = np.apply_along_axis(self.feedforward, 1, data)  
  101.                 loss = mse_loss(all_y_trues, y_preds)  
  102.                 print("Epoch %d loss: %.3f" % (epoch, loss))  
  103.                 self.loss[self.sum] = loss  
  104.                 self.sum = self.sum + 1  
  105.   
  106. 文件的名字  
  107. FILENAME = "../data.xlsx"  
  108. 禁用科学计数法  
  109. pd.set_option('float_format', lambda x: '%.3f' % x)  
  110. np.set_printoptions(suppress=True, threshold=np.nan)  
  111. 得到的DataFrame分别为总价、面积、房间、客厅、年份  
  112. data = pd.read_excel(FILENAME, header=0, usecols="A,D,H,I,J")  
  113. # DataFrame转化为array  
  114. DataArray = data.values  
  115. Y = DataArray[:, 0]  
  116. X = DataArray[:, 1:5]  
  117. X = np.array(X)#转化为array,自变量  
  118. Y = np.array(Y)#转化为array,因变量房价  
  119. 处理数据  
  120. data = np.array(X)  
  121. data_mean = np.sum(data, axis=0) / np.size(data, 0)  
  122. data = (data - data_mean) / np.max(data)  
  123. all_y_trues = np.array(Y)  
  124. all_y_trues_mean = np.sum(all_y_trues) / np.size(all_y_trues)  
  125. all_y_trues = (all_y_trues - all_y_trues_mean) / np.max(all_y_trues)  
  126. 训练数据  
  127. network = OurNeuralNetwork()  
  128. network.train(data, all_y_trues)  
  129. 输出神经网络参数  
  130. print("w11-->%.3f" % network.w11)  
  131. print("w12-->%.3f" % network.w12)  
  132. print("w13-->%.3f" % network.w13)  
  133. print("w14-->%.3f" % network.w14)  
  134. print("w21-->%.3f" % network.w21)  
  135. print("w22-->%.3f" % network.w22)  
  136. print("w23-->%.3f" % network.w23)  
  137. print("w24-->%.3f" % network.w24)  
  138. print("w1-->%.3f" % network.w1)  
  139. print("w2-->%.3f" % network.w2)  
  140. print("b1-->%.3f" % network.b1)  
  141. print("b2-->%.3f" % network.b2)  
  142. print("b3-->%.3f" % network.b3)  
  143. 标题显示中文  
  144. plt.rcParams['font.sans-serif']=['SimHei']  
  145. plt.rcParams['axes.unicode_minus'] = False  
  146. 测试数据  
  147. testData = np.array([99, 3, 2, 2014])  
  148. testPrice = network.feedforward(testData)  
  149. 损失函数曲线图  
  150. plt.plot(np.arange(100), network.loss)  
  151. plt.show()  
  152. 真实值与预测值对比  
  153. y_preds = np.apply_along_axis(network.feedforward, 1, data)  
  154. plt.plot(np.arange(380), all_y_trues,"r^")  
  155. plt.plot(np.arange(380),y_preds,"bs")  
  156. plt.title("红色为真实值,蓝色为预测值")  
  157. plt.show()  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章