TensorFlow2。0教程-自定義訓練實戰(非tf。keras)

本教程我們將使用TensorFlow來實現鳶尾花分類。整個過程包括:構建模型、模型訓練、模型預測。

最全Tensorflow 2。0 入門教程持續更新:

完整tensorflow2。0教程程式碼請看

https://

github。com/czy36mengfei

/tensorflow2_tutorials_chinese

(歡迎star)

本教程主要由tensorflow2。0官方教程的個人學習復現筆記整理而來,中文講解,方便喜歡閱讀中文教程的朋友,官方教程:https://www。tensorflow。org

匯入相關庫

匯入TensorFlow和其他所需的Python模組。 預設情況下,TensorFlow2使用急切執行來程式,會立即返回結果。

from

__future__

import

absolute_import

division

print_function

unicode_literals

import

os

import

matplotlib。pyplot

as

plt

pip

install

-

q

tensorflow

==

2。0

0

-

alpha0

import

tensorflow

as

tf

print

‘tf version:’

tf

__version__

print

‘eager execution:’

tf

executing_eagerly

())

tf

version

2。0

0

-

alpha0

eager

execution

True

鳶尾花分類問題

想象一下,你是一名植物學家,正在尋找一種自動化的方法來對你找到的每種鳶尾花進行分類。 機器學習提供了許多演算法來對花進行統計分類。 例如,複雜的機器學習程式可以基於照片對花進行分類。而這裡,我們將根據萼片和花瓣的長度和寬度測量來對鳶尾花進行分類。

鳶尾花有300多種類別,但我們的這裡主要對以下三種進行分類: - Iris setosa - Iris virginica - Iris versicolor

TensorFlow2.0教程-自定義訓練實戰(非tf.keras)

幸運的是,有人已經用萼片和花瓣測量建立了120個鳶尾花的資料集。 這是一個流行的初學者機器學習分類問題的經典資料集。

下載資料集 使用tf。keras。utils。get_file函式下載訓練資料集檔案。 這將返回下載檔案的檔案路徑。

train_dataset_url

=

“https://storage。googleapis。com/download。tensorflow。org/data/iris_training。csv”

train_dataset_fp

=

tf

keras

utils

get_file

fname

=

os

path

basename

train_dataset_url

),

origin

=

train_dataset_url

print

‘下載資料至:’

train_dataset_fp

下載資料至:

/

root

/。

keras

/

datasets

/

iris_training

csv

檢查資料

此資料集iris_training。csv是一個純文字檔案,用於儲存格式為逗號分隔值(CSV)的表格資料。 使用head -n5命令在前五個條目中取一個峰值:

head

-

n5

{

train_dataset_fp

}

120

4

setosa

versicolor

virginica

6。4

2。8

5。6

2。2

2

5。0

2。3

3。3

1。0

1

4。9

2。5

4。5

1。7

2

4。9

3。1

1。5

0。1

0

從資料集的此檢視中,請注意以下內容:

第一行是包含有關資料集的資訊的標題: 總共有120個例子。 每個示例都有四個特徵和三個可能的標籤名稱之一。 後續行是資料記錄,每行一個示例,其中: 前四個欄位是特徵:這些是示例的特徵。 這裡,欄位包含代表花卉測量值的浮點數。 最後一列是標籤:這是我們想要預測的值。 對於此資料集,它是與花名稱對應的整數值0,1或2。

column_names

=

‘sepal_length’

‘sepal_width’

‘petal_length’

‘petal_width’

‘species’

# 獲取特徵和標籤名

feature_name

=

column_names

[:

-

1

label_name

=

column_names

-

1

每個標籤都與字串名稱相關聯(例如,“setosa”),但機器學習通常依賴於數值。使用標籤數字來對映類別,例如:

0:Iris setosa:

1:Iris versicolor

2:Iris virginica

class_names

=

‘Iris setosa’

‘Iris versicolor’

‘Iris virginica’

建立一個 tf。data。Dataset

TensorFlow的資料集API處理許多將資料載入到模型中的常見情況。這是一個高階API,用於讀取資料並將其轉換為用於訓練的資料型別。

由於資料集是CSV格式的文字檔案,因此需要使用make_csv_dataset函式將資料解析為合適的格式。由於此函式為訓練模型生成資料,因此預設行為是對資料(shuffle=True, shuffle_buffer_size=10000)進行混洗,並永遠重複資料集(num_epochs=None)。同時還需要設定batch_size引數。

batch_size

=

32

train_dataset

=

tf

data

experimental

make_csv_dataset

train_dataset_fp

batch_size

column_names

=

column_names

label_name

=

label_name

num_epochs

=

1

該make_csv_dataset函式返回tf。data。Dataset的(features, label)對,其中features是一個字典:{‘feature_name’: value}

而這些Dataset物件是可迭代的。

features

labels

=

next

iter

train_dataset

))

