日萌社
人工智能AI:Keras PyTorch MXNet TensorFlow PaddlePaddle 深度學習實戰(不定時更新)
2.4 案例:實現線性迴歸
學習目標
- 目標
- 應用op的name參數實現op的名字修改
- 應用variable_scope實現圖程序作用域的添加
- 應用scalar或histogram實現張量值的跟蹤顯示
- 應用merge_all實現張量值的合併
- 應用add_summary實現張量值寫入文件
- 應用tf.train.saver實現TensorFlow的模型保存以及加載
- 應用tf.app.flags實現命令行參數添加和使用
- 應用reduce_mean、square實現均方誤差計算
- 應用tf.train.GradientDescentOptimizer實現有梯度下降優化器創建
- 應用minimize函數優化損失
- 知道梯度爆炸以及常見解決技巧
- 應用
- 實現線性迴歸模型
- 內容預覽
- 2.6.1 線性迴歸原理複習
- 2.6.2 案例:實現線性迴歸的訓練
- 2.6.3 增加其他功能
- 1 增加變量顯示
- 2 增加命名空間
- 3 模型的保存與加載
- 4 命令行參數使用
2.4.1 線性迴歸原理複習
根據數據建立迴歸模型,w1x1+w2x2+…..+b = y,通過真實值與預測值之間建立誤差,使用梯度下降優化得到損失最小對應的權重和偏置。最終確定模型的權重和偏置參數。最後可以用這些參數進行預測。
2.4.2 案例:實現線性迴歸的訓練
1 案例確定
- 假設隨機指定100個點,只有一個特徵
- 數據本身的分佈爲 y = 0.8 * x + 0.7
這裏將數據分佈的規律確定,是爲了使我們訓練出的參數跟真實的參數(即0.8和0.7)比較是否訓練準確
2 步驟分析
- 1 準備好數據集:y = 0.8x + 0.7 100個樣本
- 2 建立線性模型
- 隨機初始化W1和b1
- y = W·X + b,目標:求出權重W和偏置b
- 3 確定損失函數(預測值與真實值之間的誤差)-均方誤差
- 4 梯度下降優化損失:需要指定學習率(超參數)
4 實現完整功能
相關API
運算
- 矩陣運算
- tf.matmul(x, w)
- 平方
- tf.square(error)
- 均值
- tf.reduce_mean(error)
error = tf.reduce_mean(tf.square(y_predict - y_true))
梯度下降優化
- tf.train.GradientDescentOptimizer(learning_rate)
- 梯度下降優化
- learning_rate:學習率,一般爲0~1之間比較小的值
- method:
- minimize(loss)
- return:梯度下降op
# Tensorflow中提供了多種優化方式,不需要自行實現梯度下降運行原理公式,自定義使用優化種類
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
完整代碼過程分析:
import tensorflow as tf
import os
def linear_regression():
"""
自實現線性迴歸
:return: None
"""
# 1)準備好數據集:y = 0.8x + 0.7 100個樣本
# 特徵值X, 目標值y_true
X = tf.random_normal(shape=(100, 1), mean=2, stddev=2)
# y_true [100, 1]
# 矩陣運算 X(100, 1)* (1, 1)= y_true(100, 1)
y_true = tf.matmul(X, [[0.8]]) + 0.7
# 2)建立線性模型:
# y = W·X + b,目標:求出權重W和偏置b
# 3)隨機初始化W1和b1
weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)))
bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)))
y_predict = tf.matmul(X, weights) + bias
# 4)確定損失函數(預測值與真實值之間的誤差)-均方誤差
error = tf.reduce_mean(tf.square(y_predict - y_true))
# 5)梯度下降優化損失:需要指定學習率(超參數)
# W2 = W1 - 學習率*(方向)
# b2 = b1 - 學習率*(方向)
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
# 初始化變量
init = tf.global_variables_initializer()
# 開啓會話進行訓練
with tf.Session() as sess:
# 運行初始化變量Op
sess.run(init)
print("隨機初始化的權重爲%f, 偏置爲%f" % (weights.eval(), bias.eval()))
# 訓練模型
for i in range(100):
sess.run(optimizer)
print("第%d步的誤差爲%f,權重爲%f, 偏置爲%f" % (i, error.eval(), weights.eval(), bias.eval()))
return None
6 變量的trainable設置觀察
trainable的參數作用,指定是否訓練
weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0), name="weights", trainable=False)
2.4.3 增加其他功能
- 增加命名空間
- 命令行參數設置
2 增加命名空間
是代碼結構更加清晰,Tensorboard圖結構清楚
with tf.variable_scope("lr_model"):
def linear_regression():
# 1)準備好數據集:y = 0.8x + 0.7 100個樣本
# 特徵值X, 目標值y_true
with tf.variable_scope("original_data"):
X = tf.random_normal(shape=(100, 1), mean=2, stddev=2, name="original_data_x")
# y_true [100, 1]
# 矩陣運算 X(100, 1)* (1, 1)= y_true(100, 1)
y_true = tf.matmul(X, [[0.8]], name="original_matmul") + 0.7
# 2)建立線性模型:
# y = W·X + b,目標:求出權重W和偏置b
# 3)隨機初始化W1和b1
with tf.variable_scope("linear_model"):
weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="weights")
bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="bias")
y_predict = tf.matmul(X, weights, name="model_matmul") + bias
# 4)確定損失函數(預測值與真實值之間的誤差)-均方誤差
with tf.variable_scope("loss"):
error = tf.reduce_mean(tf.square(y_predict - y_true), name="error_op")
# 5)梯度下降優化損失:需要指定學習率(超參數)
# W2 = W1 - 學習率*(方向)
# b2 = b1 - 學習率*(方向)
with tf.variable_scope("gd_optimizer"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01, name="optimizer").minimize(error)
# 2)收集變量
tf.summary.scalar("error", error)
tf.summary.histogram("weights", weights)
tf.summary.histogram("bias", bias)
# 3)合併變量
merge = tf.summary.merge_all()
# 初始化變量
init = tf.global_variables_initializer()
# 開啓會話進行訓練
with tf.Session() as sess:
# 運行初始化變量Op
sess.run(init)
print("隨機初始化的權重爲%f, 偏置爲%f" % (weights.eval(), bias.eval()))
# 1)創建事件文件
file_writer = tf.summary.FileWriter(logdir="./summary", graph=sess.graph)
# 訓練模型
for i in range(100):
sess.run(optimizer)
print("第%d步的誤差爲%f,權重爲%f, 偏置爲%f" % (i, error.eval(), weights.eval(), bias.eval()))
# 4)運行合併變量op
summary = sess.run(merge)
file_writer.add_summary(summary, i)
return None
3 模型的保存與加載
- tf.train.Saver(var_list=None,max_to_keep=5)
- 保存和加載模型(保存文件格式:checkpoint文件)
- var_list:指定將要保存和還原的變量。它可以作爲一個dict或一個列表傳遞.
- max_to_keep:指示要保留的最近檢查點文件的最大數量。創建新文件時,會刪除較舊的文件。如果無或0,則保留所有檢查點文件。默認爲5(即保留最新的5個檢查點文件。)
使用
例如:
指定目錄+模型名字
saver.save(sess, '/tmp/ckpt/test/myregression.ckpt')
saver.restore(sess, '/tmp/ckpt/test/myregression.ckpt')
如要判斷模型是否存在,直接指定目錄
checkpoint = tf.train.latest_checkpoint("./tmp/model/")
saver.restore(sess, checkpoint)
4 命令行參數使用
- 1、 tf.app.flags.,在flags有一個FLAGS標誌,它在程序中可以調用到我們
前面具體定義的flag_name
- 2、通過tf.app.run()啓動main(argv)函數
# 定義一些常用的命令行參數
# 訓練步數
tf.app.flags.DEFINE_integer("max_step", 0, "訓練模型的步數")
# 定義模型的路徑
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路徑+模型名字")
# 定義獲取命令行參數
FLAGS = tf.app.flags.FLAGS
# 開啓訓練
# 訓練的步數(依據模型大小而定)
for i in range(FLAGS.max_step):
sess.run(train_op)
完整代碼
import tensorflow as tf
import os
tf.app.flags.DEFINE_string("model_path", "./linear_regression/", "模型保存的路徑和文件名")
FLAGS = tf.app.flags.FLAGS
def linear_regression():
# 1)準備好數據集:y = 0.8x + 0.7 100個樣本
# 特徵值X, 目標值y_true
with tf.variable_scope("original_data"):
X = tf.random_normal(shape=(100, 1), mean=2, stddev=2, name="original_data_x")
# y_true [100, 1]
# 矩陣運算 X(100, 1)* (1, 1)= y_true(100, 1)
y_true = tf.matmul(X, [[0.8]], name="original_matmul") + 0.7
# 2)建立線性模型:
# y = W·X + b,目標:求出權重W和偏置b
# 3)隨機初始化W1和b1
with tf.variable_scope("linear_model"):
weights = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="weights")
bias = tf.Variable(initial_value=tf.random_normal(shape=(1, 1)), name="bias")
y_predict = tf.matmul(X, weights, name="model_matmul") + bias
# 4)確定損失函數(預測值與真實值之間的誤差)-均方誤差
with tf.variable_scope("loss"):
error = tf.reduce_mean(tf.square(y_predict - y_true), name="error_op")
# 5)梯度下降優化損失:需要指定學習率(超參數)
# W2 = W1 - 學習率*(方向)
# b2 = b1 - 學習率*(方向)
with tf.variable_scope("gd_optimizer"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01, name="optimizer").minimize(error)
# 2)收集變量
tf.summary.scalar("error", error)
tf.summary.histogram("weights", weights)
tf.summary.histogram("bias", bias)
# 3)合併變量
merge = tf.summary.merge_all()
# 初始化變量
init = tf.global_variables_initializer()
# 開啓會話進行訓練
with tf.Session() as sess:
# 運行初始化變量Op
sess.run(init)
# 未經訓練的權重和偏置
print("隨機初始化的權重爲%f, 偏置爲%f" % (weights.eval(), bias.eval()))
# 當存在checkpoint文件,就加載模型
# 1)創建事件文件
file_writer = tf.summary.FileWriter(logdir="./summary", graph=sess.graph)
# 訓練模型
for i in range(100):
sess.run(optimizer)
print("第%d步的誤差爲%f,權重爲%f, 偏置爲%f" % (i, error.eval(), weights.eval(), bias.eval()))
# 4)運行合併變量op
summary = sess.run(merge)
file_writer.add_summary(summary, i)
return None
def main(argv):
print("這是main函數")
print(argv)
print(FLAGS.model_path)
linear_regression()
if __name__ == "__main__":
tf.app.run()
作業:將面向過程改爲面向對象
參考代碼
# 用tensorflow自實現一個線性迴歸案例
# 定義一些常用的命令行參數
# 訓練步數
tf.app.flags.DEFINE_integer("max_step", 0, "訓練模型的步數")
# 定義模型的路徑
tf.app.flags.DEFINE_string("model_dir", " ", "模型保存的路徑+模型名字")
FLAGS = tf.app.flags.FLAGS
class MyLinearRegression(object):
"""
自實現線性迴歸
"""
def __init__(self):
pass
def inputs(self):
"""
獲取特徵值目標值數據數據
:return:
"""
x_data = tf.random_normal([100, 1], mean=1.0, stddev=1.0, name="x_data")
y_true = tf.matmul(x_data, [[0.7]]) + 0.8
return x_data, y_true
def inference(self, feature):
"""
根據輸入數據建立模型
:param feature:
:param label:
:return:
"""
with tf.variable_scope("linea_model"):
# 2、建立迴歸模型,分析別人的數據的特徵數量--->權重數量, 偏置b
# 由於有梯度下降算法優化,所以一開始給隨機的參數,權重和偏置
# 被優化的參數,必須得使用變量op去定義
# 變量初始化權重和偏置
# weight 2維[1, 1] bias [1]
# 變量op當中會有trainable參數決定是否訓練
self.weight = tf.Variable(tf.random_normal([1, 1], mean=0.0, stddev=1.0),
name="weights")
self.bias = tf.Variable(0.0, name='biases')
# 建立迴歸公式去得出預測結果
y_predict = tf.matmul(feature, self.weight) + self.bias
return y_predict
def loss(self, y_true, y_predict):
"""
目標值和真實值計算損失
:return: loss
"""
# 3、求出我們模型跟真實數據之間的損失
# 均方誤差公式
loss = tf.reduce_mean(tf.square(y_true - y_predict))
return loss
def merge_summary(self, loss):
# 1、收集張量的值
tf.summary.scalar("losses", loss)
tf.summary.histogram("w", self.weight)
tf.summary.histogram('b', self.bias)
# 2、合併變量
merged = tf.summary.merge_all()
return merged
def sgd_op(self, loss):
"""
獲取訓練OP
:return:
"""
# 4、使用梯度下降優化器優化
# 填充學習率:0 ~ 1 學習率是非常小,
# 學習率大小決定你到達損失一個步數多少
# 最小化損失
train_op = tf.train.GradientDescentOptimizer(0.1).minimize(loss)
return train_op
def train(self):
"""
訓練模型
:param loss:
:return:
"""
g = tf.get_default_graph()
with g.as_default():
x_data, y_true = self.inputs()
y_predict = self.inference(x_data)
loss = self.loss(y_true, y_predict)
train_op = self.sgd_op(loss)
# 收集觀察的結果值
merged = self.merge_summary(loss)
saver = tf.train.Saver()
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
# 在沒訓練,模型的參數值
print("初始化的權重:%f, 偏置:%f" % (self.weight.eval(), self.bias.eval()))
# 開啓訓練
# 訓練的步數(依據模型大小而定)
for i in range(FLAGS.max_step):
sess.run(train_op)
# 生成事件文件,觀察圖結構
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)
print("訓練第%d步之後的損失:%f, 權重:%f, 偏置:%f" % (
i,
loss.eval(),
self.weight.eval(),
self.bias.eval()))
# 運行收集變量的結果
summary = sess.run(merged)
# 添加到文件
file_writer.add_summary(summary, i)
if __name__ == '__main__':
lr = MyLinearRegression()
lr.train()