tensorflow2.0的介紹與基本使用


本文內容來自該網址https://github.com/zht007/tensorflow-practice,非常感謝作者為學者提供簡潔又精髓的學習資料。

谷歌免費使用GPU與CPU

萬事開頭難,對於機器學習初學者來說,最困難的可能是如何在計算機中搭建機器學習所需要的環境,特別是如何配置GPU問題,讓很多老鳥都頗為頭疼。

好消息是Google爸爸已經替大家把這些問題都解決了,現在只需要有一台能(科學)上網電腦,一個瀏覽器就能可以開啟機器學習之路了,Google甚至把昂貴的GPU和TPU都開放出來了,還等什么,趕緊上車吧。

1.Colab簡介

Colab是Google開發的一個完全基於雲端的Jupyter Notebook開發環境,使用者不需要做任何設置就可以在上面運行代碼。當然也支持從本地和Github導入數據和文件。

2. Colab保存文件

在Colab中,可以完全像在本地使用Jupyter Notebook,新建,導入,運行Jupyter Notebook.

但是要注意的是如果你想保存文件最好"Save a copy to Google Drive",否則關掉瀏覽器數所有數據都會丟失掉的。當然你也可以下載".py"或者".ipnb"文件。

這些選項都在“File”中可以找到。

3. Colab實踐

我們試一下從Gitbut中導入之前文章中用到的Jupyter Notebook 文件吧。

點擊"File ——> Upload Notebook" 選擇Github選項並輸入Github地址就能找到我們之前的Jupyter Notbook文件啦。

導入之后,你就可以向在本地運行Jupyter Notebook一樣在雲端訓練你的模型啦。由於訓練是在雲端進行,本地電腦該干嘛還可以繼續干嘛,不用擔心功CPU、內存、GPU占用率過高的問題啦。

4. 使用GPU和TPU

如果模型太復雜或者數據量太大,GPU和TPU(Tensor processing unit )可以大大地提高運算和訓練速度。

選擇GPU和TPU對訓練進行加速也非常簡單,只需要點擊"Runtime —> Change Runtime Type"就可以啦。

Eager模式像原生Python一樣簡潔優雅

眾所周知,Tensorflow入門之所以困難,與其采用的Graph 和 Session 模式有關,這與原生的 Python 代碼簡單、直觀的印象格格不入。同時,由於計算僅僅發生在Session里面,所以初始化參數和變量的時候沒辦法將結果打印出來,以至於調試起來也十分困難。

當然Google官方也意識到了這點,於是引入了Eager模式,在這個模式下tensorflow的常量和變量可以直接計算並打印出來,甚至還可以和numpy數組混合計算。本文代碼參考官方教程(from github with Apache License 2.0)

import tensorflow as tf
import tensorflow.contrib.eager as tfe #tfe在后面優化器(Optimizer)的時候需要用到,故先在這里定義了。
import numpy as np
import os
import matplotlib.pyplot as plt

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3' #設置打印日志的等級
'''
1.激活Eager模式,激活Eager模式也非常簡單,僅幾行代碼。
注意,eager模式在程序開始就要激活,且不能與普通模式混用。
'''
tf.compat.v1.enable_eager_execution()
a = tf.constant([[1, 2],
                 [3, 4]])
b = tf.Variable(np.zeros((2, 2)))

print('Eger模式下,定義的變量或者常量可以直接打印出來')
print('a=', a)
print('\n b=', b)
print('張量可以直接轉為numpy數組,甚至可以與numpy混合計算。')
print(a.numpy())
print()
print(b.numpy())
print()
x = tf.Variable([[6, 7],
                 [8.0, 9.0]], dtype="float32")
y = np.array([[1, 2],
              [3, 4]], dtype="float32")

mtl = tf.matmul(x, y)
print(mtl)
print()
print(mtl.numpy())

'''eager模式下訓練線性回歸模型'''
# 3.1
# 創建模擬數據
# 與之前的數據一樣,此處數據是100萬個帶噪音的線性數據,100
# 萬個點用plt是畫不出來的,圖中隨機采樣了250個點
# 我們定義一個幫助函數方便以batch的形式這100萬個數據點中隨機抽取batch
# size大小的數據進行訓練
def next_batch(x_data,y_true, batch_size):
    batch_index = np.random.randint(len(x_data), size=(batch_size))
    x_train = x_data[batch_index]
    y_train = y_true[batch_index]
    return x_train, y_train

# 定義變量
# 此處與普通模式下的tensorflow變量沒有任何區別
w_tfe = tf.Variable(np.random.uniform())
b_tfe = tf.Variable(np.random.uniform(1, 10))

