CNTK - Bộ nhớ trong và bộ dữ liệu lớn

Trong chương này, chúng ta sẽ tìm hiểu về cách làm việc với bộ nhớ trong và bộ dữ liệu lớn trong CNTK.

Đào tạo với bộ dữ liệu bộ nhớ nhỏ

Khi chúng ta nói về việc cung cấp dữ liệu vào trình huấn luyện CNTK, có thể có nhiều cách, nhưng nó sẽ phụ thuộc vào kích thước của tập dữ liệu và định dạng của dữ liệu. Tập dữ liệu có thể là tập dữ liệu trong bộ nhớ nhỏ hoặc tập dữ liệu lớn.

Trong phần này, chúng ta sẽ làm việc với các tập dữ liệu trong bộ nhớ. Đối với điều này, chúng tôi sẽ sử dụng hai khuôn khổ sau:

  • Numpy
  • Pandas

Sử dụng mảng Numpy

Ở đây, chúng tôi sẽ làm việc với một tập dữ liệu được tạo ngẫu nhiên dựa trên numpy trong CNTK. Trong ví dụ này, chúng ta sẽ mô phỏng dữ liệu cho một bài toán phân loại nhị phân. Giả sử, chúng tôi có một tập hợp các quan sát với 4 đặc điểm và muốn dự đoán hai nhãn có thể có bằng mô hình học sâu của chúng tôi.

Ví dụ triển khai

Đối với điều này, trước tiên chúng ta phải tạo một tập hợp các nhãn có chứa biểu diễn vector một nóng của các nhãn, chúng ta muốn dự đoán. Nó có thể được thực hiện với sự trợ giúp của các bước sau:

Step 1 - Nhập numpy gói như sau -

import numpy as np
num_samples = 20000

Step 2 - Tiếp theo, tạo ánh xạ nhãn bằng cách sử dụng np.eye chức năng như sau -

label_mapping = np.eye(2)

Step 3 - Bây giờ bằng cách sử dụng np.random.choice chức năng, thu thập 20000 mẫu ngẫu nhiên như sau:

y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)

Step 4 - Bây giờ cuối cùng bằng cách sử dụng hàm np.random.random, tạo một mảng các giá trị dấu chấm động ngẫu nhiên như sau:

x = np.random.random(size=(num_samples, 4)).astype(np.float32)

Sau khi, chúng tôi tạo ra một mảng các giá trị dấu phẩy động ngẫu nhiên, chúng tôi cần chuyển đổi chúng thành số dấu phẩy động 32-bit để nó có thể khớp với định dạng mà CNTK mong đợi. Hãy làm theo các bước dưới đây để làm điều này -

Step 5 - Nhập các chức năng lớp dày đặc và tuần tự từ mô-đun cntk.layers như sau:

from cntk.layers import Dense, Sequential

Step 6- Bây giờ, chúng ta cần nhập chức năng kích hoạt cho các lớp trong mạng. Hãy để chúng tôi nhậpsigmoid như chức năng kích hoạt -

from cntk import input_variable, default_options
from cntk.ops import sigmoid

Step 7- Bây giờ, chúng ta cần nhập hàm tổn thất để huấn luyện mạng. Hãy để chúng tôi nhập khẩubinary_cross_entropy như hàm mất mát -

from cntk.losses import binary_cross_entropy

Step 8- Tiếp theo, chúng ta cần xác định các tùy chọn mặc định cho mạng. Ở đây, chúng tôi sẽ cung cấpsigmoidchức năng kích hoạt như một cài đặt mặc định. Ngoài ra, tạo mô hình bằng cách sử dụng chức năng lớp Tuần tự như sau:

with default_options(activation=sigmoid):
model = Sequential([Dense(6),Dense(2)])

Step 9 - Tiếp theo, khởi tạo một input_variable với 4 tính năng đầu vào đóng vai trò là đầu vào cho mạng.

features = input_variable(4)

Step 10 - Bây giờ, để hoàn thành nó, chúng ta cần kết nối biến tính năng với NN.

z = model(features)

Vì vậy, bây giờ chúng ta có một NN, với sự trợ giúp của các bước sau, chúng ta hãy đào tạo nó bằng cách sử dụng tập dữ liệu trong bộ nhớ -

Step 11 - Để đào tạo NN này, trước tiên chúng ta cần nhập người học từ cntk.learnersmô-đun. Chúng tôi sẽ nhập khẩusgd người học như sau -

from cntk.learners import sgd

