Tensorflow知識點總結(三)

大部分內容整理自《Tensorflow實戰Google深度學習框架》

在前面計算圖、張量、會話、Tensorflow遊樂場的基礎上轉到神經網絡,MLP的神經元,層數,參數之前已經瞭解。從Tensorflow遊樂場模型上課看出,使用神經網絡解決分類問題主要分爲以下4個步驟:

1.提取問題中實現實體的特徵向量作爲神經網絡的輸入,不同的實體可以提取不同的特徵向量。

2.定義神經網絡的結構,並定義如何從神經網絡的輸入得到輸出,這個過程就是神經網絡的前向傳播算法。輸出就是所有輸入的加權和。

3.通過訓練數據來調整神經網絡中參數的值,不同輸入的權重就是我們要調節的參數

4.使用訓練好的數據預測未知的數據

如下是用tensorflow通過變量實現神經網絡的參數並實現前向傳播的過程:

import tensorflow as tf
w1=tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1),name="w1")
w2=tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1),name="w2")
x=tf.constant([[0.7, 0.9]])
a=tf.matmul(x, w1)
y=tf.matmul(a, w2)

sess = tf.Session()
sess.run(w1.initializer)
sess.run(w1.initializer)
print(sess.run(y))
sess.close()

這裏變量初始化也可以如下方式(上面是直接調用每個變量的初始化過程,但是當變量數目增多,變量之間存在依賴關係時,單個的調用方法就麻煩了):

import tensorflow as tf

tf.reset_default_graph()
w1=tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1),name="w1")
w2=tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1),name="w2")
x=tf.constant([[0.7, 0.9]])
a=tf.matmul(x, w1)
y=tf.matmul(a, w2)
init_op=tf.initialize_all_variables()

with tf.Session() as sess:
    sess.run(init_op)
    print(sess.run(y))
    writer = tf.summary.FileWriter("D://tensorflow-log//test_tensorboard2", tf.get_default_graph())
    writer.close()
    """
    輸出所有的變量
    """
    for i in tf.trainable_variables():
        print(i)
    """
    對所屬的計算圖進行輸出,可以發現使用變量、常數、操作、以及默認圖進行的輸出結果是一樣的
    """
    print(tf.get_default_graph())
    print(a.graph)##可以直接使用某一個操作
    print(w1.graph)
    print(x.graph)
    """
    對張量進行輸出
    """
    print(tf.get_default_graph().get_tensor_by_name("w1:0")) ##合理

 類似張量,維度(shape)和類型(type)是變量的最重要兩個屬性,構建後類型不可以改變,維度可以改變,如下會報錯:

w1=tf.Variable(tf.random_normal([2,3],stddev=1),name="w1")
w2=tf.Variable(tf.random_normal([2,3],dtype=tf.float64,stddev=1),name="w2")
w1.assign(w2)

如下可以成功執行,前提是validate_shape=False選項要加上

w1=tf.Variable(tf.random_normal([2,3],stddev=1),name="w1")
w2=tf.Variable(tf.random_normal([2,2],stddev=1),name="w2")
tf.assign(w1,w2,validate_shape=False)

設置神經網絡參數的過程就是神經網絡訓練的過程,在神經網絡的優化算法中最常用的方法是反向傳播算法,在每次迭代開始先選取一小部分訓練數據,這一小部分數據叫做一個batch, 可以計算出當前神經網絡模型的預測答案與正確答案之間的差距。基於這個預測值和真實值之間的差距,去更新神經網絡的參數。

如下是placeholfer機制的使用案例:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Icecream.Shao
import tensorflow as tf

tf.reset_default_graph()
w1=tf.Variable(tf.random_normal([2, 3], stddev=1, seed=1),name="w1")
w2=tf.Variable(tf.random_normal([3, 1], stddev=1, seed=1),name="w2")
x=tf.placeholder(tf.float32,shape=(1,2),name="input")
a=tf.matmul(x, w1)
y=tf.matmul(a, w2)

sess=tf.Session()
init_op=tf.initialize_all_variables()
sess.run(init_op)
print(sess.run(y,feed_dict={x:[[0.7,0.9]]}))

