TensorFlow 房價預測
以下資料來源於極客時間學習資料
• 房價預測模型介紹
前置知識:監督學習(Supervised Learning)
監督學習是機器學習的一種方法,指從訓練數據(輸入和預期輸出)中學到一個模型(函數),
並根據模型可以推斷新實例的方法。
函數的輸出通常為一個連續值(回歸分析)或類別標簽(分類)。

前置知識:監督學習典型算法
• 線性回歸(Linear Regression)
• 邏輯回歸(Logistic Regression)
• 決策樹(Decision Tree)
• 隨機森林(Random Forest)
• 最近鄰算法(k-NN)
• 朴素貝葉斯(Naive Bayes)
• 支持向量機(SVM)
• 感知器(Perceptron)
• 深度神經網絡(DNN)

前置知識:線性回歸
在統計學中,線性回歸是利用稱為線性回歸方程的最小二乘函數對一個或多個自變量和因變
量之間關系進行建模的一種回歸分析。這種函數是一個或多個稱為回歸系數的模型參數的線性組合。
前置知識:單變量線性回歸
理想函數:

假設函數

損失值(誤差)
單變量線性回歸
梯度下降
多變量線性回歸
理想函數
假設函數

損失值(誤差)

梯度下降

單變量房價預測問題

多變量房價預測問題:數據分析
多變量房價預測問題:特征歸一化
房屋面積和卧室數量這兩個變量(特征)在數值上差了1000倍。在這種情況下,通常先進
行特征縮放(Scaling),再開始訓練,可以加速模型收斂。
多變量房價預測問題
• 使用 TensorFlow 實現房價預測模型
TensorFlow 訓練模型的工作流
數據分析庫:Pandas
Pandas 是一個
BSD 開源協議許可的,面向 Python 用戶的高性能和易於上手的數
據結構化和數據分析工具。
數據框(Data Frame)是一個二維帶標記的數據結構,每列(column)數據類型
可以不同。我們可以將其當作電子表格或數據庫表。
數據讀入
pandas.read_csv 方法實現了快速讀取 CSV(comma-separated) 文件到數據框的功能。
數據可視化庫:matplotlib & seaborn & mplot3d
matplotlib 是一個 Python 2D 繪圖庫,可以生成出版物質量級別的圖像和各種硬拷貝格式,
並廣泛支持多種平台,如:Python 腳本,Python,IPython Shell 和 Jupyter Notebook。
seaborn 是一個基於 matplotlib的 Python 數據可視化庫。它提供了更易用的高級接口,用
於繪制精美且信息豐富的統計圖形。
mpl_toolkits.mplot3d 是一個基礎 3D繪圖(散點圖、平面圖、折線圖等)工具集,也是
matplotlib 庫的一部分。同時,它也支持輕量級的獨立安裝模式。
數據分析(2D)
seaborn.lmplot 方法專門用於線性關系的可視化,適用於回歸模型。

數據分析(3D)
Axes3D.scatter3D 方法專門用於繪制3維的散點圖。