Step 12 - Cùng với đó nhập khẩu ProgressPrinter từ cntk.logging cũng như mô-đun.

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

Step 13 - Tiếp theo, xác định một biến đầu vào mới cho các nhãn như sau:

labels = input_variable(2)

Step 14 - Để đào tạo mô hình NN, tiếp theo, chúng ta cần xác định lỗ bằng cách sử dụng binary_cross_entropychức năng. Ngoài ra, cung cấp mô hình z và biến nhãn.

loss = binary_cross_entropy(z, labels)

Step 15 - Tiếp theo, khởi tạo sgd người học như sau -

learner = sgd(z.parameters, lr=0.1)

Step 16- Cuối cùng, gọi phương thức train trên hàm mất mát. Ngoài ra, cung cấp cho nó dữ liệu đầu vào,sgd người học và progress_printer.−

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

Hoàn thành ví dụ triển khai

import numpy as np
num_samples = 20000
label_mapping = np.eye(2)
y = label_mapping[np.random.choice(2,num_samples)].astype(np.float32)
x = np.random.random(size=(num_samples, 4)).astype(np.float32)
from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid
from cntk.losses import binary_cross_entropy
with default_options(activation=sigmoid):
   model = Sequential([Dense(6),Dense(2)])
features = input_variable(4)
z = model(features)
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(2)
loss = binary_cross_entropy(z, labels)
learner = sgd(z.parameters, lr=0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer])

Đầu ra

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average   since   average   since examples
loss      last    metric    last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.52      1.52      0         0     32
1.51      1.51      0         0     96
1.48      1.46      0         0    224
1.45      1.42      0         0    480
1.42       1.4      0         0    992
1.41      1.39      0         0   2016
1.4       1.39      0         0   4064
1.39      1.39      0         0   8160
1.39      1.39      0         0  16352

Sử dụng Pandas DataFrames

Mảng khó hiểu rất hạn chế về những gì chúng có thể chứa và là một trong những cách cơ bản nhất để lưu trữ dữ liệu. Ví dụ, một mảng n chiều có thể chứa dữ liệu của một kiểu dữ liệu duy nhất. Nhưng mặt khác, đối với nhiều trường hợp trong thế giới thực, chúng ta cần một thư viện có thể xử lý nhiều hơn một kiểu dữ liệu trong một tập dữ liệu.

Một trong những thư viện Python có tên là Pandas giúp làm việc với loại tập dữ liệu như vậy dễ dàng hơn. Nó giới thiệu khái niệm về DataFrame (DF) và cho phép chúng ta tải các tập dữ liệu từ đĩa được lưu trữ ở các định dạng khác nhau dưới dạng DF. Ví dụ: chúng ta có thể đọc các DF được lưu trữ dưới dạng CSV, JSON, Excel, v.v.

Bạn có thể tìm hiểu thư viện Python Pandas chi tiết hơn tại https://www.tutorialspoint.com/python_pandas/index.htm.

Ví dụ triển khai

Trong ví dụ này, chúng ta sẽ sử dụng ví dụ phân loại ba loài hoa iris có thể có dựa trên bốn đặc tính. Chúng tôi cũng đã tạo mô hình học sâu này trong các phần trước. Mô hình như sau:

from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)

Mô hình trên chứa một lớp ẩn và một lớp đầu ra với ba tế bào thần kinh để phù hợp với số lượng lớp mà chúng ta có thể dự đoán.

Tiếp theo, chúng tôi sẽ sử dụng train phương pháp và losschức năng huấn luyện mạng. Đối với điều này, trước tiên chúng ta phải tải và xử lý trước tập dữ liệu mống mắt, để nó khớp với bố cục và định dạng dữ liệu mong đợi cho NN. Nó có thể được thực hiện với sự trợ giúp của các bước sau:

Step 1 - Nhập numpyPandas gói như sau -

import numpy as np
import pandas as pd

Step 2 - Tiếp theo, sử dụng read_csv hàm để tải tập dữ liệu vào bộ nhớ -

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’,
 ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)

Step 3 - Bây giờ, chúng ta cần tạo một từ điển sẽ ánh xạ các nhãn trong tập dữ liệu với biểu diễn số tương ứng của chúng.

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 4 - Bây giờ, bằng cách sử dụng iloc trình lập chỉ mục trên DataFrame, chọn bốn cột đầu tiên như sau:

x = df_source.iloc[:, :4].values

Step 5−Tiếp theo, chúng ta cần chọn các cột loài làm nhãn cho tập dữ liệu. Nó có thể được thực hiện như sau:

