使用神經網絡進行預測(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()  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章