print

features

OrderedDict

([(

‘sepal_length’

<

tf

Tensor

id

=

64

shape

=

32

,),

dtype

=

float32

numpy

=

array

([

7。6

6。9

7。2

5。

6。7

4。8

5。4

5。1

7。7

6。

6。3

7。4

5。2

7。2

6。7

6。1

5。

4。9

6。2

4。5

6。6

6。

5。5

6。3

4。8

6。7

6。1

5。6

7。3

6。9

5。7

6。3

],

dtype

=

float32

>

),

‘sepal_width’

<

tf

Tensor

id

=

65

shape

=

32

,),

dtype

=

float32

numpy

=

array

([

3。

3。2

3。6

2。3

3。

3。

3。9

3。7

3。

2。2

2。3

2。8

2。7

3。2

3。1

2。8

3。4

3。1

2。8

2。3

3。

3。

3。5

3。3

3。4

3。

2。8

2。9

2。9

3。1

3。8

2。5

],

dtype

=

float32

>

),

‘petal_length’

<

tf

Tensor

id

=

62

shape

=

32

,),

dtype

=

float32

numpy

=

array

([

6。6

5。7

6。1

3。3

5。2

1。4

1。3

1。5

6。1

5。

4。4

6。1

3。9

6。

5。6

4。

1。6

1。5

4。8

1。3

4。4

4。8

1。3

6。

1。6

5。

4。7

3。6

6。3

4。9

1。7

5。

],

dtype

=

float32

>

),

‘petal_width’

<

tf

Tensor

id

=

63

shape

=

32

,),

dtype

=

float32

numpy

=

array

([

2。1

2。3

2。5

1。

2。3

0。3

0。4

0。4

2。3

1。5

1。3

1。9

1。4

1。8

2。4

1。3

0。4

0。1

1。8

0。3

1。4

1。8

0。2

2。5

0。2

1。7

1。2

1。3

1。8

1。5

0。3

1。9

],

dtype

=

float32

>

)])

相同的特徵被放在同一個陣列中,陣列維度為batch_size大小。 可以視覺化如圖:

plt

scatter

features

‘petal_length’

],

features

‘sepal_length’

],

c

=

labels

cmap

=

‘viridis’

plt

xlabel

“Petal length”

plt

ylabel

“Sepal length”

plt

show

()

TensorFlow2.0教程-自定義訓練實戰(非tf.keras)

一般我們會把同一個資料的不同feature放在同一個陣列中,我們使用tf。pack()來將features重構為(batch_size, num_features)形狀。

def

pack_features_vector

features

labels

):

features

=

tf

stack

list

features

values

()),

axis

=

1

return

features

labels

# 使用tf。data。Dataset。map將重構函式運用到每條資料中。

train_dataset

=

train_dataset

map

pack_features_vector

# 檢視前5個數據

features

labels

=

next

iter

train_dataset

))

print

features

[:

5

])

tf

Tensor

[[

7。6

3。

6。6

2。1

6。9

3。2

5。7

2。3

7。2

3。6

6。1

2。5

5。

2。3

3。3

1。

6。7

3。

5。2

2。3

]],

shape

=

5

4

),

dtype

=

float32

選擇模型

一個模型是功能和標籤之間的關係。對於鳶尾花分類問題,該模型定義了萼片和花瓣測量與預測的鳶尾花物種之間的關係。一些簡單的模型可以用幾行代數來描述,但是複雜的機器學習模型具有很多難以概括的引數。