y = df_source[‘species’].values

Step 6 - Bây giờ, chúng ta cần ánh xạ các nhãn trong tập dữ liệu, có thể được thực hiện bằng cách sử dụng label_mapping. Ngoài ra, sử dụngone_hot mã hóa để chuyển đổi chúng thành mảng mã hóa một nóng.

y = np.array([one_hot(label_mapping[v], 3) for v in y])

Step 7 - Tiếp theo, để sử dụng các tính năng và nhãn được ánh xạ với CNTK, chúng ta cần chuyển đổi cả hai thành float -

x= x.astype(np.float32)
y= y.astype(np.float32)

Như chúng ta biết rằng, các nhãn được lưu trữ trong tập dữ liệu dưới dạng chuỗi và CNTK không thể hoạt động với các chuỗi này. Đó là lý do, nó cần các vectơ được mã hóa một nóng đại diện cho các nhãn. Đối với điều này, chúng ta có thể xác định một hàm nóione_hot như sau -

def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result

Bây giờ, chúng ta có mảng numpy ở định dạng chính xác, với sự trợ giúp của các bước sau, chúng ta có thể sử dụng chúng để đào tạo mô hình của mình -

Step 8- Đầu tiên, chúng ta cần nhập hàm tổn thất để luyện mạng. Hãy để chúng tôi nhập khẩubinary_cross_entropy_with_softmax như hàm mất mát -

from cntk.losses import binary_cross_entropy_with_softmax

Step 9 - Để đào tạo NN này, chúng ta cũng cần nhập người học từ cntk.learnersmô-đun. Chúng tôi sẽ nhập khẩusgd người học như sau -

from cntk.learners import sgd

Step 10 - Cùng với đó nhập khẩu ProgressPrinter từ cntk.logging cũng như mô-đun.

from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)

Step 11 - Tiếp theo, xác định một biến đầu vào mới cho các nhãn như sau:

labels = input_variable(3)

Step 12 - Để đào tạo mô hình NN, tiếp theo, chúng ta cần xác định lỗ bằng cách sử dụng binary_cross_entropy_with_softmaxchức năng. Đồng thời cung cấp mô hình z và biến nhãn.

loss = binary_cross_entropy_with_softmax (z, labels)

Step 13 - Tiếp theo, khởi tạo sgd người học như sau -

learner = sgd(z.parameters, 0.1)

Step 14- Cuối cùng, gọi phương thức train trên hàm mất mát. Ngoài ra, cung cấp cho nó dữ liệu đầu vào,sgd người học và progress_printer.

training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=
[progress_writer],minibatch_size=16,max_epochs=5)

Hoàn thành ví dụ triển khai

from cntk.layers import Dense, Sequential
from cntk import input_variable, default_options
from cntk.ops import sigmoid, log_softmax
from cntk.losses import binary_cross_entropy
model = Sequential([
Dense(4, activation=sigmoid),
Dense(3, activation=log_softmax)
])
features = input_variable(4)
z = model(features)
import numpy as np
import pandas as pd
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
x = df_source.iloc[:, :4].values
y = df_source[‘species’].values
y = np.array([one_hot(label_mapping[v], 3) for v in y])
x= x.astype(np.float32)
y= y.astype(np.float32)
def one_hot(index, length):
result = np.zeros(length)
result[index] = index
return result
from cntk.losses import binary_cross_entropy_with_softmax
from cntk.learners import sgd
from cntk.logging import ProgressPrinter
progress_writer = ProgressPrinter(0)
labels = input_variable(3)
loss = binary_cross_entropy_with_softmax (z, labels)
learner = sgd(z.parameters, 0.1)
training_summary=loss.train((x,y),parameter_learners=[learner],callbacks=[progress_writer],minibatch_size=16,max_epochs=5)

Đầu ra

Build info:
     Built time: *** ** **** 21:40:10
     Last modified date: *** *** ** 21:08:46 2019
     Build type: Release
     Build target: CPU-only
     With ASGD: yes
     Math lib: mkl
     Build Branch: HEAD
     Build SHA1:ae9c9c7c5f9e6072cc9c94c254f816dbdc1c5be6 (modified)
     MPI distribution: Microsoft MPI
     MPI version: 7.0.12437.6
-------------------------------------------------------------------
average    since    average   since   examples
loss        last     metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.1         1.1        0       0      16
0.835     0.704        0       0      32
1.993      1.11        0       0      48
1.14       1.14        0       0     112
[………]