數據歸一化(3D)
數據處理:NumPy
NumPy 是一個
BSD 開源協議許可的,面向 Python 用戶的基礎科學計算庫,在多
維數組上實現了線性代數、傅立葉變換和其他豐富的函數運算。
測試代碼:
單變量房價預測 import pandas as pd import seaborn as sns sns.set(context="notebook", style="whitegrid", palette="dark") df0 = pd.read_csv('data0.csv', names=['square', 'price']) sns.lmplot('square', 'price', df0, height=6, fit_reg=True)
df0.info() df0 ''' <class 'pandas.core.frame.DataFrame'> RangeIndex: 47 entries, 0 to 46 Data columns (total 2 columns): square 47 non-null int64 price 47 non-null int64 dtypes: int64(2) memory usage: 832.0 bytes '''
多變量房價預測 import matplotlib.pyplot as plt from mpl_toolkits import mplot3d df1 = pd.read_csv('data1.csv', names=['square', 'bedrooms', 'price']) df1.head()
fig = plt.figure() # 創建一個 Axes3D object ax = plt.axes(projection='3d') # 設置 3 個坐標軸的名稱 ax.set_xlabel('square') ax.set_ylabel('bedrooms') ax.set_zlabel('price') # 繪制 3D 散點圖 # 通過字典的方式取 DataFrame 的列 # 參數 c 表示隨着 price 值越大點的顏色越深,cmap即為顏色 ax.scatter3D(df1['square'], df1['bedrooms'], df1['price'], c=df1['price'], cmap='Greens')
數據規范化 def normalize_feature(df): return df.apply(lambda column: (column - column.mean()) / column.std()) df = normalize_feature(df1) df.head()
ax = plt.axes(projection='3d') ax.set_xlabel('square') ax.set_ylabel('bedrooms') ax.set_zlabel('price') ax.scatter3D(df['square'], df['bedrooms'], df['price'], c=df['price'], cmap='Reds')
df.info() ''' <class 'pandas.core.frame.DataFrame'> RangeIndex: 47 entries, 0 to 46 Data columns (total 3 columns): square 47 non-null float64 bedrooms 47 non-null float64 price 47 non-null float64 dtypes: float64(3) memory usage: 1.2 KB ''' 數據處理:添加 ones 列(x0) import numpy as np ones = pd.DataFrame({'ones': np.ones(len(df))})# ones是n行1列的數據框,表示x0恆為1 ones.info() ''' <class 'pandas.core.frame.DataFrame'> RangeIndex: 47 entries, 0 to 46 Data columns (total 1 columns): ones 47 non-null float64 dtypes: float64(1) memory usage: 456.0 bytes ''' df = pd.concat([ones, df], axis=1) # 根據列合並數據
df.head()