我們能否在不使用機器學習的情況下確定四種特徵與虹膜物種之間的關係?也就是說,可以使用傳統的程式設計技術(例如,很多條件語句)來建立模型嗎?也許 - 如果你對資料集進行了足夠長的分析,以確定特定物種的花瓣和萼片測量值之間的關係。這對於更復雜的資料集來說變得困難 - 可能是不可能的。良好的機器學習方法可以為我們確定模型。如果我們將足夠的代表性示例提供給正確的機器學習模型型別,程式將為我們找出關係。

選擇具體模型

我們需要選擇要訓練的模型。有很多型別的模型和挑選一個好的經驗。本教程使用神經網路來解決鳶尾花I分類問題。神經網路可以找到特徵和標籤之間的複雜關係。它是一個高度結構化的圖,組織成一個或多個隱藏層。每個隱藏層由一個或多個神經元組成。有幾類神經網路,這個程式使用密集或完全連線的神經網路:一層中的神經元接收來自每個神經網路的輸入連線上一層的神經元。例如,圖2說明了一個由輸入層,兩個隱藏層和一個輸出層組成的密集神經網路:

TensorFlow2.0教程-自定義訓練實戰(非tf.keras)

圖2。具有特徵,隱藏層和預測的神經網路。

當對來自圖2的模型進行訓練並喂入未標記的示例時,它產生三個預測:該花是給定的鳶尾花物種的可能性。這種預測稱為推理。對於此示例,輸出預測的總和為1。0。在圖2中,該預測分解為:0。02對山鳶尾,0。95對於變色鳶尾,並0。03為錦葵鳶尾。這意味著模型以95%的機率預測 - 未標記的示例花是變色鳶尾。

使用Keras建立模型

TensorFlow tf。keras API是建立模型和圖層的首選方式。這使得構建模型和實驗變得容易,而Keras處理將所有內容連線在一起的複雜性。

該tf。keras。Sequential模型是層的線性堆疊。它的建構函式採用一個層例項列表,在這種情況下,兩個Dense層各有10個節點,一個輸出層有3個節點代表我們的標籤預測。第一層的input_shape引數對應於資料集中的要素數,並且是必需的。

# 構建線性模型

model

=

tf

keras

Sequential

([

tf

keras

layers

Dense

10

activation

=

‘relu’

input_shape

=

4

,)),

tf

keras

layers

Dense

10

activation

=

‘relu’

),

tf

keras

layers

Dense

3

])

啟用函式確定在層中的每個節點的輸出形狀。這些非線性很重要 - 沒有它們,模型將等同於單個層。有許多可用的啟用,但ReLU對於隱藏層是常見的。

隱藏層和神經元的理想數量取決於問題和資料集。像機器學習的許多方面一樣,選擇神經網路的最佳形狀需要知識和實驗經驗。根據經驗,增加隱藏層和神經元的數量通常會建立一個更強大的模型,這需要更多的資料來有效地訓練。

測試模型結構

prediction

=

model

features

prediction

[:

5

<

tf

Tensor

id

=

229

shape

=

5

3

),

dtype

=

float32

numpy

=

array

([[

1。6543204

0。12405288

0。24490094

],

1。4488522

0。11291474

0。24872684

],

1。5161525

0。11867774

0。28899187

],

0。86002606

0。05858952

0。06260413

],

1。3767202

0。10884094

0。21688706

]],

dtype

=

float32

>

多分類任務需要使用softmax進行歸一化

tf

nn

softmax

prediction

)[:

5

<

tf

Tensor

id

=

235

shape

=

5

3

),

dtype

=

float32

numpy

=

array

([[

0。6845738

0。148195

0。16723117

],

0。63935834

0。16809471

0。19254689

],

0。6492055

0。16049689

0。1902975

],

0。52654505

0。23625231

0。23720267

],

0。62697244

0。1764475

0。19658

]],

dtype

=

float32

>

使用tf。argmax獲取機率最大的類標籤

print

‘prediction:’

tf

argmax

prediction

axis

=

1

))

print

‘label:’

labels

prediction

tf

Tensor

([

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

0

],

shape

=

32

,),

dtype

=

int64

label

tf

Tensor

([

2

2

2

1

2

0

0

0

2

2

1

2

1

2

2

1

0

0

2

0

1

2

0

2

0

1

1

1

2

1

0

2

],

shape

=

32

,),

