tensorflow基礎版

派森的猫發表於2024-07-27

目錄
  • 一、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])}")

相關文章