# 線性函數
# 在普通模式下的tensorflow中我們需要定義計算圖譜,這里我們直接以python函數的形式,
# 定義要訓練的線性回歸函數。
def linear_regression(inputs):
    return inputs * w_tfe + b_tfe


# 損失函數
# 同樣的,MS(Mean Square)損失函數也要以python函數的形式定義,而不是計算圖譜。
def mean_square_fn(model_fn, inputs, labels,batch_size):
    return tf.reduce_sum(tf.pow(model_fn(inputs) - labels, 2)) / (2 * batch_size)

# 優化器
# 同樣使用Gradient Descent的優化器,不同在於,普通模式下我們創建一個計算圖譜train = optimizer.minimize(error),
# 在Eager模式下,要用tfe.implicit_gradients()來返回一個函數。

optimizer = tf.compat.v1.train.GradientDescentOptimizer(learning_rate=0.001)
grad = tfe.implicit_gradients(mean_square_fn)

# 模型訓練
# 由於沒有計算圖譜,所以也不需要初始化變量,也不需在Session下運行,而是類似於原生Python
# 函數的形式將數據傳入"Optimizer模型"函數。訓練完成之后,w和b的參數也自動保存下來,不必在Session中提取。

#創建數據
np.random.seed(28)
x_data = np.random.normal(5,3,size=(100,2))
for i in range(10,30,5):
    x_data = np.vstack((x_data,np.random.normal(i,3,size=(100,2))))

BATCH_SIZE = 10
BATCHS = len(x_data) // BATCH_SIZE


for step in range(BATCHS):
    x_train, y_train = next_batch(x_data[:,0],x_data[:,1],BATCH_SIZE)
    optimizer.apply_gradients(grad(linear_regression, x_train, y_train,BATCH_SIZE))
print(w_tfe.numpy())
print(b_tfe.numpy())

# 驗證訓練結果,直接將最終的 w和b
test_data = np.arange(-5,35)
predict_y = w_tfe*test_data + b_tfe
plt.scatter(x_data[:,0],x_data[:,1])
plt.plot(test_data,predict_y,'r-')
plt.show()
eager模式下的使用優化器做線性回歸

自動求導與線性回歸

 1.Tensorflow 2.0 初始化

寫作本文的時候 Tensorflow 2.0 已經出到 RC 版本了,與正式版應該相差不大了。如何安裝該版本請參考官方說明。

# upgrade pip
pip install --upgrade pip

# Current stable release for CPU-only
pip install tensorflow

# Preview nightly build for CPU-only (unstable)
pip install tf-nightly

# Install TensorFlow 2.0 RC
pip install tensorflow==2.0.0-rc1

如果使用 Colab 只需要在初始的代碼框運行這幾行代碼即可

try:
  # %tensorflow_version only exists in Colab.
  %tensorflow_version 2.x
except Exception:
  pass

2. 自動求導

微分求導是機器學習的基礎,Tensorflow 提供了強大的自動求導工具,下面我們就用 Tensorflow 2.0 計算函數 y(x)=x^2 在 x=3 時的導數

import tensorflow as tf

x = tf.Variable(initial_value=3.)
with tf.GradientTape() as tape:     # 在 tf.GradientTape() 的上下文內,所有計算步驟都會被記錄以用於求導
    y = tf.square(x)
y_grad = tape.gradient(y, x)        # 計算y關於x的導數
print([y.numpy(), y_grad.numpy()])

該部分代碼參考 github repo with MIT License

我們可以得到 y = 3*3 = 9, y_grad = 2 * 3 =6 的結果。

tf.GradientTape() 是一個自動求導的記錄器,在其中的變量和計算步驟都會被自動記錄。在上面的示例中,變量 x和計算步驟 y = tf.square(x) 被自動記錄,因此可以通過 y_grad = tape.gradient(y, x) 求張量 y 對變量 x 的導數。

3. 線性回歸

該部分模擬生成的數據,我們之前用 Keras, Tensorflow 1.0 以及 Tensorflow Eager 模式都訓練過了,感興趣的讀者可以找來對比一下。

3.1 創建模擬數據

與之前的數據一樣,此處數據是100萬個帶噪音的線性數據,100萬個點用plt是畫不出來的,圖中隨機采樣了250個點

image

我們定義一個幫助函數方便以batch的形式這100萬個數據點中隨機抽取batch size大小的數據進行訓練

def next_batch(x_data, batch_size):
    batch_index = np.random.randint(len(x_data),size=(BATCH_SIZE))
    x_train = x_data[batch_index]
    y_train = y_true[batch_index]
    return x_train, y_train

3.2 定義變量

此處與 Tensorflow 1.0 變量沒有任何區別

w = tf.Variable(initial_value=0.)
b = tf.Variable(initial_value=0.)