dtype

=

int32

訓練模型

訓練是機器學習中模型從資料集中學習知識並最佳化自身能力的過程。

Iris分類問題是一個典型的監督學習問題,其透過包含標籤的資料集進行學習。而無監督學習則是僅從特徵中去尋找相應的模式。

訓練和評估的過程都需要計算模型的損失,它可以衡量預測與正確標籤的差距,訓練過程都是要最小化損失。

我們後面將直接使用tf。keras裡面包裝好的損失函式來計算損失。

# 損失函式

loss_object

=

tf

keras

losses

SparseCategoricalCrossentropy

from_logits

=

True

# 獲取損失

def

loss

model

x

y

):

y_

=

model

x

return

loss_object

y_true

=

y

y_pred

=

y_

l

=

loss

model

features

labels

print

l

tf

Tensor

1。3738844

shape

=

(),

dtype

=

float32

使用tf。GradientTape計算loss對所有變數的梯度。

def

grad

model

inputs

targets

):

with

tf

GradientTape

()

as

tape

loss_value

=

loss

model

inputs

targets

return

loss_value

tape

gradient

loss_value

model

trainable_variables

建立最佳化器

最佳化程式將計算出的梯度應用於模型的變數,以最大限度地減少損失函式。 您可以將損失函式視為曲面(參見圖3),我們希望透過四處走動找到它的最低點。 漸變指向最陡的上升方向 - 所以我們將以相反的方向行進並向下移動。 透過迭代計算每批的損失和梯度,我們將在訓練期間調整模型。 逐漸地,該模型將找到權重和偏差的最佳組合,以最小化損失。 損失越低,模型的預測越好。

TensorFlow2.0教程-自定義訓練實戰(非tf.keras)

TensorFlow有許多可用於訓練的最佳化演算法。 該模型使用tf。train。GradientDescentOptimizer實現隨機梯度下降(SGD)演算法。 learning_rate設定每次迭代下一步的步長。 這是一個超引數,您通常會調整以獲得更好的結果。

optimizer

=

tf

keras

optimizers

Adam

learning_rate

=

0。01

最佳化器使用如下

loss_value

grads

=

grad

model

features

labels

print

‘步數:{}, 初始loss值:{}’

format

optimizer

iterations

numpy

(),

loss_value

numpy

()))

optimizer

apply_gradients

zip

grads

model

trainable_variables

))

print

‘步數:{}, loss值:{}’

format

optimizer

iterations

numpy

(),

loss

model

features

labels

numpy

()))

步數:

0

初始

loss值

1。3738844394683838

步數:

1

loss值

1。1648454666137695

訓練迴圈

每個epoch資料將會被訓練一次。

# 儲存loss和acc

train_loss_results

=

[]

train_accuracy_results

=

[]

num_epochs

=

201

for

epoch

in

range

num_epochs

):

# 用於記錄loss和acc的類

epoch_loss_avg

=

tf

keras

metrics

Mean

()

epoch_accuracy

=

tf

keras

metrics

SparseCategoricalAccuracy

()

# 訓練迴圈

for

x

y

in

train_dataset

# 獲取loss和梯度

loss_value

grads

=

grad

model

x

y

# 梯度最佳化

optimizer

apply_gradients

zip

grads

model

trainable_variables

))

# 記錄loss均值

epoch_loss_avg

loss_value

# 記錄準確率

epoch_accuracy

y

model

x

))

# 儲存每個epoch的loss和acc

train_loss_results

append

epoch_loss_avg

result

())

train_accuracy_results

append

epoch_accuracy

result

())

if

epoch

%

50

==

0

print

“Epoch {:03d}: Loss: {:。3f}, Accuracy: {:。3%}”

format

epoch

epoch_loss_avg

result

(),

epoch_accuracy

result

()))

Epoch

000

Loss

1。048

Accuracy

70。000

%

Epoch

050

Loss

0。074

Accuracy

99。167

%

Epoch

100

Loss

0。059

Accuracy

99。167

%

Epoch

150

Loss

0。054

Accuracy

99。167

%

Epoch

200

Loss

0。051

Accuracy

99。167

%

視覺化訓練過程

fig

axes

=

plt

subplots