然後第3章裏示例了一個完整的樣例

batch size爲8,128個樣本,用了placeholder,定義了前向傳播算法(只有一層隱藏層),並沒有加入激活函數和偏置項,訓練了5000次,定義了損失函數。可以認爲是一個線性的神經網絡

接着講用激活函數實現去線性化(加上激活函數和偏置項),激活函數有ReLU, Sigmoid,tanh函數

接着重點講解了損失函數,提到了交叉熵是常用的評判方法之一。softmax迴歸將神經網絡的輸出變成一個概率分佈。

                                                                            

有了求出的概率分佈後,容易計算出交叉熵,公式爲:

                                                                     

假設某個樣本的正確答案是(1,0,0)

經softmax迴歸之後的預測答案是(0.5,0.4,0.1),那麼交叉熵爲:

H((1,0,0),(0.5,0.4,0.1))=-(1*log0.5+0*log0.4+0*log0.1)~0.3

tf.clip_by_value函數可以限制張量中的數值限制在一個範圍內,可以避免一些運算錯誤,比如log0.

tf.mean函數可以求平均值,求得一個batch平均交叉熵。

tensorflow提供tf.nn.softmax_cross_entropy_with_logits(y,y_)做了封裝,來計算該batch迴歸之後的交叉熵。

又介紹瞭解決迴歸問題最常用的損失函數均方誤差

                                                            

除了以上介紹的兩個函數外,還可以自定義其它損失函數

接下來重點介紹了神經網絡的優化算法,

(1)用梯度下降算法調整神經網絡中的參數取值

假設初始值爲5,學習率0.3,梯度下降算法優化函數(損失函數的大小)J(x)=x^2

輪數 當前輪參數值 梯度*學習率 更新後參數值
1 5 2*5*0.3=3 5-3=2
2 2 2*2*0.3=1.2 2-1.2=0.8
3 0.8 2*0.8*0.3=0.48 0.8-0.48=0.32
4 0.32 2*0.32*0.3=0.192 0.32-0.192=0.128
5 0.128 2*0.128*0.3=0.0768 0.128-0.0768=0.0512

 

梯度下降算法並不能保證被優化函數達到全局最優,只有當損失函數爲凸函數時,梯度下降算法才能保證達到全局最優解

一般會綜合梯度下降算法和隨機梯度下降算法,

(2)學習率(初始學習率,衰減係數和衰減速度)

(3)正則化(在損失函數中加入刻畫模型複雜程度的指標),L1正則化和L2正則化

w=tf.Variable(tf.random_normal([2,1], stddev=1,seed=1))
y=tf.matmul(x,w)
loss=tf.reduce_mean(tf.square(y_-y))+tf.contrib.layers.l2_regularizer(lambda )(w)

這邊的損失函數由兩部分組成,第一個部分是均方差損失函數,第二個部分是正則化

可以使用tensorflow中提供的集合collection來計算損失函數

mse_loss=tf.reduce_mean(tf.square(y_ - cur_layer))
tf.add_to_collection('losses',mse_loss)
loss = tf.add_n(tf.get_collection('losses'))

最後介紹了滑動平均模型tf.train.ExponentialMovingAverage()

shadow_variable函數爲影子變量,variable爲代更新的變量,decay爲衰減率。

接下來介紹了Mnist數據集,然後給出結合以上所有優化手段訓練只有一個隱藏層的神經網絡MLP

結論:在神經網絡結構的設計上,需要使用激活函數和多層隱藏層,在神經網絡優化時,可以使用指數衰減學習率,加入正則化損失函數,滑動平均模型。由於在MNIST,模型收斂速度很快。

使用所有優化,不用滑動平均,不用正則化,不同指數衰減學習率的正確率到98%多

不用隱藏層,不用激活函數時,只能到92%

接下來講了變量管理。當tf.variable_scope函數使用參數reuse=True生成上下文管理器時,這個上下文管理器內所有的tf.get_variable函數會直接獲取已經創建的變量。如果變量不存在,就會報錯。