3.3 定義優化器

為了讓 Tensorflow 自動更新參數,我們需要用到優化器,這里我用 SGD 來更新參數。

optimizer = tf.keras.optimizers.SGD(learning_rate= 1e-3)

3.4 線性回歸模型訓練

在這里我們需要理解一下幾點

  • 要更新參數就需要對參數求導,這里需要更新的參數(變量)為 w 和 b。
  • 要讓模型最優,及需要求變量(w, b)對損失函數求導(偏微分)
  • 與前面一樣,使用 tape.gradient(ys, xs) 自動計算梯度
  • 使用 optimizer.apply_gradients(grads_and_vars) 自動更新模型參數。
for step in range(BATCHS):
  x_train, y_train = next_batch(x_data, BATCH_SIZE)
  with tf.GradientTape() as tape:
    y_pred = w * x_train + b
    loss = tf.reduce_sum(tf.square(y_pred - y_train))/(BATCH_SIZE)
  
  grads = tape.gradient(loss, [w, b])
  optimizer.apply_gradients(grads_and_vars=zip(grads,[w,b]))

3.5 訓練結果

此處結果也相當符合預期

image-20190502150808881

4. 總結

Tensorflow 2.0 提供了一個非常優雅和簡潔的方式對參數進行自動求導和自動更新。 tf.GradientTape() 記錄計算步驟用於自動求導和自動更新參數的方式請務必牢記,在更復雜的模型下也將會被用到。

tf.GradientTape().gradient()只能被調用一次,如果需要多次調用就需要多次定義tf.GradientTape()或把求導封裝成一個函數。

import tensorflow as tf
import os
import numpy as np
import tensorflow.contrib.eager as tfe
tf.compat.v1.enable_eager_execution()
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

x = tf.Variable(-0.5)
y = tf.Variable(0.05)
iters = 10
for i in range(iters):
    with tf.GradientTape() as tape: #表達式需要寫在上下文內
        z = tf.subtract(tf.square(x), tf.square(y))
        x_grad, y_grad = tape.gradient(z, [x, y])
        x.assign(tf.subtract(x, 0.25 * x_grad))
        y.assign(tf.subtract(y, 0.25 * y_grad))
        print(x_grad.numpy())
        print(y_grad.numpy())
View Code
import tensorflow as tf
import os
import numpy as np
import tensorflow.contrib.eager as tfe
tf.compat.v1.enable_eager_execution()
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'

x = tf.Variable(-0.5)
y = tf.Variable(0.05)
iters = 10

def gradient_func():
    with tf.GradientTape() as tape: #表達式需要寫在上下文內
        z = tf.subtract(tf.square(x), tf.square(y))
        grad_result_list = tape.gradient(z, [x, y])
        x.assign(tf.subtract(x, 0.25 * grad_result_list[0]))
        y.assign(tf.subtract(y, 0.25 * grad_result_list[1]))
        return grad_result_list

for i in range(iters):
    x_grad,y_grad = gradient_func()
    print(x_grad.numpy())
    print(y_grad.numpy())
View Code

快速建立模型

Keras 是一個用於構建和訓練深度學習模型的高階 API。它可用於快速設計原型、高級研究和生產。

keras的3個優點: 方便用戶使用、模塊化和可組合、易於擴展

tensorflow2推薦使用keras構建網絡,常見的神經網絡都包含在keras.layer中(最新的tf.keras的版本可能和keras不同)

import tensorflow as tf
import os
import tensorflow_datasets as tfds
import matplotlib.pyplot as plt
import numpy as np
import glob
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '3'
from PIL import Image

cat_img = glob.glob('./test_data/cat/*.*.jpg')


def _parse_function(filename):
    # print(filename)
    image_string = tf.io.read_file(filename)

    image_decoded = tf.image.decode_jpeg(image_string,channels=3)
    print(type(image_decoded))
    image_resized = tf.cast(tf.image.resize(image_decoded,[200,200]),tf.uint8)
    # image_resized = tf.image.resize_with_crop_or_pad(image_decoded, 200, 200)

    # image_decoded = tf.image.decode_image(image_string)  # (375, 500, 3)
    # image_resized = tf.image.resize_with_crop_or_pad(image_decoded, 200, 200)
    # return tf.squeeze(mage_resized,axis=0)
    print(type(image_decoded))
    return image_resized

# dataset = tf.data.Dataset.from_tensor_slices(cat_img)
#
# dataset = dataset.map(_parse_function)
# dataset = dataset.shuffle(10).repeat(10).batch(2)
# iterator = tf.compat.v1.data.make_one_shot_iterator(dataset)
# img = iterator.get_next()
#
# with tf.compat.v1.Session() as sess:
#     for i in sess.run(img):
#         plt.imshow(i)
#         plt.show()