df.info() ''' <class 'pandas.core.frame.DataFrame'> RangeIndex: 47 entries, 0 to 46 Data columns (total 4 columns): ones 47 non-null float64 square 47 non-null float64 bedrooms 47 non-null float64 price 47 non-null float64 dtypes: float64(4) memory usage: 1.5 KB '''
import pandas as pd import numpy as np def normalize_feature(df): return df.apply(lambda column: (column - column.mean()) / column.std()) df = normalize_feature(pd.read_csv('data1.csv', names=['square', 'bedrooms', 'price'])) ones = pd.DataFrame({'ones': np.ones(len(df))})# ones是n行1列的數據框,表示x0恆為1 df = pd.concat([ones, df], axis=1) # 根據列合並數據 df.head()
數據處理:獲取 X 和 y X_data = np.array(df[df.columns[0:3]]) y_data = np.array(df[df.columns[-1]]).reshape(len(df), 1) print(X_data.shape, type(X_data)) print(y_data.shape, type(y_data)) ''' (47, 3) <class 'numpy.ndarray'> (47, 1) <class 'numpy.ndarray'> ''' 創建線性回歸模型(數據流圖) import tensorflow as tf alpha = 0.01 # 學習率 alpha epoch = 500 # 訓練全量數據集的輪數 # 輸入 X,形狀[47, 3] X = tf.placeholder(tf.float32, X_data.shape) # 輸出 y,形狀[47, 1] y = tf.placeholder(tf.float32, y_data.shape) # 權重變量 W,形狀[3,1] W = tf.get_variable("weights", (X_data.shape[1], 1), initializer=tf.constant_initializer()) # 假設函數 h(x) = w0*x0+w1*x1+w2*x2, 其中x0恆為1 # 推理值 y_pred 形狀[47,1] y_pred = tf.matmul(X, W) # 損失函數采用最小二乘法,y_pred - y 是形如[47, 1]的向量。 # tf.matmul(a,b,transpose_a=True) 表示:矩陣a的轉置乘矩陣b,即 [1,47] X [47,1] # 損失函數操作 loss loss_op = 1 / (2 * len(X_data)) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True) # 隨機梯度下降優化器 opt opt = tf.train.GradientDescentOptimizer(learning_rate=alpha) # 單輪訓練操作 train_op train_op = opt.minimize(loss_op) 創建會話(運行環境) with tf.Session() as sess: # 初始化全局變量 sess.run(tf.global_variables_initializer()) # 開始訓練模型, # 因為訓練集較小,所以每輪都使用全量數據訓練 for e in range(1, epoch + 1): sess.run(train_op, feed_dict={X: X_data, y: y_data}) if e % 10 == 0: loss, w = sess.run([loss_op, W], feed_dict={X: X_data, y: y_data}) log_str = "Epoch %d \t Loss=%.4g \t Model: y = %.4gx1 + %.4gx2 + %.4g" print(log_str % (e, loss, w[1], w[2], w[0])) ''' Epoch 10 Loss=0.4116 Model: y = 0.0791x1 + 0.03948x2 + 3.353e-10 Epoch 20 Loss=0.353 Model: y = 0.1489x1 + 0.07135x2 + -5.588e-11 Epoch 30 Loss=0.3087 Model: y = 0.2107x1 + 0.09676x2 + 3.912e-10 Epoch 40 Loss=0.2748 Model: y = 0.2655x1 + 0.1167x2 + -1.863e-11 Epoch 50 Loss=0.2489 Model: y = 0.3142x1 + 0.1321x2 + 1.77e-10 Epoch 60 Loss=0.2288 Model: y = 0.3576x1 + 0.1436x2 + -4.47e-10 Epoch 70 Loss=0.2131 Model: y = 0.3965x1 + 0.1519x2 + -8.103e-10 Epoch 80 Loss=0.2007 Model: y = 0.4313x1 + 0.1574x2 + -6.985e-10 Epoch 90 Loss=0.1908 Model: y = 0.4626x1 + 0.1607x2 + -4.936e-10 Epoch 100 Loss=0.1828 Model: y = 0.4909x1 + 0.1621x2 + -6.147e-10 Epoch 110 Loss=0.1763 Model: y = 0.5165x1 + 0.162x2 + -7.87e-10 Epoch 120 Loss=0.1709 Model: y = 0.5397x1 + 0.1606x2 + -5.821e-10 Epoch 130 Loss=0.1664 Model: y = 0.5609x1 + 0.1581x2 + -9.08e-10 Epoch 140 Loss=0.1625 Model: y = 0.5802x1 + 0.1549x2 + -9.965e-10 Epoch 150 Loss=0.1592 Model: y = 0.5979x1 + 0.1509x2 + -9.756e-10 Epoch 160 Loss=0.1564 Model: y = 0.6142x1 + 0.1465x2 + -4.144e-10 Epoch 170 Loss=0.1539 Model: y = 0.6292x1 + 0.1416x2 + -1.001e-10 Epoch 180 Loss=0.1518 Model: y = 0.643x1 + 0.1364x2 + -3.236e-10 Epoch 190 Loss=0.1498 Model: y = 0.6559x1 + 0.131x2 + -6.286e-11 Epoch 200 Loss=0.1481 Model: y = 0.6678x1 + 0.1255x2 + 2.119e-10 Epoch 210 Loss=0.1466 Model: y = 0.6789x1 + 0.1199x2 + -1.956e-10 Epoch 220 Loss=0.1452 Model: y = 0.6892x1 + 0.1142x2 + -1.758e-10 Epoch 230 Loss=0.1439 Model: y = 0.6989x1 + 0.1085x2 + -4.307e-11 Epoch 240 Loss=0.1428 Model: y = 0.708x1 + 0.1029x2 + 3.376e-10 Epoch 250 Loss=0.1418 Model: y = 0.7165x1 + 0.09736x2 + 2.841e-10 Epoch 260 Loss=0.1408 Model: y = 0.7245x1 + 0.09189x2 + 3.295e-10 Epoch 270 Loss=0.14 Model: y = 0.732x1 + 0.08653x2 + -8.033e-11 Epoch 280 Loss=0.1392 Model: y = 0.7391x1 + 0.08128x2 + 1.141e-10 Epoch 290 Loss=0.1385 Model: y = 0.7458x1 + 0.07616x2 + 1.321e-10 Epoch 300 Loss=0.1378 Model: y = 0.7522x1 + 0.07118x2 + 5.087e-10 Epoch 310 Loss=0.1372 Model: y = 0.7582x1 + 0.06634x2 + 7.398e-10 Epoch 320 Loss=0.1367 Model: y = 0.7639x1 + 0.06165x2 + 6.845e-10 Epoch 330 Loss=0.1362 Model: y = 0.7693x1 + 0.0571x2 + 8.423e-10 Epoch 340 Loss=0.1357 Model: y = 0.7744x1 + 0.0527x2 + 9.252e-10 Epoch 350 Loss=0.1353 Model: y = 0.7793x1 + 0.04845x2 + 1.104e-09 Epoch 360 Loss=0.1349 Model: y = 0.784x1 + 0.04435x2 + 1.145e-09 Epoch 370 Loss=0.1346 Model: y = 0.7884x1 + 0.0404x2 + 1.631e-09 Epoch 380 Loss=0.1343 Model: y = 0.7926x1 + 0.03658x2 + 1.446e-09 Epoch 390 Loss=0.134 Model: y = 0.7966x1 + 0.03291x2 + 1.429e-09 Epoch 400 Loss=0.1337 Model: y = 0.8004x1 + 0.02938x2 + 1.694e-09 Epoch 410 Loss=0.1334 Model: y = 0.8041x1 + 0.02598x2 + 1.697e-09 Epoch 420 Loss=0.1332 Model: y = 0.8076x1 + 0.02271x2 + 2.125e-09 Epoch 430 Loss=0.133 Model: y = 0.8109x1 + 0.01957x2 + 2.292e-09 Epoch 440 Loss=0.1328 Model: y = 0.8141x1 + 0.01655x2 + 2.913e-09 Epoch 450 Loss=0.1326 Model: y = 0.8171x1 + 0.01366x2 + 3.412e-09 Epoch 460 Loss=0.1325 Model: y = 0.82x1 + 0.01087x2 + 3.749e-09 Epoch 470 Loss=0.1323 Model: y = 0.8228x1 + 0.008204x2 + 3.499e-09 Epoch 480 Loss=0.1322 Model: y = 0.8254x1 + 0.005641x2 + 3.663e-09 Epoch 490 Loss=0.1321 Model: y = 0.828x1 + 0.003183x2 + 4.2e-09 Epoch 500 Loss=0.132 Model: y = 0.8304x1 + 0.0008239x2 + 4.138e-09 '''
• 使用 TensorBoard 可視化模型數據流圖
TensorBoard 可視化工具
在數據處理過程中,用戶通常想要可視化地直觀查看
數據集分布情況。
在模型設計過程中,用戶往往需要分析和檢查
數據流圖是否正確實現。
在模型訓練過程中,用戶也常常需要關注
模型參數和
超參數變化趨勢。
在模型測試過程中,用戶也往往需要查看
准確率和
召回率等評估指標。
因此,TensorFlow 項目組開發了機器學習可視化工具
TensorBoard ,
它通過展示直觀的圖形,能夠有效地輔助機器學習程序的開發者和使
用者理解算法模型及其工作流程,提升模型開發工作效率。
TensorBoard 可視化訓練