2

sharex

=

True

figsize

=

12

8

))

fig

suptitle

‘Training Metrics’

axes

0

set_ylabel

“Loss”

fontsize

=

14

axes

0

plot

train_loss_results

axes

1

set_ylabel

“Accuracy”

fontsize

=

14

axes

1

set_xlabel

“Epoch”

fontsize

=

14

axes

1

plot

train_accuracy_results

plt

show

()

TensorFlow2.0教程-自定義訓練實戰(非tf.keras)

評估模型

評估模型類似於訓練模型。 最大的區別是示例來自單獨的測試集而不是訓練集。 為了公平地評估模型的有效性,用於評估模型的示例必須與用於訓練模型的示例不同。

測試資料集的設定類似於訓練資料集的設定。 下載CSV文字檔案並解析該值,然後將其打亂:

test_url

=

“https://storage。googleapis。com/download。tensorflow。org/data/iris_test。csv”

test_fp

=

tf

keras

utils

get_file

fname

=

os

path

basename

test_url

),

origin

=

test_url

Downloading

data

from

https

//

storage

googleapis

com

/

download

tensorflow

org

/

data

/

iris_test

csv

8192

/

573

============================================================================================================================================================================================================================================================================================================================================================================================================================================

-

0

s

0

us

/

step

test_dataset

=

tf

data

experimental

make_csv_dataset

test_fp

batch_size

column_names

=

column_names

label_name

=

‘species’

num_epochs

=

1

shuffle

=

False

test_dataset

=

test_dataset

map

pack_features_vector

評估測試資料集上的模型

與訓練階段不同,該模型僅評估測試資料的單個時期。 在下面的程式碼單元格中,我們迭代測試集中的每個示例,並將模型的預測與實際標籤進行比較。 這用於測量整個測試集中模型的準確性。

# 準確率統計類

test_accuracy

=

tf

keras

metrics

Accuracy

()

for

x

y

in

test_dataset

logits

=

model

x

prediction

=

tf

argmax

logits

axis

=

1

output_type

=

tf

int32

test_accuracy

prediction

y

print

‘測試集準確率:’

test_accuracy

result

())

測試集準確率:

tf

Tensor

0。96666664

shape

=

(),

dtype

=

float32

結果對比

tf

stack

([

y

prediction

],

axis

=

1

<

tf

Tensor

id

=

164737

shape

=

30

2

),

dtype

=

int32

numpy

=

array

([[

1

1

],

2

2

],

0

0

],

1

1

],

1

1

],

1

1

],

0

0

],

2

1

],

1

1

],

2

2

],

2

2

],

0

0

],

2

2

],

1

1

],

1

1

],

0

0

],

1

1

],

0

0

],

0

0

],

2

2

],

0

0

],

1

1

],

2

2

],

1

1

],

1

1

],

1

1

],

0

0

],

1

1

],

2

2

],

1

1

]],

dtype

=

int32

>

使用訓練的模型進行預測

我們已經訓練了一個模型並且“證明”它對Iris物種進行分類是好的 - 但不是完美的。 現在讓我們使用訓練有素的模型對未標記的例子做出一些預測; 也就是說,包含特徵但不包含標籤的示例。

在現實生活中,未標記的示例可能來自許多不同的來源,包括應用程式,CSV檔案和資料來源。 目前,我們將手動提供三個未標記的示例來預測其標籤。 回想一下,標籤號被對映到命名錶示,如下所示: - 0: Iris setosa - 1: Iris versicolor - 2: Iris virginica

predict_dataset

=

tf

convert_to_tensor

([

5。1

3。3

1。7

0。5

,],

5。9

3。0

4。2

1。5

,],

6。9

3。1

5。4

2。1

])

predictions

=

model

predict_dataset

for

i

logits

in

enumerate

predictions

):

class_idx

=

tf

argmax

logits

numpy

()

p

=

tf

nn

softmax

logits

)[

class_idx

name

=

class_names

class_idx

print

“Example {} prediction: {} ({:4。1f}%)”

format

i

name

100

*

p

))

Example

0

prediction

Iris

setosa

99。9

%

Example

1

prediction

Iris

versicolor

99。9

%

Example

2

prediction

Iris

virginica

99。1

%