# import numpy as np
# p = 0.5  #dropout的概率,也就是保留一個神經元的存活率
# def train_step(X,W1,W2,W3,B1,B2,B3):
#     #FP階段:對於3層NN
#     H1 = np.maximum(0, np.dot(W1,X) + B1) #maximum相當於做了relu
#     U1 = np.random.rand(*H1.shape) < p
#     H1 *= U1 #drop要不轉換為0,要不直接原始值
#
#     H2 = np.maximum(0, np.dot(W2, H1) + B2)
#     U2 = (np.random.rand(*H2.shape) < p) / p #這里做了一次除以p的操作。可以不做。
#     H2 *= U2
#     out = np.dot(W3, H2) + B3
#
#     #BP操作:計算梯度...(省略)
#     #更新參數...(省略)
#
# #預測
# def predict(X,W1,W2,W3,B1,B2,B3):
#     #直接向前計算,不需要乘以p的值
#     H1 = np.maximum(0, np.dot(W1,X) + B1)
#     H2 = np.maximum(0, np.dot(W2, H1) + B2 )
#     out = np.dot(W3, H2) + B3


tf.compat.v1.enable_eager_execution()

'''構建模型的網絡流程'''
# model = tf.keras.Sequential()
# model.add(tf.keras.layers.Dense(32, activation='relu'))
# model.add(tf.keras.layers.Dense(32, activation='relu'))
# model.add(tf.keras.layers.Dense(10, activation='softmax'))
# model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
#              loss=tf.keras.losses.categorical_crossentropy,
#              metrics=[tf.keras.metrics.categorical_accuracy]) #構建好模型后,通過調用 compile 方法配置該模型的學習流程
#
'''產生數據'''
train_x = np.random.random((1000, 72))
train_y = np.random.random((1000, 10))
val_x = np.random.random((200, 72))
val_y = np.random.random((200, 10))
#
# '''模型訓練'''
# model.fit(train_x, train_y, epochs=10, batch_size=100,
#           validation_data=(val_x, val_y))

# dataset = tf.data.Dataset.from_tensor_slices((train_x, train_y))
# dataset = dataset.batch(32)
# dataset = dataset.repeat()
# val_dataset = tf.data.Dataset.from_tensor_slices((val_x, val_y))
# val_dataset = val_dataset.batch(32)
# val_dataset = val_dataset.repeat()
#
# model.fit(dataset, epochs=10, steps_per_epoch=30,
#           validation_data=val_dataset, validation_steps=3)


# '''模型評估'''
# test_x = np.random.random((1000, 72))
# test_y = np.random.random((1000, 10))
# model.evaluate(test_x, test_y, batch_size=32) #評估
# test_data = tf.data.Dataset.from_tensor_slices((test_x, test_y))
# test_data = test_data.batch(32).repeat()
# model.evaluate(test_data, steps=30)
#
# '''模型預測'''
# result = model.predict(test_x, batch_size=32)
# print(result.shape)


'''構建高級模型'''
'''
tf.keras.Sequential 模型是層的簡單堆疊,無法表示任意模型。使用 Keras 函數式 API 可以構建復雜的模型拓撲,例如:
多輸入模型,
多輸出模型,
具有共享層的模型(同一層被調用多次),
具有非序列數據流的模型(例如,殘差連接)。
使用函數式 API 構建的模型具有以下特征:
層實例可調用並返回張量。 輸入張量和輸出張量用於定義 tf.keras.Model 實例。 此模型的訓練方式和 Sequential 模型一樣。
'''
# input_x = tf.keras.Input(shape=(72,))
# hidden1 = tf.keras.layers.Dense(32, activation='relu')(input_x)
# hidden2 = tf.keras.layers.Dense(16, activation='relu')(hidden1)
# pred = tf.keras.layers.Dense(10, activation='softmax')(hidden2)
#
# model = tf.keras.Model(inputs=input_x, outputs=pred)
# model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
#              loss=tf.keras.losses.categorical_crossentropy,
#              metrics=['accuracy'])
# model.fit(train_x, train_y, batch_size=32, epochs=5)

'''模型子類化'''
'''
通過對 tf.keras.Model 進行子類化並定義您自己的前向傳播來構建完全可自定義的模型。
在 init 方法中創建層並將它們設置為類實例的屬性。在 call 方法中定義前向傳播
'''