TensorBoard 可視化統計數據

TensorBoard 可視化數據分布

TensorBoard 可視化數據集(MNIST)
TensorBoard 可視化數據流圖

TensorBoard 使用流程
可視化的數據是數據流圖和張量,它們需要在會話中加載或執行操作后才能獲取。然后,
用戶需要使用
FileWriter 實例將這些數據寫入事件文件。最后,啟動 TensorBoard 程序,
加載事件文件中的序列化數據,從而可以在各個面板中展示對應的可視化對象。

tf.summary 模塊介紹
前述流程中使用的 FileWriter 實例和匯總操作(Summary Ops)
均屬於 tf.summary 模塊。其主要功能是獲取和輸出模型相關的
序列化數據,它貫通 TensorBoard 的整個使用流程。
tf.summary 模塊的核心部分由一組匯總操作以及
FileWriter、Summary 和 Event 3個類組成。

可視化數據流圖 工作流

Which one is better?

名字作用域與抽象節點

創建 FileWriter 實例

啟動 TensorBoard
D:\Program Files\jupyter notebook\TensorFlow\TensorFlowTest\chapter-4\summary>tensorboard --logdir ./ --host localhost
測試代碼:
import pandas as pd import numpy as np def normalize_feature(df): return df.apply(lambda column: (column - column.mean()) / column.std()) df = normalize_feature(pd.read_csv('data1.csv', names=['square', 'bedrooms', 'price'])) ones = pd.DataFrame({'ones': np.ones(len(df))})# ones是n行1列的數據框,表示x0恆為1 df = pd.concat([ones, df], axis=1) # 根據列合並數據 X_data = np.array(df[df.columns[0:3]]) y_data = np.array(df[df.columns[-1]]).reshape(len(df), 1) print(X_data.shape, type(X_data)) print(y_data.shape, type(y_data)) ''' (47, 3) <class 'numpy.ndarray'> (47, 1) <class 'numpy.ndarray'> ''' 創建線性回歸模型(數據流圖) import tensorflow as tf alpha = 0.01 # 學習率 alpha epoch = 500 # 訓練全量數據集的輪數 with tf.name_scope('input'): # 輸入 X,形狀[47, 3] X = tf.placeholder(tf.float32, X_data.shape, name='X') # 輸出 y,形狀[47, 1] y = tf.placeholder(tf.float32, y_data.shape, name='y') with tf.name_scope('hypothesis'): # 權重變量 W,形狀[3,1] W = tf.get_variable("weights", (X_data.shape[1], 1), initializer=tf.constant_initializer()) # 假設函數 h(x) = w0*x0+w1*x1+w2*x2, 其中x0恆為1 # 推理值 y_pred 形狀[47,1] y_pred = tf.matmul(X, W, name='y_pred') with tf.name_scope('loss'): # 損失函數采用最小二乘法,y_pred - y 是形如[47, 1]的向量。 # tf.matmul(a,b,transpose_a=True) 表示:矩陣a的轉置乘矩陣b,即 [1,47] X [47,1] # 損失函數操作 loss loss_op = 1 / (2 * len(X_data)) * tf.matmul((y_pred - y), (y_pred - y), transpose_a=True) with tf.name_scope('train'): # 隨機梯度下降優化器 opt train_op = tf.train.GradientDescentOptimizer(learning_rate=alpha).minimize(loss_op) 創建會話(運行環境) with tf.Session() as sess: # 初始化全局變量 sess.run(tf.global_variables_initializer()) # 創建FileWriter實例,並傳入當前會話加載的數據流圖 writer = tf.summary.FileWriter('./summary/linear-regression-1', sess.graph) # 開始訓練模型 # 因為訓練集較小,所以每輪都使用全量數據訓練 for e in range(1, epoch + 1): sess.run(train_op, feed_dict={X: X_data, y: y_data}) if e % 10 == 0: loss, w = sess.run([loss_op, W], feed_dict={X: X_data, y: y_data}) log_str = "Epoch %d \t Loss=%.4g \t Model: y = %.4gx1 + %.4gx2 + %.4g" print(log_str % (e, loss, w[1], w[2], w[0])) # 關閉FileWriter的輸出流 writer.close() ''' Epoch 100 Loss=0.1835 Model: y = 0.4909x1 + 0.1621x2 + -6.147e-10 Epoch 200 Loss=0.1483 Model: y = 0.6678x1 + 0.1255x2 + 2.119e-10 Epoch 300 Loss=0.1379 Model: y = 0.7522x1 + 0.07118x2 + 5.087e-10 Epoch 400 Loss=0.1337 Model: y = 0.8004x1 + 0.02938x2 + 1.694e-09 Epoch 500 Loss=0.132 Model: y = 0.8304x1 + 0.0008239x2 + 4.138e-09 ''' 可視化損失值 print(len(loss_data)) ''' 500 ''' import matplotlib.pyplot as plt import seaborn as sns sns.set(context="notebook", style="whitegrid", palette="dark") ax = sns.lineplot(x='epoch', y='loss', data=pd.DataFrame({'loss': loss_data, 'epoch': np.arange(epoch)})) ax.set_xlabel('epoch') ax.set_ylabel('loss') plt.show()