Đào tạo với bộ dữ liệu lớn

Trong phần trước, chúng ta đã làm việc với các tập dữ liệu trong bộ nhớ nhỏ bằng cách sử dụng Numpy và gấu trúc, nhưng không phải tất cả các tập dữ liệu đều nhỏ như vậy. Đặc biệt bộ dữ liệu chứa hình ảnh, video, âm thanh mẫu có dung lượng lớn.MinibatchSourcelà một thành phần, có thể tải dữ liệu theo khối, được cung cấp bởi CNTK để làm việc với các tập dữ liệu lớn như vậy. Một số tính năng củaMinibatchSource các thành phần như sau:

  • MinibatchSource có thể ngăn NN khỏi việc trang bị quá mức bằng cách tự động lấy mẫu ngẫu nhiên được đọc từ nguồn dữ liệu.

  • Nó có đường ống chuyển đổi tích hợp có thể được sử dụng để tăng cường dữ liệu.

  • Nó tải dữ liệu trên một luồng nền tách biệt với quá trình đào tạo.

Trong các phần tiếp theo, chúng ta sẽ khám phá cách sử dụng nguồn minibatch với dữ liệu hết bộ nhớ để làm việc với các tập dữ liệu lớn. Chúng ta cũng sẽ khám phá, làm thế nào chúng ta có thể sử dụng nó để nuôi để đào tạo NN.

Tạo phiên bản MinibatchSource

Trong phần trước, chúng ta đã sử dụng ví dụ về hoa iris và làm việc với tập dữ liệu nhỏ trong bộ nhớ bằng cách sử dụng Pandas DataFrames. Ở đây, chúng tôi sẽ thay thế mã sử dụng dữ liệu từ DF của gấu trúc bằngMinibatchSource. Đầu tiên, chúng ta cần tạo một phiên bản củaMinibatchSource với sự trợ giúp của các bước sau -

Ví dụ triển khai

Step 1 - Đầu tiên, từ cntk.io nhập các thành phần cho minibatchsource như sau:

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer,
 INFINITY_REPEAT

Step 2 - Bây giờ, bằng cách sử dụng StreamDef lớp, đóng thùng một định nghĩa luồng cho các nhãn.

labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)

Step 3 - Tiếp theo, tạo để đọc các tính năng được gửi từ tệp đầu vào, tạo một phiên bản khác của StreamDef như sau.

feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)

Step 4 - Bây giờ, chúng tôi cần cung cấp iris.ctf tập tin làm đầu vào và khởi tạo deserializer như sau -

deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=
label_stream, features=features_stream)

Step 5 - Cuối cùng, chúng ta cần tạo phiên bản của minisourceBatch bằng cách sử dụng deserializer như sau -

Minibatch_source = MinibatchSource(deserializer, randomize=True)

Tạo phiên bản MinibatchSource - Hoàn thành ví dụ triển khai

from cntk.io import StreamDef, StreamDefs, MinibatchSource, CTFDeserializer, INFINITY_REPEAT
labels_stream = StreamDef(field=’labels’, shape=3, is_sparse=False)
feature_stream = StreamDef(field=’features’, shape=4, is_sparse=False)
deserializer = CTFDeserializer(‘iris.ctf’, StreamDefs(labels=label_stream, features=features_stream)
Minibatch_source = MinibatchSource(deserializer, randomize=True)

Tạo tệp MCTF

Như bạn đã thấy ở trên, chúng tôi đang lấy dữ liệu từ tệp 'iris.ctf'. Nó có định dạng tệp được gọi là CNTK Text Format (CTF). Bắt buộc phải tạo tệp CTF để lấy dữ liệu choMinibatchSourceví dụ chúng tôi đã tạo ở trên. Hãy để chúng tôi xem cách chúng tôi có thể tạo tệp CTF.

Ví dụ triển khai

Step 1 - Đầu tiên, chúng ta cần nhập các gói gấu trúc và numpy như sau:

import pandas as pd
import numpy as np

Step 2- Tiếp theo, chúng ta cần tải tệp dữ liệu của mình, tức là iris.csv vào bộ nhớ. Sau đó, lưu trữ nó trongdf_source Biến đổi.

df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)

Step 3 - Bây giờ, bằng cách sử dụng ilocindexer như các tính năng, lấy nội dung của bốn cột đầu tiên. Ngoài ra, sử dụng dữ liệu từ cột loài như sau:

features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values