class MyModel(tf.keras.Model):
    def __init__(self, num_classes=10):
        super(MyModel, self).__init__(name='my_model')
        self.num_classes = num_classes
        self.layer1 = tf.keras.layers.Dense(32, activation='relu')
        self.layer2 = tf.keras.layers.Dense(num_classes, activation='softmax')
    def call(self,inputs,training=None,mask=None):
        h1 = self.layer1(inputs)
        out = self.layer2(h1)
        return out

    def compute_output_shape(self, input_shape):
        print(type(tf.TensorShape(input_shape)))
        shape = tf.TensorShape(input_shape).as_list()
        shape[-1] = self.num_classes
        return tf.TensorShape(shape)

# model = MyModel(num_classes=10)
# model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
#              loss=tf.keras.losses.categorical_crossentropy,
#              metrics=['accuracy'])
#
# model.fit(train_x, train_y, batch_size=16, epochs=5)


'''自定義層'''
'''
通過對 tf.keras.layers.Layer 進行子類化並實現以下方法來創建自定義層:
build:創建層的權重。使用 add_weight 方法添加權重。
call:定義前向傳播。
compute_output_shape:指定在給定輸入形狀的情況下如何計算層的輸出形狀。 
或者,可以通過實現 get_config 方法和 from_config 類方法序列化層。
'''

class MyLayer(tf.keras.layers.Layer):
    def __init__(self, output_dim, **kwargs):
        self.output_dim = output_dim
        super(MyLayer, self).__init__(**kwargs)

    def build(self, input_shape):
        shape = tf.TensorShape((input_shape[1], self.output_dim))
        self.kernel = self.add_weight(name='kernel1', shape=shape,
                                   initializer='uniform', trainable=True)
        super(MyLayer, self).build(input_shape)

    def call(self, inputs, **kwargs):
        return tf.matmul(inputs, self.kernel)

    def compute_output_shape(self, input_shape):
        shape = tf.TensorShape(input_shape).as_list()
        shape[-1] = self.output_dim
        return tf.TensorShape(shape)

    def get_config(self):
        base_config = super(MyLayer, self).get_config()
        base_config['output_dim'] = self.output_dim
        return base_config

    @classmethod
    def from_config(cls, config):
        return cls(**config)

# model = tf.keras.Sequential([MyLayer(10), tf.keras.layers.Activation('softmax')])
# model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
#              loss=tf.keras.losses.categorical_crossentropy,
#              metrics=['accuracy'])
#
# model.fit(train_x, train_y, batch_size=16, epochs=5)


'''回調'''
# callbacks = [
#     tf.keras.callbacks.EarlyStopping(patience=2, monitor='val_loss'),
#     tf.keras.callbacks.TensorBoard(log_dir='./logs')
# ]
# model.fit(train_x, train_y, batch_size=16, epochs=5,
#          callbacks=callbacks, validation_data=(val_x, val_y))


'''權重保存'''
# model = tf.keras.Sequential([
# tf.keras.layers.Dense(64, activation='relu'),
# tf.keras.layers.Dense(10, activation='softmax')])
#
# model.compile(optimizer=tf.keras.optimizers.Adam(0.001),
#               loss='categorical_crossentropy',
#               metrics=['accuracy'])
#
# #加載參數
# model.load_weights('./weights/model.ckpt')
#載入最新版模型

# latest = tf.train.latest_checkpoint('./weights/')
# model.load_weights(latest)

# model.fit(train_x,train_y,batch_size=32,epochs=10)
# model.load_weights('./weights/model.h5')

# model.summary() #查看模型信息
#保存模型參數
# model.save_weights('./weights/model.ckpt')
# model.save_weights('./weights/model.h5')

'''保存整個模型'''
# model = tf.keras.Sequential([
#   tf.keras.layers.Dense(10, activation='softmax', input_shape=(72,)),
#   tf.keras.layers.Dense(10, activation='softmax')
# ])
# model.compile(optimizer='rmsprop',
#               loss='categorical_crossentropy',
#               metrics=['accuracy'])
# model.fit(train_x, train_y, batch_size=32, epochs=5)
# model.save('all_model.h5')
# # model = tf.keras.models.load_model('all_model.h5')


'''
將keras用於Estimator
Estimator API 用於針對分布式環境訓練模型。它適用於一些行業使用場景,例如用大型數據集進行分布式訓練並導出模型以用於生產
'''
# model = tf.keras.Sequential([tf.keras.layers.Dense(10,activation='softmax'),
#                           tf.keras.layers.Dense(10,activation='softmax')])
#
# model.compile(optimizer=tf.keras.optimizers.RMSprop(0.001),
#               loss='categorical_crossentropy',
#               metrics=['accuracy'])
#
# estimator = tf.keras.estimator.model_to_estimator(model)
View Code

tensorflow回調函數

回調函數Callbacks

