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 numpy và Pandas 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 trainer và training_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_epoch và num_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
[………]