本文內容來自該網址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()
自動求導與線性回歸
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個點
我們定義一個幫助函數方便以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 訓練結果
此處結果也相當符合預期
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())

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())
快速建立模型
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)
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
將包含訓練的正確率和誤差,acc
和loss
,如果指定了驗證集,還會包含驗證集正確率和誤差val_acc)
和val_loss
,val_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_end
的logs
關鍵字所填入
例如,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)
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_begin
和on_epoch_end
假定輸入的參數是epoch, logs
. on_batch_begin
和on_batch_end
假定輸入的參數是batch, logs
,on_train_begin
和on_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])
編寫自己的回調函數
我們可以通過繼承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'))

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)
更多學習去下面的連接:
https://zhuanlan.zhihu.com/p/59507137
https://github.com/zht007/tensorflow-practice