回調函數是一組在訓練的特定階段被調用的函數集,你可以使用回調函數來觀察訓練過程中網絡內部的狀態和統計信息。通過傳遞回調函數列表到模型的.fit()中,即可在給定的訓練階段調用該函數集中的函數。

【Tips】雖然我們稱之為回調“函數”,但事實上Keras的回調函數是一個類,回調函數只是習慣性稱呼

keras.callbacks.Callback()

這是回調函數的抽象類,定義新的回調函數必須繼承自該類。

類屬性

  • params:字典,訓練參數集(如信息顯示方法verbosity,batch大小,epoch數)

  • model:keras.models.Model對象,為正在訓練的模型的引用回調函數以字典logs為參數,該字典包含了一系列與當前batch或epoch相關的信息。目前,模型的.fit()中有下列參數會被記錄到logs中:

  • 在每個epoch的結尾處(on_epoch_end),logs將包含訓練的正確率和誤差,accloss,如果指定了驗證集,還會包含驗證集正確率和誤差val_acc)val_lossval_acc還額外需要在.compile中啟用metrics=['accuracy']

  • 在每個batch的開始處(on_batch_begin):logs包含size,即當前batch的樣本數

  • 在每個batch的結尾處(on_batch_end):logs包含loss,若啟用accuracy則還包含acc

BaseLogger

keras.callbacks.BaseLogger()

該回調函數用來對每個epoch累加metrics指定的監視指標的epoch平均值

該回調函數在每個Keras模型中都會被自動調用

ProgbarLogger

keras.callbacks.ProgbarLogger()

該回調函數用來將metrics指定的監視指標輸出到標准輸出上

History

keras.callbacks.History()

該回調函數在Keras模型上會被自動調用,History對象即為fit方法的返回值

ModelCheckpoint

keras.callbacks.ModelCheckpoint(filepath, monitor='val_loss', verbose=0, save_best_only=False, save_weights_only=False, mode='auto', period=1)

該回調函數將在每個epoch后保存模型到filepath

filepath可以是格式化的字符串,里面的占位符將會被epoch值和傳入on_epoch_endlogs關鍵字所填入

例如,filepath若為weights.{epoch:02d-{val_loss:.2f}}.hdf5,則會生成對應epoch和驗證集loss的多個文件。

參數

  • filename:字符串,保存模型的路徑

  • monitor:需要監視的值

  • verbose:信息展示模式,0或1

  • save_best_only:當設置為True時,將只保存在驗證集上性能最好的模型

  • mode:‘auto’,‘min’,‘max’之一,在save_best_only=True時決定性能最佳模型的評判准則,例如,當監測值為val_acc時,模式應為max,當檢測值為val_loss時,模式應為min。在auto模式下,評價准則由被監測值的名字自動推斷。

  • save_weights_only:若設置為True,則只保存模型權重,否則將保存整個模型(包括模型結構,配置信息等)

  • period:CheckPoint之間的間隔的epoch數

EarlyStopping

keras.callbacks.EarlyStopping(monitor='val_loss', patience=0, verbose=0, mode='auto')

當監測值不再改善時,該回調函數將中止訓練

參數

  • monitor:需要監視的量

  • patience:當early stop被激活(如發現loss相比上一個epoch訓練沒有下降),則經過patience個epoch后停止訓練。

  • verbose:信息展示模式

  • mode:‘auto’,‘min’,‘max’之一,在min模式下,如果檢測值停止下降則中止訓練。在max模式下,當檢測值不再上升則停止訓練。

RemoteMonitor

keras.callbacks.RemoteMonitor(root='http://localhost:9000')

該回調函數用於向服務器發送事件流,該回調函數需要requests

參數

  • root:該參數為根url,回調函數將在每個epoch后把產生的事件流發送到該地址,事件將被發往root + '/publish/epoch/end/'。發送方法為HTTP POST,其data字段的數據是按JSON格式編碼的事件字典。

LearningRateScheduler

keras.callbacks.LearningRateScheduler(schedule)

該回調函數是學習率調度器

參數

  • schedule:函數,該函數以epoch號為參數(從0算起的整數),返回一個新學習率(浮點數)

TensorBoard

keras.callbacks.TensorBoard(log_dir='./logs', histogram_freq=0, write_graph=True, write_images=False, embeddings_freq=0, embeddings_layer_names=None, embeddings_metadata=None)

該回調函數是一個可視化的展示器

TensorBoard是TensorFlow提供的可視化工具,該回調函數將日志信息寫入TensorBorad,使得你可以動態的觀察訓練和測試指標的圖像以及不同層的激活值直方圖。

如果已經通過pip安裝了TensorFlow,我們可通過下面的命令啟動TensorBoard:

tensorboard --logdir=/full_path_to_your_logs 

更多的參考信息,請點擊這里