當tf.variable_scope函數使用參數reuse=False生成上下文管理器時,tf.get_variable操作將創建新的變量。如果同名的變量已經存在,則tf.get_variable函數將報錯。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Icecream.Shao
import tensorflow as tf
with tf.variable_scope("foo"):
    v=tf.get_variable("v",[1],initializer=tf.constant_initializer(1.0))

#如下語句
with tf.variable_scope("foo"):
    v=tf.get_variable("v",[1])

with tf.variable_scope("foo",reuse=True):
    v1 = tf.get_variable("v",[1])
    print(v==v1)

#如下語句會報錯
with tf.variable_scope("bar",reuse=True):
    v=tf.get_variable("v",[1])

tf.variable_scope函數除了可以控制tf.get_variable執行的功能之外,這個函數也提供了一個管理變量命名空間的方式。

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Icecream.Shao
import tensorflow as tf
v1=tf.get_variable("v",[1])
print(v1.name)

with tf.variable_scope("foo"):
    v2=tf.get_variable("v",[1])
    print(v2.name)

with tf.variable_scope("foo"):
    with tf.variable_scope("bar"):
        v3=tf.get_variable("v",[1])
        print(v3.name)

    v4 = tf.get_variable("v1",[1])
    print(v4.name)

with tf.variable_scope("",reuse=True):
    v5=tf.get_variable("foo/bar/v")
    print(v5==v3)

    v6=tf.get_variable("foo/v1")
    print(v6==v4)

with tf.Session() as sess:
    #sess.run(tf.global_variables_initializer())
    tf.initialize_all_variables().run()
    print("v1: ", v1.eval())
    print("v2: ", v2.eval())
    print("v3: ", v3.eval())

    print("v4: ", v4.eval())
    print("v5: ", v5.eval())
    print("v6: ", v6.eval())

結果爲:v1:  [-0.61839104]
v2:  [0.03291154]
v3:  [0.9467553]
v4:  [-0.49030578]
v5:  [0.9467553]
v6:  [-0.49030578]

 

接下來講了模型持久化,tf.train.Saver()會保存運行tensorflow程序所需要的的全部信息

結合變量管理機制和tensorflow模型持久化機制,介紹了一個tensorflow訓練神經網絡的最佳實踐,將訓練和測試分爲兩個獨立的程序,有三個程序mnist_inference.py, mnist_train.py,mnist_eval.py

mnisy_inference.py程序如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Icecream.Shao
# -*- coding: utf-8 -*-
import tensorflow as tf

# 定義神經網絡結構相關的參數
INPUT_NODE = 784
OUTPUT_NODE = 10
LAYER1_NODE = 500

# 通過tf.get_variable函數來獲取變量。在訓練神經網絡時會創建這些變量;在測試時會通
# 過保存的模型加載這些變量的取值。而且更加方便的是,因爲可以在變量加載時將滑動平均變
# 量重命名,所以可以直接通過相同的名字在訓練時使用變量自身,而在測試時使用變量的滑動
# 平均值。在這個函數中也會將變量的正則化損失加入到損失集合。
def get_weight_variable(shape, regularizer):
    weights = tf.get_variable(
        "weights", shape,
        initializer=tf.truncated_normal_initializer(stddev=0.1)
    )
    # 當給出了正則化生成函數時,將當前變量的正則化損失加入名字爲losses的集合。在這裏
    # 使用了add_to_collection函數將一個張量加入一個集合,而這個集合的名稱爲losses。
    # 這是自定義的集合,不在TensorFlow自動管理的集合列表中。
    if regularizer != None:
        tf.add_to_collection('losses', regularizer(weights))
    return weights

# 定義神經網絡的前向傳播過程
def inference(input_tensor, regularizer):
    # 聲明第一層神經網絡的變量並完成前向傳播過程。
    with tf.variable_scope('layer1'):
        # 這裏通過tf.get_variable或者tf.Variable沒有本質區別,因爲在訓練或者測試
        # 中沒有在同一個程序中多次調用這個函數。如果在同一個程序中多次調用,在第一次
        # 調用之後需要將reuse參數設置爲True。
        weights = get_weight_variable(
            [INPUT_NODE, LAYER1_NODE], regularizer
        )
        biases = tf.get_variable(
            "biases", [LAYER1_NODE],
            initializer=tf.constant_initializer(0.0)
        )
        layer1 = tf.nn.relu(tf.matmul(input_tensor, weights)+biases)

    # 類似的聲明第二層神經網絡的變量並完成前向傳播過程。
    with tf.variable_scope('layer2'):
        weights = get_weight_variable(
            [LAYER1_NODE, OUTPUT_NODE], regularizer
        )
        biases = tf.get_variable(
            "biases", [OUTPUT_NODE],
            initializer=tf.constant_initializer(0.0)
        )
        layer2 = tf.matmul(layer1, weights) + biases

    # 返回最後前向傳播的結果
    return layer2

