目錄
- 一、tensorflow框架
- 0.tensorflow的基本結構
- 1.圖
- 2.會話
- 3.張量
- 4.變數
- 5.高階API(keras)
- 6.案例:線性迴歸
- 7.檔案I/O操作
- 案例1:讀取狗圖片
- 案例2:讀取二進位制圖片
- 案例3:全連線對手寫數字進行識別
- 二、神經網路
- 案例:全連線對手寫數字進行識別
- 案例:讀取檔案
- 案例:mnist手寫數字資料在執行時候實時提供給給佔位符
- 案例:驗證碼圖片識別
- 案例:使用keras分類
一、tensorflow框架
圖
會話
張量
變數
0.tensorflow的基本結構
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
def tensorflow_demo():
"""
TensorFlow的基本結構
:return:
"""
# 原生python加法運算
a = 2
b = 3
c = a + b
print("普通加法運算的結果:\n", c)
# TensorFlow實現加法運算
a_t = tf.constant(2)
b_t = tf.constant(3)
c_t = a_t + b_t
print("TensorFlow加法運算的結果:\n", c_t)
# 開啟會話
with tf.Session() as sess:
c_t_value = sess.run(c_t)
print("c_t_value:\n", c_t_value)
1.圖
tensorflow的圖主要是兩個部分構成:
構建圖:
定義資料(張量Tensor)和操作(節點Op)
執行圖:
呼叫各方子淵,將定義和哦啊的資料和操作執行起來,配合會話使用
檢視預設圖:
tf.get_default_graph()
a_t.graph
自定義圖:
new_g = tf.Graph()
with new_g.as_default():
a_new.graph
TensorBoard-將圖寫入本地生成events檔案:
tf.summary.FileWriter("./tmp/summary", graph=sess.graph)
資料:Tensor物件
操作:Operation物件 - Op
1 常見OP
操作函式 & 操作物件
tf.constant(Tensor物件) 輸入Tensor物件 -Const-輸出 Tensor物件
tf.add(Tensor物件1, Tensor物件2) 輸入Tensor物件1, Tensor物件2 - Add物件 - 輸出 Tensor物件3
2 指令名稱
一張圖 - 一個名稱空間
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
def graph_demo():
"""
圖的演示
:return:
"""
# TensorFlow實現加法運算
a_t = tf.constant(2, name="a_t")
b_t = tf.constant(3, name="a_t")
c_t = tf.add(a_t, b_t, name="c_t")
print("a_t:\n", a_t)
print("b_t:\n", b_t)
print("c_t:\n", c_t)
# print("c_t.eval():\n", c_t.eval())
# 檢視預設圖
# 方法1:呼叫方法
default_g = tf.get_default_graph()
print("default_g:\n", default_g)
# 方法2:檢視屬性
print("a_t的圖屬性:\n", a_t.graph)
print("c_t的圖屬性:\n", c_t.graph)
# 自定義圖
new_g = tf.Graph()
# 在自己的圖中定義資料和操作
with new_g.as_default():
a_new = tf.constant(20)
b_new = tf.constant(30)
c_new = a_new + b_new
print("a_new:\n", a_new)
print("b_new:\n", b_new)
print("c_new:\n", c_new)
print("a_new的圖屬性:\n", a_new.graph)
print("c_new的圖屬性:\n", c_new.graph)
# 開啟會話
with tf.Session() as sess:
# c_t_value = sess.run(c_t)
# 試圖執行自定義圖中的資料、操作
# c_new_value = sess.run((c_new))
# print("c_new_value:\n", c_new_value)
print("c_t_value:\n", c_t.eval())
print("sess的圖屬性:\n", sess.graph)
# 1)將圖寫入本地生成events檔案
tf.summary.FileWriter("./tmp/summary", graph=sess.graph)
# 開啟new_g的會話
with tf.Session(graph=new_g) as new_sess:
c_new_value = new_sess.run((c_new))
print("c_new_value:\n", c_new_value)
print("new_sess的圖屬性:\n", new_sess.graph)
return None
2.會話
tf.Session:用於完整的程式當中
tf.InteractiveSession:用於互動式上下文中的TensorFlow ,例如shell
1)會話掌握資源,用完要回收 - 上下文管理器
2)初始化會話物件時的引數
graph=None
target:如果將此引數留空(預設設定),
會話將僅使用本地計算機中的裝置。
可以指定 grpc:// 網址,以便指定 TensorFlow 伺服器的地址,
這使得會話可以訪問該伺服器控制的計算機上的所有裝置。
config:此引數允許您指定一個 tf.ConfigProto
以便控制會話的行為。例如,ConfigProto協議用於列印裝置使用資訊
3)run(fetches,feed_dict=None)
3 feed操作
a = tf.placeholder(tf.float32, shape=)
b = tf.placeholder(tf.float32, shape=)
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
def session_demo():
"""
會話的演示
:return:
"""
# TensorFlow實現加法運算
a_t = tf.constant(2, name="a_t")
b_t = tf.constant(3, name="a_t")
c_t = tf.add(a_t, b_t, name="c_t")
print("a_t:\n", a_t)
print("b_t:\n", b_t)
print("c_t:\n", c_t)
# print("c_t.eval():\n", c_t.eval())
# 定義佔位符
a_ph = tf.placeholder(tf.float32)
b_ph = tf.placeholder(tf.float32)
c_ph = tf.add(a_ph, b_ph)
print("a_ph:\n", a_ph)
print("b_ph:\n", b_ph)
print("c_ph:\n", c_ph)
# 檢視預設圖
# 方法1:呼叫方法
default_g = tf.get_default_graph()
print("default_g:\n", default_g)
# 方法2:檢視屬性
print("a_t的圖屬性:\n", a_t.graph)
print("c_t的圖屬性:\n", c_t.graph)
# 開啟會話
with tf.Session(config=tf.ConfigProto(allow_soft_placement=True,
log_device_placement=True)) as sess:
# 執行placeholder
c_ph_value = sess.run(c_ph, feed_dict={a_ph: 3.9, b_ph: 4.8})
print("c_ph_value:\n", c_ph_value)
# c_t_value = sess.run(c_t)
# 試圖執行自定義圖中的資料、操作
# c_new_value = sess.run((c_new))
# print("c_new_value:\n", c_new_value)
# 同時檢視a_t, b_t, c_t
a, b, c = sess.run([a_t, b_t, c_t])
print("abc:\n", a, b, c)
print("c_t_value:\n", c_t.eval())
print("sess的圖屬性:\n", sess.graph)
# 1)將圖寫入本地生成events檔案
tf.summary.FileWriter("./tmp/summary", graph=sess.graph)
return None
3.張量
張量Tensor
print()
ndarray
1.張量(Tensor)
張量 在計算機當中如何儲存?
標量 一個數字 0階張量
向量 一維陣列 [2, 3, 4] 1階張量
矩陣 二維陣列 [[2, 3, 4], 2階張量
[2, 3, 4]]
……
張量 n維陣列 n階張量
1 張量的型別
2 張量的階
建立張量的時候,如果不指定型別
預設 tf.float32
整型 tf.int32
浮點型 tf.float32
2 建立張量的指令
3 張量的變換
ndarray屬性的修改
型別的修改
1)ndarray.astype(type)
tf.cast(tensor, dtype)
不會改變原始的tensor
返回新的改變型別後的tensor
2)ndarray.tostring()
形狀的修改
1)ndarray.reshape(shape)
-1 自動計算形狀
2)ndarray.resize(shape)
靜態形狀 - 初始建立張量時的形狀
1)如何改變靜態形狀
什麼情況下才可以改變/更新靜態形狀?
只有在形狀沒有完全固定下來的情況下
tensor.set_shape(shape)
2)如何改變動態形狀
tf.reshape(tensor, shape)
不會改變原始的tensor
返回新的改變形狀後的tensor
動態建立新張量時,張量的元素個數必須匹配
4 張量的數學運算
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
def tensor_demo():
"""
張量的演示
:return:
"""
tensor1 = tf.constant(4.0)
tensor2 = tf.constant([1, 2, 3, 4])
linear_squares = tf.constant([[4], [9], [16], [25]], dtype=tf.int32)
print("tensor1:\n", tensor1)
print("tensor2:\n", tensor2)
print("linear_squares_before:\n", linear_squares)
# 張量型別的修改
l_cast = tf.cast(linear_squares, dtype=tf.float32)
print("linear_squares_after:\n", linear_squares)
print("l_cast:\n", l_cast)
# 更新/改變靜態形狀
# 定義佔位符
# 沒有完全固定下來的靜態形狀
a_p = tf.placeholder(dtype=tf.float32, shape=[None, None])
b_p = tf.placeholder(dtype=tf.float32, shape=[None, 10])
c_p = tf.placeholder(dtype=tf.float32, shape=[3, 2])
print("a_p:\n", a_p)
print("b_p:\n", b_p)
print("c_p:\n", c_p)
# 更新形狀未確定的部分
# a_p.set_shape([2, 3])
# b_p.set_shape([2, 10])
# c_p.set_shape([2, 3])
# 動態形狀修改
a_p_reshape = tf.reshape(a_p, shape=[2, 3, 1])
print("a_p:\n", a_p)
# print("b_p:\n", b_p)
print("a_p_reshape:\n", a_p_reshape)
c_p_reshape = tf.reshape(c_p, shape=[2, 3])
print("c_p:\n", c_p)
print("c_p_reshape:\n", c_p_reshape)
4.變數
變數OP
TensorFlow - 變數
儲存模型引數
1 建立變數
變數需要顯式初始化,才能執行值
2 使用tf.variable_scope()修改變數的名稱空間
使得結構更加清晰
import tensorflow as tf
import os
os.environ['TF_CPP_MIN_LOG_LEVEL']='2'
def variable_demo():
"""
變數的演示
:return:
"""
# 建立變數
with tf.variable_scope("my_scope"):
a = tf.Variable(initial_value=50)
b = tf.Variable(initial_value=40)
with tf.variable_scope("your_scope"):
c = tf.add(a, b)
print("a:\n", a)
print("b:\n", b)
print("c:\n", c)
# 初始化變數
init = tf.global_variables_initializer()
# 開啟會話
with tf.Session() as sess:
# 執行初始化
sess.run(init)
a_value, b_value, c_value = sess.run([a, b, c])
print("a_value:\n", a_value)
print("b_value:\n", b_value)
print("c_value:\n", c_value)
5.高階API(keras)
參考地址: https://tensorflow.google.cn/guide/keras?hl=zh-cn
6.案例:線性迴歸
案例:實現線性迴歸
1 線性迴歸原理複習
1)構建模型
y = w1x1 + w2x2 + …… + wnxn + b
2)構造損失函式
均方誤差
3)最佳化損失
梯度下降
2 案例:實現線性迴歸的訓練
準備真實資料
100樣本
x 特徵值 形狀 (100, 1)
y_true 目標值 (100, 1)
y_true = 0.8x + 0.7
假定x 和 y 之間的關係 滿足
y = kx + b
k ≈ 0.8 b ≈ 0.7
流程分析:
(100, 1) * (1, 1) = (100, 1)
y_predict = x * weights(1, 1) + bias(1, 1)
1)構建模型
y_predict = tf.matmul(x, weights) + bias
2)構造損失函式
error = tf.reduce_mean(tf.square(y_predict - y_true))
3)最佳化損失
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
5 學習率的設定、步數的設定與梯度爆炸
3 增加其他功能
1 增加變數顯示
1)建立事件檔案
2)收集變數
3)合併變數
4)每次迭代執行一次合併變數
5)每次迭代將summary物件寫入事件檔案
2 增加名稱空間
3 模型的儲存與載入
saver = tf.train.Saver(var_list=None,max_to_keep=5)
1)例項化Saver
2)儲存
saver.save(sess, path)
3)載入
saver.restore(sess, path)
4 命令列引數使用
1)tf.app.flags
tf.app.flags.DEFINE_integer("max_step", 0, "訓練模型的步數")
tf.app.flags.DEFINE_string("model_dir", " ", "模型儲存的路徑+模型名字")
2)FLAGS = tf.app.flags.FLAGS
透過FLAGS.max_step呼叫命令列中傳過來的引數
3、透過tf.app.run()啟動main(argv)函
def linear_regression():
"""
自實現一個線性迴歸
:return:
"""
with tf.variable_scope("prepare_data"):
# 1)準備資料
X = tf.random_normal(shape=[100, 1], name="feature")
y_true = tf.matmul(X, [[0.8]]) + 0.7
with tf.variable_scope("create_model"):
# 2)構造模型
# 定義模型引數 用 變數
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) + bias
with tf.variable_scope("loss_function"):
# 3)構造損失函式
error = tf.reduce_mean(tf.square(y_predict - y_true))
with tf.variable_scope("optimizer"):
# 4)最佳化損失
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
# 2_收集變數
tf.summary.scalar("error", error)
tf.summary.histogram("weights", weights)
tf.summary.histogram("bias", bias)
# 3_合併變數
merged = tf.summary.merge_all()
# 建立Saver物件
saver = tf.train.Saver()
# 顯式地初始化變數
init = tf.global_variables_initializer()
# 開啟會話
with tf.Session() as sess:
# 初始化變數
sess.run(init)
# 1_建立事件檔案
file_writer = tf.summary.FileWriter("./tmp/linear", graph=sess.graph)
# 檢視初始化模型引數之後的值
print("訓練前模型引數為:權重%f,偏置%f,損失為%f" % (weights.eval(), bias.eval(), error.eval()))
# 開始訓練
# for i in range(100):
# sess.run(optimizer)
# print("第%d次訓練後模型引數為:權重%f,偏置%f,損失為%f" % (i+1, weights.eval(), bias.eval(), error.eval()))
#
# # 執行合併變數操作
# summary = sess.run(merged)
# # 將每次迭代後的變數寫入事件檔案
# file_writer.add_summary(summary, i)
#
# # 儲存模型
# if i % 10 ==0:
# saver.save(sess, "./tmp/model/my_linear.ckpt")
# 載入模型
if os.path.exists("./tmp/model/checkpoint"):
saver.restore(sess, "./tmp/model/my_linear.ckpt")
print("訓練後模型引數為:權重%f,偏置%f,損失為%f" % (weights.eval(), bias.eval(), error.eval()))
return None
def linear_regression():
"""
自實現一個線性迴歸
:return:
"""
with tf.variable_scope("prepare_data"):
# 1)準備資料
X = tf.random_normal(shape=[100, 1], name="feature")
y_true = tf.matmul(X, [[0.8]]) + 0.7
with tf.variable_scope("create_model"):
# 2)構造模型
# 定義模型引數 用 變數
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) + bias
with tf.variable_scope("loss_function"):
# 3)構造損失函式
error = tf.reduce_mean(tf.square(y_predict - y_true))
with tf.variable_scope("optimizer"):
# 4)最佳化損失
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(error)
# 2_收集變數
tf.summary.scalar("error", error)
tf.summary.histogram("weights", weights)
tf.summary.histogram("bias", bias)
# 3_合併變數
merged = tf.summary.merge_all()
# 建立Saver物件
saver = tf.train.Saver()
# 顯式地初始化變數
init = tf.global_variables_initializer()
# 開啟會話
with tf.Session() as sess:
# 初始化變數
sess.run(init)
# 1_建立事件檔案
file_writer = tf.summary.FileWriter("./tmp/linear", graph=sess.graph)
# 檢視初始化模型引數之後的值
print("訓練前模型引數為:權重%f,偏置%f,損失為%f" % (weights.eval(), bias.eval(), error.eval()))
# 開始訓練
# for i in range(100):
# sess.run(optimizer)
# print("第%d次訓練後模型引數為:權重%f,偏置%f,損失為%f" % (i+1, weights.eval(), bias.eval(), error.eval()))
#
# # 執行合併變數操作
# summary = sess.run(merged)
# # 將每次迭代後的變數寫入事件檔案
# file_writer.add_summary(summary, i)
#
# # 儲存模型
# if i % 10 ==0:
# saver.save(sess, "./tmp/model/my_linear.ckpt")
# 載入模型
if os.path.exists("./tmp/model/checkpoint"):
saver.restore(sess, "./tmp/model/my_linear.ckpt")
print("訓練後模型引數為:權重%f,偏置%f,損失為%f" % (weights.eval(), bias.eval(), error.eval()))
return None
# 1)定義命令列引數
tf.app.flags.DEFINE_integer("max_step", 100, "訓練模型的步數")
tf.app.flags.DEFINE_string("model_dir", "Unknown", "模型儲存的路徑+模型名字")
# 2)簡化變數名
FLAGS = tf.app.flags.FLAGS
def command_demo():
"""
命令列引數演示
:return:
"""
print("max_step:\n", FLAGS.max_step)
print("model_dir:\n", FLAGS.model_dir)
return None
def main(argv):
print("code start")
return None
7.檔案I/O操作
檔案讀取流程
多執行緒 + 佇列
3.1.1 檔案讀取流程
1)構造檔名佇列
file_queue = tf.train.string_input_producer(string_tensor,shuffle=True)
2)讀取與解碼
文字:
讀取:tf.TextLineReader()
解碼:tf.decode_csv()
圖片:
讀取:tf.WholeFileReader()
解碼:
tf.image.decode_jpeg(contents)
tf.image.decode_png(contents)
二進位制:
讀取:tf.FixedLengthRecordReader(record_bytes)
解碼:tf.decode_raw()
TFRecords
讀取:tf.TFRecordReader()
key, value = 讀取器.read(file_queue)
key:檔名
value:一個樣本
3)批處理佇列
tf.train.batch(tensors, batch_size, num_threads = 1, capacity = 32, name=None)
手動開啟執行緒
tf.train.QueueRunner()
開啟會話:
tf.train.start_queue_runners(sess=None, coord=None)
案例1:讀取狗圖片
圖片資料
1 影像基本知識
文字 特徵詞 -> 二維陣列
字典 one-hot -> 二維陣列
圖片 畫素值
1 圖片三要素
黑白圖、灰度圖
一個通道
黑[0, 255]白
彩色圖
三個通道
一個畫素點 三個通道值構成
R [0, 255]
G [0, 255]
B [0, 255]
2 TensorFlow中表示圖片
Tensor物件
指令名稱、形狀、型別
shape = [height, width, channel]
3 圖片特徵值處理
[samples, features]
為什麼要縮放圖片到統一大小?
1)每一個樣本特徵數量要一樣多
2)縮小圖片的大小
tf.image.resize_images(images, size)
4 資料格式
儲存:uint8
訓練:float32
狗圖片讀取
1)構造檔名佇列
file_queue = tf.train.string_input_producer(string_tensor,shuffle=True)
2)讀取與解碼
讀取:
reader = tf.WholeFileReader()
key, value = reader.read(file_queue)
解碼:
image_decoded = tf.image.decode_jpeg(value)
3)批處理佇列
image_decoded = tf.train.batch([image_decoded], 100, num_threads = 2, capacity=100)
import tensorflow as tf
import os
def read_picture():
"""
讀取狗圖片案例
:return:
"""
# 1、構造檔名佇列
# 構造檔名列表
filename_list = os.listdir("./dog")
# 給檔名加上路徑
file_list = [os.path.join("./dog/", i) for i in filename_list]
# print("file_list:\n", file_list)
# print("filename_list:\n", filename_list)
file_queue = tf.train.string_input_producer(file_list)
# 2、讀取與解碼
# 讀取
reader = tf.WholeFileReader()
key, value = reader.read(file_queue)
print("key:\n", key)
print("value:\n", value)
# 解碼
image_decoded = tf.image.decode_jpeg(value)
print("image_decoded:\n", image_decoded)
# 將圖片縮放到同一個大小
image_resized = tf.image.resize_images(image_decoded, [200, 200])
print("image_resized_before:\n", image_resized)
# 更新靜態形狀
image_resized.set_shape([200, 200, 3])
print("image_resized_after:\n", image_resized)
# 3、批處理佇列
image_batch = tf.train.batch([image_resized], batch_size=100, num_threads=2, capacity=100)
print("image_batch:\n", image_batch)
# 開啟會話
with tf.Session() as sess:
# 開啟執行緒
# 構造執行緒協調器
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 執行
filename, sample, image, n_image = sess.run([key, value, image_resized, image_batch])
print("filename:\n", filename)
print("sample:\n", sample)
print("image:\n", image)
print("n_image:\n", n_image)
coord.request_stop()
coord.join(threads)
return None
if __name__ == "__main__":
# 程式碼1:讀取狗圖片案例
read_picture()
案例2:讀取二進位制圖片
TFRecords
1 什麼是TFRecords檔案
2 Example結構解析
cifar10
特徵值 - image - 3072個位元組
目標值 - label - 1個位元組
example = tf.train.Example(features=tf.train.Features(feature={
"image":tf.train.Feature(bytes_list=tf.train. BytesList(value=[image])
"label":tf.train.Feature(int64_list=tf.train. Int64List(value=[label]))
}))
example.SerializeToString()
3 案例:CIFAR10資料存入TFRecords檔案
流程分析
4 讀取TFRecords檔案API
1)構造檔名佇列
2)讀取和解碼
讀取
解析example
feature = tf.parse_single_example(value, features={
"image":tf.FixedLenFeature([], tf.string),
"label":tf.FixedLenFeature([], tf.int64)
})
image = feature["image"]
label = feature["label"]
解碼
tf.decode_raw()
import tensorflow as tf
import os
def read_picture():
"""
讀取狗圖片案例
:return:
"""
# 1、構造檔名佇列
# 構造檔名列表
filename_list = os.listdir("./dog")
# 給檔名加上路徑
file_list = [os.path.join("./dog/", i) for i in filename_list]
# print("file_list:\n", file_list)
# print("filename_list:\n", filename_list)
file_queue = tf.train.string_input_producer(file_list)
# 2、讀取與解碼
# 讀取
reader = tf.WholeFileReader()
key, value = reader.read(file_queue)
print("key:\n", key)
print("value:\n", value)
# 解碼
image_decoded = tf.image.decode_jpeg(value)
print("image_decoded:\n", image_decoded)
# 將圖片縮放到同一個大小
image_resized = tf.image.resize_images(image_decoded, [200, 200])
print("image_resized_before:\n", image_resized)
# 更新靜態形狀
image_resized.set_shape([200, 200, 3])
print("image_resized_after:\n", image_resized)
# 3、批處理佇列
image_batch = tf.train.batch([image_resized], batch_size=100, num_threads=2, capacity=100)
print("image_batch:\n", image_batch)
# 開啟會話
with tf.Session() as sess:
# 開啟執行緒
# 構造執行緒協調器
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
# 執行
filename, sample, image, n_image = sess.run([key, value, image_resized, image_batch])
print("filename:\n", filename)
print("sample:\n", sample)
print("image:\n", image)
print("n_image:\n", n_image)
coord.request_stop()
coord.join(threads)
return None
if __name__ == "__main__":
# 程式碼1:讀取狗圖片案例
read_picture()
案例3:全連線對手寫數字進行識別
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
def full_connection():
"""
用全連線對手寫數字進行識別
:return:
"""
# 1)準備資料
mnist = input_data.read_data_sets("./mnist_data", one_hot=True)
# 用佔位符定義真實資料
X = tf.placeholder(dtype=tf.float32, shape=[None, 784])
y_true = tf.placeholder(dtype=tf.float32, shape=[None, 10])
# 2)構造模型 - 全連線
# [None, 784] * W[784, 10] + Bias = [None, 10]
weights = tf.Variable(initial_value=tf.random_normal(shape=[784, 10], stddev=0.01))
bias = tf.Variable(initial_value=tf.random_normal(shape=[10], stddev=0.1))
y_predict = tf.matmul(X, weights) + bias
# 3)構造損失函式
loss_list = tf.nn.softmax_cross_entropy_with_logits(logits=y_predict, labels=y_true)
loss = tf.reduce_mean(loss_list)
# 4)最佳化損失
# optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss)
optimizer = tf.train.AdamOptimizer(learning_rate=0.01).minimize(loss)
# 5)增加準確率計算
bool_list = tf.equal(tf.argmax(y_true, axis=1), tf.argmax(y_predict, axis=1))
accuracy = tf.reduce_mean(tf.cast(bool_list, tf.float32))
# 初始化變數
init = tf.global_variables_initializer()
# 開啟會話
with tf.Session() as sess:
# 初始化變數
sess.run(init)
# 開始訓練
for i in range(5000):
# 獲取真實值
image, label = mnist.train.next_batch(500)
_, loss_value, accuracy_value = sess.run([optimizer, loss, accuracy], feed_dict={X: image, y_true: label})
print("第%d次的損失為%f,準確率為%f" % (i+1, loss_value, accuracy_value))
return None
if __name__ == "__main__":
full_connection()
二、神經網路
神經網路
輸入層
特徵值和權重 線性加權
y = w1x1 + w2x2 + …… + wnxn + b
細胞核-啟用函式
sigmoid
sign
隱藏層
輸出層
單個神經元 - 感知機
感知機(PLA: Perceptron Learning Algorithm))
x1, x2
w1x1 + w2x2 + b = 常數
w2x2 = -w1x1 - b + 常數
x2 = kx1 + b
x2 = kx1 + b
x1 x2
與問題
0 0 0
0 1 0
1 0 0
1 1 1
異或問題
0 0 0
0 1 1
1 0 1
1 1 0
單個神經元不能解決一些複雜問題
1)多層神經元
2)增加啟用函式
案例:全連線對手寫數字進行識別
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
def full_connection():
"""
用全連線對手寫數字進行識別
:return:
"""
# 1)準備資料
mnist = input_data.read_data_sets("./mnist_data", one_hot=True)
# 用佔位符定義真實資料
X = tf.placeholder(dtype=tf.float32, shape=[None, 784])
y_true = tf.placeholder(dtype=tf.float32, shape=[None, 10])
# 2)構造模型 - 全連線
# [None, 784] * W[784, 10] + Bias = [None, 10]
weights = tf.Variable(initial_value=tf.random_normal(shape=[784, 10], stddev=0.01))
bias = tf.Variable(initial_value=tf.random_normal(shape=[10], stddev=0.1))
y_predict = tf.matmul(X, weights) + bias
# 3)構造損失函式
loss_list = tf.nn.softmax_cross_entropy_with_logits(logits=y_predict, labels=y_true)
loss = tf.reduce_mean(loss_list)
# 4)最佳化損失
# optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01).minimize(loss)
optimizer = tf.train.AdamOptimizer(learning_rate=0.01).minimize(loss)
# 5)增加準確率計算
bool_list = tf.equal(tf.argmax(y_true, axis=1), tf.argmax(y_predict, axis=1))
accuracy = tf.reduce_mean(tf.cast(bool_list, tf.float32))
# 初始化變數
init = tf.global_variables_initializer()
# 開啟會話
with tf.Session() as sess:
# 初始化變數
sess.run(init)
# 開始訓練
for i in range(5000):
# 獲取真實值
image, label = mnist.train.next_batch(500)
_, loss_value, accuracy_value = sess.run([optimizer, loss, accuracy], feed_dict={X: image, y_true: label})
print("第%d次的損失為%f,準確率為%f" % (i+1, loss_value, accuracy_value))
return None
if __name__ == "__main__":
full_connection()
案例:讀取檔案
import pandas as pd
name = ["file_num", "chars"]
data = pd.read_csv("./GenPics/labels.csv", names=name, index_col="file_num")
labels = []
for label in data["chars"]:
tmp = []
for letter in label:
tmp.append(ord(letter) - ord("A"))
labels.append(tmp)
data["labels"] = labels
案例:mnist手寫數字資料在執行時候實時提供給給佔位符
import tensorflow as tf
import os
from tensorflow.examples.tutorials.mnist import input_data
from tensorflow.contrib.slim.python.slim.nets.inception_v3 import inception_v3_base
# 1、利用資料,在訓練的時候實時提供資料
# mnist手寫數字資料在執行時候實時提供給給佔位符
tf.app.flags.DEFINE_integer("is_train", 1, "指定是否是訓練模型,還是拿資料去預測")
FLAGS = tf.app.flags.FLAGS
def create_weights(shape):
return tf.Variable(initial_value=tf.random_normal(shape=shape, stddev=0.01))
def create_model(x):
"""
構建卷積神經網路
:param x:
:return:
"""
# 1)第一個卷積大層
with tf.variable_scope("conv1"):
# 卷積層
# 將x[None, 784]形狀進行修改
input_x = tf.reshape(x, shape=[-1, 28, 28, 1])
# 定義filter和偏置
conv1_weights = create_weights(shape=[5, 5, 1, 32])
conv1_bias = create_weights(shape=[32])
conv1_x = tf.nn.conv2d(input=input_x, filter=conv1_weights, strides=[1, 1, 1, 1], padding="SAME") + conv1_bias
# 啟用層
relu1_x = tf.nn.relu(conv1_x)
# 池化層
pool1_x = tf.nn.max_pool(value=relu1_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 2)第二個卷積大層
with tf.variable_scope("conv2"):
# 卷積層
# 定義filter和偏置
conv2_weights = create_weights(shape=[5, 5, 32, 64])
conv2_bias = create_weights(shape=[64])
conv2_x = tf.nn.conv2d(input=pool1_x, filter=conv2_weights, strides=[1, 1, 1, 1], padding="SAME") + conv2_bias
# 啟用層
relu2_x = tf.nn.relu(conv2_x)
# 池化層
pool2_x = tf.nn.max_pool(value=relu2_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 3)全連線層
with tf.variable_scope("full_connection"):
# [None, 7, 7, 64]->[None, 7 * 7 * 64]
# [None, 7 * 7 * 64] * [7 * 7 * 64, 10] = [None, 10]
x_fc = tf.reshape(pool2_x, shape=[-1, 7 * 7 * 64])
weights_fc = create_weights(shape=[7 * 7 * 64, 10])
bias_fc = create_weights(shape=[10])
y_predict = tf.matmul(x_fc, weights_fc) + bias_fc
return y_predict
def full_connected_mnist():
"""
單層全連線神經網路識別手寫數字圖片
特徵值:[None, 784]
目標值:one_hot編碼 [None, 10]
:return:
"""
mnist = input_data.read_data_sets("./mnist_data/", one_hot=True)
# 1、準備資料
# x [None, 784] y_true [None. 10]
with tf.variable_scope("mnist_data"):
x = tf.placeholder(tf.float32, [None, 784])
y_true = tf.placeholder(tf.int32, [None, 10])
y_predict = create_model(x)
# 3、softmax迴歸以及交叉熵損失計算
with tf.variable_scope("softmax_crossentropy"):
# labels:真實值 [None, 10] one_hot
# logits:全臉層的輸出[None,10]
# 返回每個樣本的損失組成的列表
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_true, logits=y_predict))
# 4、梯度下降損失最佳化
with tf.variable_scope("optimizer"):
# 學習率
train_op = tf.train.AdamOptimizer(0.001).minimize(loss)
# 5、得出每次訓練的準確率(透過真實值和預測值進行位置比較,每個樣本都比較)
with tf.variable_scope("accuracy"):
equal_list = tf.equal(tf.argmax(y_true, 1), tf.argmax(y_predict, 1))
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
# (2)收集要顯示的變數
# 先收集損失和準確率
tf.summary.scalar("losses", loss)
tf.summary.scalar("acc", accuracy)
# 初始化變數op
init_op = tf.global_variables_initializer()
# (3)合併所有變數op
merged = tf.summary.merge_all()
# 建立模型儲存和載入
saver = tf.train.Saver()
# 開啟會話去訓練
with tf.Session() as sess:
# 初始化變數
sess.run(init_op)
# (1)建立一個events檔案例項
file_writer = tf.summary.FileWriter("./tmp/summary/", graph=sess.graph)
# 載入模型
# if os.path.exists("./tmp/modelckpt/checkpoint"):
# saver.restore(sess, "./tmp/modelckpt/fc_nn_model")
if FLAGS.is_train == 1:
# 迴圈步數去訓練
for i in range(3000):
# 獲取資料,實時提供
# 每步提供50個樣本訓練
mnist_x, mnist_y = mnist.train.next_batch(50)
# 執行訓練op
sess.run(train_op, feed_dict={x: mnist_x, y_true: mnist_y})
print("訓練第%d步的準確率為:%f, 損失為:%f " % (i+1,
sess.run(accuracy, feed_dict={x: mnist_x, y_true: mnist_y}),
sess.run(loss, feed_dict={x: mnist_x, y_true: mnist_y})
)
)
# 執行合變數op,寫入事件檔案當中
summary = sess.run(merged, feed_dict={x: mnist_x, y_true: mnist_y})
file_writer.add_summary(summary, i)
# if i % 100 == 0:
# saver.save(sess, "./tmp/modelckpt/fc_nn_model")
else:
# 如果不是訓練,我們就去進行預測測試集資料
for i in range(100):
# 每次拿一個樣本預測
mnist_x, mnist_y = mnist.test.next_batch(1)
print("第%d個樣本的真實值為:%d, 模型預測結果為:%d" % (
i+1,
tf.argmax(sess.run(y_true, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval(),
tf.argmax(sess.run(y_predict, feed_dict={x: mnist_x, y_true: mnist_y}), 1).eval()
)
)
return None
if __name__ == "__main__":
full_connected_mnist()
案例:驗證碼圖片識別
import tensorflow as tf
import glob
import pandas as pd
import numpy as np
# 1)讀取圖片資料filename -> 標籤值
def read_picture():
"""
讀取驗證碼圖片
:return:
"""
# 1、構造檔名佇列
file_list = glob.glob("./GenPics/*.jpg")
# print("file_list:\n", file_list)
file_queue = tf.train.string_input_producer(file_list)
# 2、讀取與解碼
# 讀取
reader = tf.WholeFileReader()
filename, image = reader.read(file_queue)
# 解碼
image_decode = tf.image.decode_jpeg(image)
# 更新圖片形狀
image_decode.set_shape([20, 80, 3])
# print("image_decode:\n", image_decode)
# 修改圖片型別
image_cast = tf.cast(image_decode, tf.float32)
# 3、構造批處理佇列
filename_batch, image_batch = tf.train.batch([filename, image_cast], batch_size=100, num_threads=2, capacity=100)
return filename_batch, image_batch
# 2)解析csv檔案,將標籤值NZPP->[13, 25, 15, 15]
def parse_csv():
# 解析CSV檔案, 建立檔名和標籤值對應表格
csv_data = pd.read_csv("./GenPics/labels.csv", names=["file_num", "chars"], index_col="file_num")
labels = []
for label in csv_data["chars"]:
tmp = []
for letter in label:
tmp.append(ord(letter) - ord("A"))
labels.append(tmp)
csv_data["labels"] = labels
return csv_data
# 3)將filename和標籤值聯絡起來
def filename2label(filenames, csv_data):
"""
將filename和標籤值聯絡起來
:param filenames:
:param csv_data:
:return:
"""
labels = []
# 將b'檔名中的數字提取出來並索引相應的標籤值
for filename in filenames:
digit_str = "".join(list(filter(str.isdigit, str(filename))))
label = csv_data.loc[int(digit_str), "labels"]
labels.append(label)
# print("labels:\n", labels)
return np.array(labels)
# 4)構建卷積神經網路->y_predict
def create_weights(shape):
return tf.Variable(initial_value=tf.random_normal(shape=shape, stddev=0.01))
def create_model(x):
"""
構建卷積神經網路
:param x:[None, 20, 80, 3]
:return:
"""
# 1)第一個卷積大層
with tf.variable_scope("conv1"):
# 卷積層
# 定義filter和偏置
conv1_weights = create_weights(shape=[5, 5, 3, 32])
conv1_bias = create_weights(shape=[32])
conv1_x = tf.nn.conv2d(input=x, filter=conv1_weights, strides=[1, 1, 1, 1], padding="SAME") + conv1_bias
# 啟用層
relu1_x = tf.nn.relu(conv1_x)
# 池化層
pool1_x = tf.nn.max_pool(value=relu1_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 2)第二個卷積大層
with tf.variable_scope("conv2"):
# [None, 20, 80, 3] --> [None, 10, 40, 32]
# 卷積層
# 定義filter和偏置
conv2_weights = create_weights(shape=[5, 5, 32, 64])
conv2_bias = create_weights(shape=[64])
conv2_x = tf.nn.conv2d(input=pool1_x, filter=conv2_weights, strides=[1, 1, 1, 1], padding="SAME") + conv2_bias
# 啟用層
relu2_x = tf.nn.relu(conv2_x)
# 池化層
pool2_x = tf.nn.max_pool(value=relu2_x, ksize=[1, 2, 2, 1], strides=[1, 2, 2, 1], padding="SAME")
# 3)全連線層
with tf.variable_scope("full_connection"):
# [None, 10, 40, 32] -> [None, 5, 20, 64]
# [None, 5, 20, 64] -> [None, 5 * 20 * 64]
# [None, 5 * 20 * 64] * [5 * 20 * 64, 4 * 26] = [None, 4 * 26]
x_fc = tf.reshape(pool2_x, shape=[-1, 5 * 20 * 64])
weights_fc = create_weights(shape=[5 * 20 * 64, 4 * 26])
bias_fc = create_weights(shape=[104])
y_predict = tf.matmul(x_fc, weights_fc) + bias_fc
return y_predict
# 5)構造損失函式
# 6)最佳化損失
# 7)計算準確率
# 8)開啟會話、開啟執行緒
if __name__ == "__main__":
filename, image = read_picture()
csv_data = parse_csv()
# 1、準備資料
x = tf.placeholder(tf.float32, shape=[None, 20, 80, 3])
y_true = tf.placeholder(tf.float32, shape=[None, 4*26])
# 2、構建模型
y_predict = create_model(x)
# 3、構造損失函式
loss_list = tf.nn.sigmoid_cross_entropy_with_logits(labels=y_true, logits=y_predict)
loss = tf.reduce_mean(loss_list)
# 4、最佳化損失
optimizer = tf.train.AdamOptimizer(learning_rate=0.001).minimize(loss)
# 5、計算準確率
equal_list = tf.reduce_all(
tf.equal(tf.argmax(tf.reshape(y_predict, shape=[-1, 4, 26]), axis=2),
tf.argmax(tf.reshape(y_true, shape=[-1, 4, 26]), axis=2)), axis=1)
accuracy = tf.reduce_mean(tf.cast(equal_list, tf.float32))
# 初始化變數
init = tf.global_variables_initializer()
# 開啟會話
with tf.Session() as sess:
# 初始化變數
sess.run(init)
# 開啟執行緒
coord = tf.train.Coordinator()
threads = tf.train.start_queue_runners(sess=sess, coord=coord)
for i in range(1000):
filename_value, image_value = sess.run([filename, image])
# print("filename_value:\n", filename_value)
# print("image_value:\n", image_value)
labels = filename2label(filename_value, csv_data)
# 將標籤值轉換成one-hot
labels_value = tf.reshape(tf.one_hot(labels, depth=26), [-1, 4*26]).eval()
_, error, accuracy_value = sess.run([optimizer, loss, accuracy], feed_dict={x: image_value, y_true: labels_value})
print("第%d次訓練後損失為%f,準確率為%f" % (i+1, error, accuracy_value))
# 回收執行緒
coord.request_stop()
coord.join(threads)
案例:使用keras分類
import numpy as np
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
# 生成模擬資料集
# 假設我們有兩個類別的資料,每個類別有50個樣本
# 類別0的資料特徵圍繞點(2, 2)
# 類別1的資料特徵圍繞點(6, 6)
np.random.seed(0) # 確保每次執行生成的資料都是一樣的
num_samples_per_class = 50
# 生成類別0的資料
class_0_points = np.random.multivariate_normal(mean=[2, 2], cov=[[1, 0.5], [0.5, 1]], size=num_samples_per_class)
class_0_labels = np.zeros(shape=num_samples_per_class)
# 生成類別1的資料
class_1_points = np.random.multivariate_normal(mean=[6, 6], cov=[[1, 0.5], [0.5, 1]], size=num_samples_per_class)
class_1_labels = np.ones(shape=num_samples_per_class)
# 合併資料
points = np.vstack([class_0_points, class_1_points])
labels = np.hstack([class_0_labels, class_1_labels])
# 打亂資料
indices = np.arange(points.shape[0])
np.random.shuffle(indices)
points = points[indices]
labels = labels[indices]
# 定義模型
model = keras.Sequential([
layers.Dense(units=5, activation='relu', input_shape=(2,)),
layers.Dense(units=1, activation='sigmoid')
])
# 編譯模型
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
# 訓練模型
model.fit(points, labels, epochs=50, batch_size=10)
# 評估模型
loss, accuracy = model.evaluate(points, labels)
print(f"模型評估結果 - 損失: {loss}, 準確率: {accuracy}")
# 使用模型進行預測
predictions = model.predict(points)
predictions = (predictions > 0.5) # 將預測結果轉換為0或1
# 列印前幾個預測結果和真實標籤
print("預測結果和真實標籤:")
for i in range(10):
print(f"預測: {int(predictions[i])}, 真實標籤: {int(labels[i])}")