Step 4- Tiếp theo, chúng ta cần tạo một ánh xạ giữa tên nhãn và biểu diễn số của nó. Nó có thể được thực hiện bằng cách tạolabel_mapping như sau -

label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}

Step 5 - Bây giờ, chuyển đổi các nhãn thành một tập hợp các vectơ được mã hóa một lần như sau:

labels = [one_hot(label_mapping[v], 3) for v in labels]

Bây giờ, như chúng ta đã làm trước đây, hãy tạo một hàm tiện ích có tên one_hotđể mã hóa các nhãn. Nó có thể được thực hiện như sau:

def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result

Vì chúng tôi đã tải và xử lý trước dữ liệu, đã đến lúc lưu trữ nó trên đĩa ở định dạng tệp CTF. Chúng tôi có thể làm điều đó với sự trợ giúp của mã Python sau:

With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))

Tạo tệp MCTF - Hoàn thành ví dụ triển khai

import pandas as pd
import numpy as np
df_source = pd.read_csv(‘iris.csv’, names = [‘sepal_length’, ‘sepal_width’, ‘petal_length’, ‘petal_width’, ‘species’], index_col=False)
features = df_source.iloc[: , :4].values
labels = df_source[‘species’].values
label_mapping = {‘Iris-Setosa’ : 0, ‘Iris-Versicolor’ : 1, ‘Iris-Virginica’ : 2}
labels = [one_hot(label_mapping[v], 3) for v in labels]
def one_hot(index, length):
result = np.zeros(length)
result[index] = 1
return result
With open(‘iris.ctf’, ‘w’) as output_file:
for index in range(0, feature.shape[0]):
feature_values = ‘ ‘.join([str(x) for x in np.nditer(features[index])])
label_values = ‘ ‘.join([str(x) for x in np.nditer(labels[index])])
output_file.write(‘features {} | labels {} \n’.format(feature_values, label_values))

Cung cấp dữ liệu

Sau khi bạn tạo MinibatchSource,ví dụ, chúng ta cần đào tạo nó. Chúng ta có thể sử dụng cùng một logic đào tạo như được sử dụng khi chúng ta làm việc với các bộ dữ liệu nhỏ trong bộ nhớ. Ở đây, chúng tôi sẽ sử dụngMinibatchSource ví dụ như đầu vào cho phương thức train trên hàm mất mát như sau:

Ví dụ triển khai

Step 1 - Để ghi lại kết quả của phiên đào tạo, trước tiên hãy nhập ProgressPrinter từ cntk.logging mô-đun như sau -

from cntk.logging import ProgressPrinter

Step 2 - Tiếp theo, để thiết lập phiên đào tạo, nhập trainertraining_session từ cntk.train mô-đun như sau -

from cntk.train import Trainer,

Step 3 - Bây giờ, chúng ta cần xác định một số tập hợp các hằng số như minibatch_size, samples_per_epochnum_epochs như sau -

minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30

Step 4 - Tiếp theo, để biết CNTK đọc dữ liệu như thế nào trong quá trình huấn luyện, chúng ta cần xác định một ánh xạ giữa biến đầu vào cho mạng và các luồng trong nguồn minibatch.

input_map = {
     features: minibatch.source.streams.features,
     labels: minibatch.source.streams.features
}

Step 5 - Tiếp theo, để ghi đầu ra của quá trình đào tạo, hãy khởi tạo progress_printer biến với một mới ProgressPrinter ví dụ như sau -

progress_writer = ProgressPrinter(0)

Step 6 - Cuối cùng, chúng ta cần gọi phương thức tàu khi lỗ như sau:

train_history = loss.train(minibatch_source,
parameter_learners=[learner],
  model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)

Cung cấp dữ liệu - Hoàn thành ví dụ triển khai

from cntk.logging import ProgressPrinter
from cntk.train import Trainer, training_session
minbatch_size = 16
samples_per_epoch = 150
num_epochs = 30
input_map = {
   features: minibatch.source.streams.features,
   labels: minibatch.source.streams.features
}
progress_writer = ProgressPrinter(0)
train_history = loss.train(minibatch_source,
parameter_learners=[learner],
model_inputs_to_streams=input_map,
callbacks=[progress_writer],
epoch_size=samples_per_epoch,
max_epochs=num_epochs)

Đầu ra

-------------------------------------------------------------------
average   since   average   since  examples
loss      last     metric   last
------------------------------------------------------
Learning rate per minibatch: 0.1
1.21      1.21      0        0       32
1.15      0.12      0        0       96
[………]