mnist_train.py程序如下:

# -*- coding: utf-8 -*-
import os

import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 加載mnist_inference.py中定義的常量和前向傳播的函數。
import mnist_inference

# 配置神經網絡的參數。
BATCH_SIZE = 100
LEARNING_RATE_BASE = 0.8
LEARNING_RATE_DECAY = 0.99
REGULARIZATION_RATE = 0.0001
TRAINING_STEPS = 10000
MOVING_AVERAGE_DECAY = 0.99

# 模型保存的路徑和文件名
MODEL_SAVE_PATH = "./model/"
MODEL_NAME = "model.ckpt"

def train(mnist):
    # 定義輸入輸出placeholder。
    x = tf.placeholder(tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input')
    y_ = tf.placeholder(tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input')

    regularizer = tf.contrib.layers.l2_regularizer(REGULARIZATION_RATE)
    # 直接使用mnist_inference.py中定義的前向傳播過程
    y = mnist_inference.inference(x, regularizer)


    global_step = tf.Variable(0, trainable=False)

    # 定義損失函數、學習率、滑動平均操作以及訓練過程
    variable_averages = tf.train.ExponentialMovingAverage(
        MOVING_AVERAGE_DECAY, global_step
    )
    variable_averages_op = variable_averages.apply(
        tf.trainable_variables()
    )
    cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
        logits=y, labels=tf.argmax(y_, 1)
    )
    cross_entropy_mean = tf.reduce_mean(cross_entropy)
    loss = cross_entropy_mean + tf.add_n(tf.get_collection('losses'))
    learning_rate = tf.train.exponential_decay(
        LEARNING_RATE_BASE,
        global_step,
        mnist.train.num_examples / BATCH_SIZE,
        LEARNING_RATE_DECAY
    )
    train_step = tf.train.GradientDescentOptimizer(learning_rate)\
                   .minimize(loss, global_step=global_step)
    with tf.control_dependencies([train_step, variable_averages_op]):
        train_op = tf.no_op(name='train')

    # 初始化TensorFlow持久化類

    saver = tf.train.Saver()
    writer = tf.summary.FileWriter("D:\\tensorflow-log\\test_mlp_true_net", tf.get_default_graph())
    writer.close()
    with tf.Session() as sess:
        tf.global_variables_initializer().run()

        # 在訓練過程中不再測試模型在驗證數據上的表現,驗證和測試的過程將會有一個獨
        # 立的程序來完成。
        for i in range(TRAINING_STEPS):
            xs, ys = mnist.train.next_batch(BATCH_SIZE)
            _, loss_value, step = sess.run([train_op, loss, global_step],
                                           feed_dict={x: xs, y_: ys})
            # 每1000輪保存一次模型
            if i % 1000 == 0:
                # 輸出當前的訓練情況。這裏只輸出了模型在當前訓練batch上的損失
                # 函數大小。通過損失函數的大小可以大概瞭解訓練的情況。在驗證數
                # 據集上正確率的信息會有一個單獨的程序來生成
                print("After %d training step(s), loss on training "
                      "batch is %g." % (step, loss_value))
                # 保存當前的模型。注意這裏給出了global_step參數,這樣可以讓每個
                # 被保存的模型的文件名末尾加上訓練的輪數,比如“model.ckpt-1000”,
                # 表示訓練1000輪之後得到的模型。
                saver.save(
                    sess, os.path.join(MODEL_SAVE_PATH, MODEL_NAME),
                    global_step=global_step
                )
        # 將當前的計算圖輸出到TensorBoard日誌文件。


def main(argv=None):
    mnist = input_data.read_data_sets("./data", one_hot=True)
    train(mnist)

if __name__ == "__main__":
    tf.app.run()

mnist_eval.py程序如下:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
# author:Icecream.Shao
import time
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data

# 加載mnist_inference.py 和mnist_train.py中定義的常量和函數。
import mnist_inference
import mnist_train

# 每10秒加載一次最新的模型,並且在測試數據上測試最新模型的正確率
EVAL_INTERVAL_SECS = 10

def evaluate(mnist):
    with tf.Graph().as_default() as g:
        # 定義輸入輸出的格式。
        x = tf.placeholder(
            tf.float32, [None, mnist_inference.INPUT_NODE], name='x-input'
        )
        y_ = tf.placeholder(
            tf.float32, [None, mnist_inference.OUTPUT_NODE], name='y-input'
        )
        validate_feed = {x: mnist.validation.images,
                         y_: mnist.validation.labels}

        # 直接通過調用封裝好的函數來計算前向傳播的結果。因爲測試時不關注ze正則化損失的值
        # 所以這裏用於計算正則化損失的函數被設置爲None。
        y = mnist_inference.inference(x, None)

        # 使用前向傳播的結果計算正確率。如果需要對未知的樣例進行分類,那麼使用
        # tf.argmax(y,1)就可以得到輸入樣例的預測類別了。
        correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_, 1))
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

        # 通過變量重命名的方式來加載模型,這樣在前向傳播的過程中就不需要調用求滑動平均
        # 的函數來獲取平均值了。這樣就可以完全共用mnist_inference.py中定義的
        # 前向傳播過程。
        variable_averages = tf.train.ExponentialMovingAverage(
            mnist_train.MOVING_AVERAGE_DECAY
        )
        variables_to_restore = variable_averages.variables_to_restore()
        saver = tf.train.Saver(variables_to_restore)

        # 每隔EVAL_INTERVAL_SECS秒調用一次計算正確率的過程以檢驗訓練過程中正確率的
        # 變化。
        while True:
            with tf.Session() as sess:
                # tf.train.get_checkpoint_state函數會通過checkpoint文件自動
                # 找到目錄中最新模型的文件名。
                ckpt = tf.train.get_checkpoint_state(
                    mnist_train.MODEL_SAVE_PATH
                )
                if ckpt and ckpt.model_checkpoint_path:
                    # 加載模型。
                    saver.restore(sess, ckpt.model_checkpoint_path)
                    # 通過文件名得到模型保存時迭代的輪數。
                    global_step = ckpt.model_checkpoint_path\
                                      .split('/')[-1].split('-')[-1]
                    accuracy_score = sess.run(accuracy,
                                              feed_dict=validate_feed)
                    print("After %s training step(s), validation "
                          "accuracy = %g" % (global_step, accuracy_score))
                else:
                    print("No checkpoint file found")
                    return
            time.sleep(EVAL_INTERVAL_SECS)

def main(argv=None):
    mnist = input_data.read_data_sets("./data", one_hot=True)
    evaluate(mnist)

if __name__ == "__main__":
    tf.app.run()

卷積神經網絡能夠很好的利用圖像的結構信息,在全連接神經網絡中,每相鄰兩層之間的節點都有邊相連,對於卷積神經網絡,相鄰兩層之間只有部分節點相連。tensorflow訓練一個卷積神經網絡和全連接神經網絡沒有任何區別。對於mnist數據集,假設用全連接神經網絡,每一張圖片的大小爲28*28*1,所以輸入有28*28*1個節點,假設第一層隱藏層的節點數爲500個,那麼一個全連接神經網絡有28*28*500+500個參數。假設是cifar-10圖像,大小爲32*32*3,則輸入層有32*32*3個節點,假設隱藏層有500個節點,則有32*32*3*500+500~150萬個參數。

CNN主要有三大特色,分別是局部感知、權重共享和多卷積核

局部感知就是所說的感受野,實際上就是卷積核和圖像卷積的時候,每次卷積核所覆蓋的像素只是一小部分,是局部特徵,所以說是局部感知。感受野的計算見我之前的博客

權重共享,不同的圖像或者同一張圖像共用一個卷積核,減少重複的卷積核。同一張圖像當中可能會出現相同的特徵,共享卷積核能夠進一步減少權值參數。