參數

  • log_dir:保存日志文件的地址,該文件將被TensorBoard解析以用於可視化

  • histogram_freq:計算各個層激活值直方圖的頻率(每多少個epoch計算一次),如果設置為0則不計算。

  • write_graph: 是否在Tensorboard上可視化圖,當設為True時,log文件可能會很大

  • write_images: 是否將模型權重以圖片的形式可視化
  • embeddings_freq: 依據該頻率(以epoch為單位)篩選保存的embedding層
  • embeddings_layer_names:要觀察的層名稱的列表,若設置為None或空列表,則所有embedding層都將被觀察。
  • embeddings_metadata: 字典,將層名稱映射為包含該embedding層元數據的文件名,參考這里獲得元數據文件格式的細節。如果所有的embedding層都使用相同的元數據文件,則可傳遞字符串。

ReduceLROnPlateau

keras.callbacks.ReduceLROnPlateau(monitor='val_loss', factor=0.1, patience=10, verbose=0, mode='auto', epsilon=0.0001, cooldown=0, min_lr=0)
當評價指標不在提升時,減少學習率當學習停滯時,減少2倍或10倍的學習率常常能獲得較好的效果。該回調函數檢測指標的情況,如果在 patience個epoch中看不到模型性能提升,則減少學習率

參數

  • monitor:被監測的量
  • factor:每次減少學習率的因子,學習率將以lr = lr*factor的形式被減少
  • patience:當patience個epoch過去而模型性能不提升時,學習率減少的動作會被觸發
  • mode:‘auto’,‘min’,‘max’之一,在min模式下,如果檢測值觸發學習率減少。在max模式下,當檢測值不再上升則觸發學習率減少。
  • epsilon:閾值,用來確定是否進入檢測值的“平原區”
  • cooldown:學習率減少后,會經過cooldown個epoch才重新進行正常操作
  • min_lr:學習率的下限

CSVLogger

keras.callbacks.CSVLogger(filename, separator=',', append=False)

將epoch的訓練結果保存在csv文件中,支持所有可被轉換為string的值,包括1D的可迭代數值如np.ndarray.

參數

  • fiename:保存的csv文件名,如run/log.csv
  • separator:字符串,csv分隔符
  • append:默認為False,為True時csv文件如果存在則繼續寫入,為False時總是覆蓋csv文件

LambdaCallback

keras.callbacks.LambdaCallback(on_epoch_begin=None, on_epoch_end=None, on_batch_begin=None, on_batch_end=None, on_train_begin=None, on_train_end=None)

用於創建簡單的callback的callback類

該callback的匿名函數將會在適當的時候調用,注意,該回調函數假定了一些位置參數on_eopoch_beginon_epoch_end假定輸入的參數是epoch, logson_batch_beginon_batch_end假定輸入的參數是batch, logson_train_beginon_train_end假定輸入的參數是logs

參數

  • on_epoch_begin: 在每個epoch開始時調用
  • on_epoch_end: 在每個epoch結束時調用
  • on_batch_begin: 在每個batch開始時調用
  • on_batch_end: 在每個batch結束時調用
  • on_train_begin: 在訓練開始時調用
  • on_train_end: 在訓練結束時調用

示例

# Print the batch number at the beginning of every batch.
batch_print_callback = LambdaCallback(
    on_batch_begin=lambda batch,logs: print(batch))
 
# Plot the loss after every epoch.
import numpy as np
import matplotlib.pyplot as plt
plot_loss_callback = LambdaCallback(
    on_epoch_end=lambda epoch, logs: plt.plot(np.arange(epoch),
                      logs['loss']))
 
# Terminate some processes after having finished model training.
processes = ...
cleanup_callback = LambdaCallback(
    on_train_end=lambda logs: [
    p.terminate() for p in processes if p.is_alive()])
 
model.fit(...,
      callbacks=[batch_print_callback,
         plot_loss_callback,
         cleanup_callback])
View Code

編寫自己的回調函數

我們可以通過繼承keras.callbacks.Callback編寫自己的回調函數,回調函數通過類成員self.model訪問訪問,該成員是模型的一個引用。

這里是一個簡單的保存每個batch的loss的回調函數:

class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
 
    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
View Code
class LossHistory(keras.callbacks.Callback):
    def on_train_begin(self, logs={}):
        self.losses = []
 
    def on_batch_end(self, batch, logs={}):
        self.losses.append(logs.get('loss'))
 
model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
 
history = LossHistory()
model.fit(X_train, Y_train, batch_size=128, epochs=20, verbose=0, callbacks=[history])
 
