多元性線性迴歸
與之前的一元線性迴歸相比:都是線性模型,但是輸入的特徵維度是多維的,所以應建立多維的線性映射關係來實現對於數據的預測。本文將以波士頓房價爲例進行多維線性模型的建立、訓練以及預測。
數據說明
- 共506個樣本,每個樣本共12個特徵;
- 數據以csv的格式進行存儲,在csv中表現爲507行13列;第一行爲列名,前12列表示特徵,最後一列表示標籤值。
讀取數據:
import tensorflow asd tf
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import sklearn.utils import shuffle
df = pd.read_csv("Boston.csv")
print(df.describe())
print(df)
上述代碼實現了對於csv數據的載入。主要是利用了pandas這一模塊,pandas是基於python的開源第三方庫,可用於載入包括csv在內的多種形式的數據,並且在載入csv數據時可以按列索引;利用上述的代碼的倒數第二行,可以得到csv文件中每列參數的摘要,包括最值、均值等;利用最後一行可以將csv的所有數據按表格的形式打印出來。並且,使用pandas要進一步轉化爲np形式,才能進一步處理,所以要載入numpy模塊。
數據準備
# 將pandas文件轉化爲numpy格式,因爲後續數據分離以及歸一化對是基於numpy
df = df.values
df = np.array(df)
print(df) # 打印所有數據
# 數據歸一化,已知有13列數據,前12列是特徵,最後一列是標籤
# 數據歸一化是爲了壓縮各個特徵的取值範圍,有利於loss的收斂
# 但是注意是對特徵信息給歸一化,不要壓縮標籤值
for i in range(12):
df[:, i] = df[:, i]/(df[:, i].max()-df[:, i].min())
# 分離csv數據
x_data = df[:, :12] # 取前12列
y_data = df[:, 12] # 取第13列
csv數據讀入後首先要轉化爲np格式,以便之後做矩陣的處理。由於各個特徵對於最終結果的實際影響作用不同,所以要對數據進行歸一化,壓縮其變化範圍,這樣有利於訓練時的快速有效收斂。但是注意,歸一化是針對輸入值的,不要對標籤值進行歸一化。
構建模型
# 建立模型
# 此處的x即爲對於一個樣本的概述,一個樣本有12個特徵;爲了適應batchsize,此處不指明有幾個樣本;None可以爲1,也可以是更大的
# y同理,每個標籤只有一個維度
x = tf.placeholder(tf.float32, [None, 12], name='X')
y = tf.placeholder(tf.float32, [None, 1], name='Y')
with tf.name_scope("Model"): # 封裝權重、偏差、loss以及前向計算於一個命名空間
w = tf.Variable(tf.random_normal([12, 1], stddev=0.01), name='W')
b = tf.Variable(1.0, name='b')
def model(x, w, b): # 定義前行計算模型
return(tf.matmul(x,w)+b)
preb = model(x, w, b) # 建立前向計算操作
如上述代碼實現多維線性模型的建立,並建立的對應的前向計算操作;上述代碼中,使用了命名空間,這其實有點類似c++中的命名空間,不同的是,此處使用的效果不僅在代碼上有更好的可讀性,在graph上一個命名空間表示一個子圖,即在計算圖上也有較好的可讀性。着重理解佔位符中的NONE,即不固定輸入的樣本數目,這將在批量訓練時有重要作用。
進行訓練前的準備
# 設置超參
train_epochs = 200
learning_rate = 0.01
logdir = 'E:/log'
with tf.name_scope("Loss_Function"): # 封損失函數在此命名空間
loss_function = tf.reduce_mean(tf.pow(y-preb, 2))
# 優化器
optimizer = tf.train.GradientDescentOptimizer(learning_rate).minimize(loss_function)
# 將loss記錄在graph上
sum_loss_op = tf.summary.scalar("loss", loss_function)
merged = tf.summary.merge_all()
訓練前要設好超參,此處的模型較爲簡單,超參只包括訓練的輪數以及學習率;同時要爲模型建立損失函數以及優化器;並且,爲了將loss值顯示在graph上,此處定義了一個sum_loss_op,由於是summary.scalar所以將在tensorboard的scalar中顯示,注意要實現顯示,merge是必要的操作,尤其是有多個數據要顯示在tensorboard中時,此步是必需要有的。
進行訓練
# 啓動會話
sess = tf.Session()
sess.run(tf.global_variables_initializer())
writer = tf.summary.FileWriter(logdir,sess.graph) # 記錄日誌
print('***********TRAIN***********')
loss_list = [] # loss統計值集合
for epoch in range(train_epochs): # 逐輪次訓練
loss_sum = 0.0 # 統計每輪訓練的loss值
for xs, ys in zip(x_data, y_data): # 從訓練數據與標籤值中對應抽取數據
xs = xs.reshape(1, 12) # feeddict前一定要確保尺寸與佔位符規定的一致
ys = ys.reshape(1, 1)
_, summary_str, loss = sess.run([optimizer, sum_loss_op, loss_function], feed_dict={x: xs, y: ys})# 進行優化、記錄loss,計算loss三個操作
loss_sum = loss_sum+loss # 統計每輪訓練的loss值
writer.add_summary(summary_str, epoch) # 將記錄loss的返回值與輪數對應繪製圖像
xvalues, yvaules = shuffle(x_data, y_data) # 每次訓練打亂原數據集
btemp = b.eval(session=sess) # 獲取此輪訓練得到的b值
wtemp = w.eval(session=sess) # 獲取本輪訓練得到的w值
loss_average = loss_sum/len(y_data) # 計算本輪評價loss值
loss_list.append(loss_average) # 記錄本輪評價loss值
# 打印本輪訓練結果
print("epoch:", epoch+1, "loss: ", loss_average, "b: ", btemp, "w: ", wtemp)
上述代碼實現了對於所建立模型的訓練;注意在feed_dict之前,要確保喂的值與佔位符所規定的維度一致;每輪訓練後要打亂原有數據集,是爲了防止模型取背答案,換句話說就是防止模型將順序當作特徵進行了學習。
模型應用
# 檢驗模型
n = np.random.randint(506)
print(n)
x_test = x_data[n]
target = y_data[n]
x_test = x_test.reshape(1, 12)
predict = sess.run(preb, feed_dict={x: x_test})
print("prediction: ", predict, "Target: ", target)
writer.close()
利用上述代碼檢測模型;由於初步教程,並未對數據集進行訓練集測試集以及驗證集的劃分,所以僅以實驗目的,此處利用隨機數生成索引值,利用索引值去抽取一個樣本,進行檢測值與實際標籤值的對比。