多卷積核,一種卷積核代表的是一種特徵,爲獲得更多不同的特徵集合,卷積層會有多個卷積核,生成不同的特徵,這也是爲什麼卷積後的圖片的高,每一個圖片代表不同的特徵,一般輸出單位節點矩陣的深度代表卷積核的個數

共享每一層卷積層中過濾器中的參數可巨幅減少神經網絡上的參數。以cifar-10問題爲例,輸入層矩陣的維度爲32*32*3,假設第一層卷積層使用尺寸爲5*5,深度爲16的過濾器,那麼這個卷積層參數的個數爲5*5*3*16+16=1216個。相比較前面150萬個參數減少很多。

全0填充,一定步長,一定大小的過濾器卷積後的圖像大小計算見我之前博客

可以自己構建一個參數矩陣去遍歷圖像實現

當中四維矩陣前兩維代表過濾器的尺寸,第三個代表深度,第四個表示過濾器的深度

filter_weight = tf.get_variable('weights',[5,5,3,16],initializer=tf.truncated_normal_initializer(stddev=0.1))
biases=tf.get_variable('biases',[16],initializer=tf.constant_initializer(0.1))

但可以用tf.nn.conv2d來實現卷積層前向傳播的算法,第一個輸入爲當前層的節點矩陣,這個矩陣是四維矩陣,後面三維對應一個節點矩陣,第一維對應一個輸入batch, 第二個參數提供了卷積層的權重,第三個參數爲不同維度上的步長,第一維和最後一維的數字要求一定爲1,最後一個是填充的方法,SAME表示全0填充,VALID表示不添加

conv = tf.nn.conv2d(input,filter_weight,strides=[1,1,1,1],padding='SAME')
bias = tf.nn.bias_add(conv, biases)
actived_conv = tf.nn.relu(bias)

一個卷積神經網絡主要由以下5中結構組成:

輸入層、卷積層、池化層、全連接層、softmax層

pool=tf.nn.max_pool(actived_conv,ksize=[1,3,3,1],strides=[1,2,2,1],padding="SAME")

和卷積層類似,要先傳入四維矩陣,第二個參數爲過濾器的尺寸,第三個參數爲步長,第四個參數和卷積層設置保持一致

接下來分析了經典的卷積網絡模型LeNet-5模型,可以對比我的博客:caffe使用命令行方式訓練預測mnist、cifar10及自己的數據集中caffe實現的LeNet-5結構

並給出了實現LetNet-5模型的tensorflow程序,只需要修改前面的mnist_inference.py即可,在這個程序中使用了dropout方法,dropout可以進一步提升模型可靠性並防止過擬合,dropout過程只在訓練時使用。

後面又介紹了Inception-v3模型

後面又介紹了卷積神經網絡遷移學習的程序示例

圖像數據處理,多線程輸入,循環神經網絡,計算加速。

tensorflow源碼編譯可見我之前的博客win7下VS2015編譯tensorflow源碼教程(在線和離線)及調用配置

不同於caffe,使用tensorflow框架基本還是在python環境下去搭建網絡結構(可結合keras快速搭建),訓練和測試

我的其它博客有介紹如何源碼編譯caffe,並在matlab、python、c++環境下去搭建網絡、訓練網絡、預測圖片

其中keras的.h5模型可以轉化爲tensorflow的pb模型,供c++及python版tensorflow使用。對我而言如果需要用c++環境去訓練和預測圖片,我會優先選擇caffe來做。如果是python環境去訓練和預測圖片,我會優先考慮tensorflow結合keras。caffe也可以輸出網絡結構圖及打印損失率及精度曲線,我的其它博客有介紹。目前來看常用的還是用在python環境下使用tensorflow或者keras去定義網絡結構, 該訓練好的模型可以生成pb文件,直接給c++版的tensorflow去預測。很少去用tensorflow 的c++版去訓練網絡結構。

發佈了24 篇原創文章 · 獲贊 24 · 訪問量 4萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章