print(history.losses)
# outputs
'''
[0.66047596406559383, 0.3547245744908703, ..., 0.25953155204159617, 0.25901699725311789]
例子:記錄損失函數的歷史數據
from keras.callbacks import ModelCheckpoint
 
model = Sequential()
model.add(Dense(10, input_dim=784, kernel_initializer='uniform'))
model.add(Activation('softmax'))
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
 
'''
saves the model weights after each epoch if the validation loss decreased
'''
checkpointer = ModelCheckpoint(filepath="/tmp/weights.hdf5", verbose=1, save_best_only=True)
model.fit(X_train, Y_train, batch_size=128, epochs=20, verbose=0, validation_data=(X_test, Y_test), callbacks=[checkpointer])
例子:模型檢查點
# import tensorflow as tf
# import os
# import numpy as np
# tf.compat.v1.enable_eager_execution()
# #
# #讀取數據
# (train_x,train_y),(test_x,test_y) = tf.keras.datasets.mnist.load_data()
# train_x = train_x.reshape(train_x.shape[0],-1).astype('float32')/255
# test_x = test_x.reshape(test_x.shape[0],-1).astype('float32')/255
# print(train_x.shape)
# print(train_y.shape)
# print(test_x.shape)
# print(test_y.shape)
#
# '''構建bp網絡'''
# input_layer = tf.keras.Input(shape=(784,),name='input_layer')
# hidden_layer = tf.keras.layers.Dense(32,activation=tf.keras.activations.sigmoid,name='hidden_layer')(input_layer)
# out_layer = tf.keras.layers.Dense(10,activation="softmax",name='output_layer')(hidden_layer)
#
# '''創建模型並編譯'''
# model = tf.keras.Model(inputs=input_layer,outputs=out_layer,name='mnist_model')
# model.summary() #查看模型的構建信息
# # tf.keras.utils.plot_model(model, './test_data/mnist_model.png') #畫出模型的網絡圖
# # tf.keras.utils.plot_model(model, './test_data/model_info.png', show_shapes=True)
#
# #編譯模型:構建模型的學習流程。
# model.compile(optimizer=tf.keras.optimizers.RMSprop(),
#               loss='sparse_categorical_crossentropy',
#               metrics=['accuracy'])
#
# '''模型訓練及收集訓練信息與評估'''
# #防止寫TensorBoard信息文件時報錯找不到目錄的方法
# # os.makedirs('./log_dir/plugins/profile') #方法1:給相當路徑時需要加這行代碼
# dir_log = 'D:\\AI_pycharm_Code_backups\\Deep_learning_TensorFlow\\log_dir\\mnist_log' #方法2:給定一個絕對路徑。
# callbacks = [tf.keras.callbacks.TensorBoard(dir_log,histogram_freq=1,write_images=True,)]
# #模型訓練
# 第一次訓練
# first_epoch = 3
# model.fit(train_x,train_y,batch_size=32,epochs=first_epoch,callbacks=callbacks,validation_split=0.2)
#
# # test_evaluate = model.evaluate(test_x,test_y,batch_size=32,verbose=0)
# # print('loss:{}'.format(test_evaluate[0]))
# # print('acc:{}'.format(test_evaluate[1]))
#

# model.save_weights('./test_model/my_model_weights.h5') #保存的模型位置

# # 重新訓練
# json_string = model.to_json()
# del model
# model = tf.keras.models.model_from_json(json_string)
# model.load_weights('./test_model/my_model_weights.h5') #載入模型
# # model.compile(optimizer=tf.keras.optimizers.RMSprop(),
# #               loss='sparse_categorical_crossentropy',
# #               metrics=['accuracy'])
#
# second_epoch = 3
# history = model.fit(x=train_x, y=train_y,epochs=first_epoch+second_epoch,callbacks=callbacks,validation_split=0.2,initial_epoch=first_epoch) #關鍵的初始化epoch數
# print(history)
#
#


#保存整個模型
# model.save('./test_model/my_model.h5')
# '''模型加載做預測'''
# new_model = tf.keras.models.load_model('./test_model/my_model.h5')
# true_y = test_y[:10]
# predict_y = new_model.predict(test_x[:10])
# print(true_y)
# print(np.argmax(predict_y,axis=1))
# test_evaluate = new_model.evaluate(test_x,test_y,batch_size=32,verbose=0)
# print('loss:{}'.format(test_evaluate[0]))
# print('acc:{}'.format(test_evaluate[1]))
#
# #還可以繼續訓練
# history = new_model.fit(x=train_x, y=train_y,epochs=3,validation_split=0.2) #關鍵的初始化epoch數
# print(history.history)
bp神經網絡

更多學習去下面的連接:

https://zhuanlan.zhihu.com/p/59507137

https://github.com/zht007/tensorflow-practice

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM