Содержание

База данных MNIST с рукописными цифрами — Azure Open Datasets

  • Чтение занимает 4 мин

В этой статье

База данных образцов рукописного написания цифр MNIST содержит 60 000 образцов наборов данных для обучения и тестовый набор из 10 000 образцов. Цифры были нормализованы по размеру и расположены в центре изображения фиксированного размера.

Примечание

Корпорация Майкрософт предоставляет Открытые наборы данных Azure как есть. Корпорация Майкрософт не предоставляет никаких гарантий (явных или подразумеваемых) и не определяет никаких условий в связи с использованием этих наборов данных. В рамках, допускаемых местным законодательством, корпорация Майкрософт отказывается от ответственности за ущерб и убытки (в том числе прямые, косвенные, специальные, опосредованные, случайные и штрафные), понесенные в результате использования вами этих наборов данных.

Этот набор данных предоставляется на тех же условиях, на которых корпорация Майкрософт получила исходные данные. Этот набор может включать данные, полученные от корпорации Майкрософт.

Набор данных получен из базы данных MNIST образцов рукописного написания цифр. Это часть большой базы данных рукописных форм и символов, опубликованной Национальным институтом стандартов и технологий США (NIST).

Расположение хранения

  • Учетная запись хранилища BLOB-объектов: azureopendatastorage
  • Имя контейнера: mnist

В контейнере доступно 4 файла:

  • train-images-idx3-ubyte.gz: набор изображений для обучения (9 912 422 байт)
  • train-labels-idx1-ubyte.gz: набор меток для обучения (28 881 байт)
  • t10k-images-idx3-ubyte.gz: набор изображений для тестирования (1 648 877 байт)
  • t10k-labels-idx1-ubyte.gz: набор меток для тестирования (4 542 байт)

Доступ к данным

Записные книжки Azure

Загрузите MNIST в кадр данных с помощью табличных наборов данных Машинного обучения Azure.

Дополнительные сведения о наборах данных в Машинном обучении Azure см. в статье о создании наборов данных Машинного обучения Azure.

Получение полного набора данных в кадре данных
from azureml.opendatasets import MNIST

mnist = MNIST.get_tabular_dataset()
mnist_df = mnist.to_pandas_dataframe()
mnist_df.info()
Получение кадров данных для обучения и тестирования
mnist_train = MNIST.get_tabular_dataset(dataset_filter='train')
mnist_train_df = mnist_train.to_pandas_dataframe()
X_train = mnist_train_df.drop("label", axis=1).astype(int).values/255.0
y_train = mnist_train_df.filter(items=["label"]).astype(int).values

mnist_test = MNIST.get_tabular_dataset(dataset_filter='test')
mnist_test_df = mnist_test.to_pandas_dataframe()
X_test = mnist_test_df.drop("label", axis=1).astype(int).values/255.0
y_test = mnist_test_df.filter(items=["label"]).astype(int).values
Вывод изображений некоторых цифр
%matplotlib inline
import numpy as np
import matplotlib.
pyplot as plt # now let's show some randomly chosen images from the traininng set. count = 0 sample_size = 30 plt.figure(figsize=(16, 6)) for i in np.random.permutation(X_train.shape[0])[:sample_size]: count = count + 1 plt.subplot(1, sample_size, count) plt.axhline('') plt.axvline('') plt.text(x=10, y=-10, s=y_train[i], fontsize=18) plt.imshow(X_train[i].reshape(28, 28), cmap=plt.cm.Greys) plt.show()

Скачайте или подключите необработанные файлы MNIST наборов данных службы «Машинное обучение Azure».

Это работает только для вычислительных ресурсов на базе Linux. Дополнительные сведения о наборах данных в Машинном обучении Azure см. в статье о создании наборов данных Машинного обучения Azure.

mnist_file = MNIST.get_file_dataset()
mnist_file
mnist_file.to_path()
Скачивание файлов в локальное хранилище
import os
import tempfile

data_folder = tempfile.mkdtemp()
data_paths = mnist_file. download(data_folder, overwrite=True)
data_paths
Подключите файлы. Полезно при запуске задания обучения на удаленном вычислительном ресурсе.
import gzip
import struct
import pandas as pd
import numpy as np

# load compressed MNIST gz files and return pandas dataframe of numpy arrays
def load_data(filename, label=False):
    with gzip.open(filename) as gz:
        gz.read(4)
        n_items = struct.unpack('>I', gz.read(4))
        if not label:
            n_rows = struct.unpack('>I', gz.read(4))[0]
            n_cols = struct.unpack('>I', gz.read(4))[0]
            res = np.frombuffer(gz.read(n_items[0] * n_rows * n_cols), dtype=np.uint8)
            res = res.reshape(n_items[0], n_rows * n_cols)
        else:
            res = np.frombuffer(gz.read(n_items[0]), dtype=np.uint8)
            res = res.reshape(n_items[0], 1)
    return pd.DataFrame(res)
import sys
mount_point = tempfile.mkdtemp()
print(mount_point)
print(os.
path.exists(mount_point)) if sys.platform == 'linux': print("start mounting....") with mnist_file.mount(mount_point): print("list dir...") print(os.listdir(mount_point)) print("get the dataframe info of mounted data...") train_images_df = load_data(next(path for path in data_paths if path.endswith("train-images-idx3-ubyte.gz"))) print(train_images_df.info())
%matplotlib inline
import numpy as np
import matplotlib.pyplot as plt
import urllib.request
import os

data_folder = os.path.join(os.getcwd(), 'data')
os.makedirs(data_folder, exist_ok=True)

urllib.request.urlretrieve('https://azureopendatastorage.blob.core.windows.net/mnist/train-images-idx3-ubyte.gz',
                           filename=os.path.join(data_folder, 'train-images.gz'))
urllib.request.urlretrieve('https://azureopendatastorage.blob.core.windows.net/mnist/train-labels-idx1-ubyte.gz',
                           filename=os.path.join(data_folder, 'train-labels.
gz')) urllib.request.urlretrieve('https://azureopendatastorage.blob.core.windows.net/mnist/t10k-images-idx3-ubyte.gz', filename=os.path.join(data_folder, 'test-images.gz')) urllib.request.urlretrieve('https://azureopendatastorage.blob.core.windows.net/mnist/t10k-labels-idx1-ubyte.gz', filename=os.path.join(data_folder, 'test-labels.gz'))
import gzip
import struct

# load compressed MNIST gz files and return numpy arrays
def load_data(filename, label=False):
    with gzip.open(filename) as gz:
        struct.unpack('I', gz.read(4))
        n_items = struct.unpack('>I', gz.read(4))
        if not label:
            n_rows = struct.unpack('>I', gz.read(4))[0]
            n_cols = struct.unpack('>I', gz.read(4))[0]
            res = np.frombuffer(gz.read(n_items[0] * n_rows * n_cols), dtype=np.uint8)
            res = res.reshape(n_items[0], n_rows * n_cols)
        else:
            res = np.frombuffer(gz.
read(n_items[0]), dtype=np.uint8) res = res.reshape(n_items[0], 1) return res
# note we also shrink the intensity values (X) from 0-255 to 0-1. This helps the model converge faster.
X_train = load_data(os.path.join(
    data_folder, 'train-images.gz'), False) / 255.0
X_test = load_data(os.path.join(data_folder, 'test-images.gz'), False) / 255.0
y_train = load_data(os.path.join(
    data_folder, 'train-labels.gz'), True).reshape(-1)
y_test = load_data(os.path.join(
    data_folder, 'test-labels.gz'), True).reshape(-1)

# now let's show some randomly chosen images from the traininng set.
count = 0
sample_size = 30
plt.figure(figsize=(16, 6))
for i in np.random.permutation(X_train.shape[0])[:sample_size]:
    count = count + 1
    plt.subplot(1, sample_size, count)
    plt.axhline('')
    plt.axvline('')
    plt.text(x=10, y=-10, s=y_train[i], fontsize=18)
    plt.imshow(X_train[i].reshape(28, 28), cmap=plt.cm.Greys)
plt.show()

Azure Databricks

Загрузите MNIST в кадр данных с помощью табличных наборов данных Машинного обучения Azure.

Дополнительные сведения о наборах данных в Машинном обучении Azure см. в статье о создании наборов данных Машинного обучения Azure.

Получение полного набора данных в кадре данных
# This is a package in preview.
from azureml.opendatasets import MNIST

mnist = MNIST.get_tabular_dataset()
mnist_df = mnist.to_spark_dataframe()
display(mnist_df.limit(5))

Скачайте или подключите необработанные файлы MNIST наборов данных службы «Машинное обучение Azure».

Это работает только для вычислительных ресурсов на базе Linux. Дополнительные сведения о наборах данных в Машинном обучении Azure см. в статье о создании наборов данных Машинного обучения Azure.

mnist_file = MNIST.get_file_dataset()
mnist_file
mnist_file.to_path()
Скачивание файлов в локальное хранилище
import os
import tempfile

mount_point = tempfile.mkdtemp()
mnist_file.download(mount_point, overwrite=True)
Подключите файлы.
Полезно при запуске задания обучения на удаленном вычислительном ресурсе.
import gzip
import struct
import pandas as pd
import numpy as np

# load compressed MNIST gz files and return numpy arrays
def load_data(filename, label=False):
    with gzip.open(filename) as gz:
        gz.read(4)
        n_items = struct.unpack('>I', gz.read(4))
        if not label:
            n_rows = struct.unpack('>I', gz.read(4))[0]
            n_cols = struct.unpack('>I', gz.read(4))[0]
            res = np.frombuffer(gz.read(n_items[0] * n_rows * n_cols), dtype=np.uint8)
            res = res.reshape(n_items[0], n_rows * n_cols)
        else:
            res = np.frombuffer(gz.read(n_items[0]), dtype=np.uint8)
            res = res.reshape(n_items[0], 1)
    return pd.DataFrame(res)
import sys
mount_point = tempfile.mkdtemp()
print(mount_point)
print(os.path.exists(mount_point))
print(os.listdir(mount_point))

if sys.platform == 'linux':
  print("start mounting. ...")
  with mnist_file.mount(mount_point):
    print(context.mount_point )
    print(os.listdir(mount_point))  
    train_images_df = load_data(os.path.join(mount_point, 'train-images-idx3-ubyte.gz'))
    print(train_images_df.info())

Пример для этого сочетания платформы и пакета недоступен.

Дальнейшие действия

Ознакомьтесь с другими наборами в каталоге Открытых наборов данных.

scikit-learn — Распознавание рукописных цифр — Этот пример показывает,как scikit-learn может быть использован для распознавания

Этот пример показывает,как scikit-learn может быть использован для распознавания изображений рукописных цифр от 0-9.

print(__doc__)





import matplotlib.pyplot as plt


from sklearn import datasets, svm, metrics
from sklearn.model_selection import train_test_split



Digits dataset

Набор данных digits состоит из изображений цифр размером 8×8 пикселей. В images атрибутов из набора данных магазинов 8×8 массивы значений градаций серого для каждого изображения. Мы будем использовать эти массивы для визуализации первых 4 изображений. target атрибут из набора данных хранит цифра каждое изображение представляет собой , и это входит в названии 4 участков ниже.

Примечание: если бы мы работали с файлами изображений (например, файлами ‘png’), мы бы загружали их с помощью matplotlib.pyplot.imread .

digits = datasets.load_digits()

_, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))
for ax, image, label in zip(axes, digits.images, digits.target):
    ax.set_axis_off()
    ax.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
    ax.set_title('Training: %i' % label)

Classification

Чтобы применить классификатор к этим данным, нам нужно сгладить изображения, превратив каждый двумерный массив значений оттенков серого из shape (8, 8) в shape (64,) . Впоследствии весь набор данных будет иметь форму (n_samples, n_features) , где n_samples — это количество изображений, а n_features — это общее количество пикселей в каждом изображении.

Затем мы можем разделить данные на обучающие и тестовые подмножества и установить классификатор опорных векторов на обучающих выборках.Полученный классификатор может быть использован для прогнозирования значения цифры для образцов в тестовом подмножестве.

n_samples = len(digits.images)
data = digits.images.reshape((n_samples, -1))


clf = svm.SVC(gamma=0.001)


X_train, X_test, y_train, y_test = train_test_split(
    data, digits.target, test_size=0.5, shuffle=False)


clf.fit(X_train, y_train)


predicted = clf.predict(X_test)

Ниже мы визуализируем первые 4 тестовых образца и показываем их предсказанное цифровое значение в заголовке.

_, axes = plt.subplots(nrows=1, ncols=4, figsize=(10, 3))
for ax, image, prediction in zip(axes, X_test, predicted):
    ax. set_axis_off()
    image = image.reshape(8, 8)
    ax.imshow(image, cmap=plt.cm.gray_r, interpolation='nearest')
    ax.set_title(f'Prediction: {prediction}')

classification_report строит текстовый отчет, показывающий основные показатели классификации.

print(f"Classification report for classifier {clf}:\n"
      f"{metrics.classification_report(y_test, predicted)}\n")

Out:

Classification report for classifier SVC(gamma=0.001):
              precision    recall  f1-score   support

           0       1.00      0.99      0.99        88
           1       0.99      0.97      0.98        91
           2       0.99      0.99      0.99        86
           3       0.98      0.87      0.92        91
           4       0.99      0.96      0.97        92
           5       0.95      0.97      0.96        91
           6       0.99      0.99      0.99        91
           7       0.96      0.99      0.97        89
           8       0.94      1. 00      0.97        88
           9       0.93      0.98      0.95        92

    accuracy                           0.97       899
   macro avg       0.97      0.97      0.97       899
weighted avg       0.97      0.97      0.97       899

Мы также можем построить матрицу путаницы истинных цифровых значений и предсказанных цифровых значений.

disp = metrics.plot_confusion_matrix(clf, X_test, y_test)
disp.figure_.suptitle("Confusion Matrix")
print(f"Confusion matrix:\n{disp.confusion_matrix}")

plt.show()

Out:

Confusion matrix:
[[87  0  0  0  1  0  0  0  0  0]
 [ 0 88  1  0  0  0  0  0  1  1]
 [ 0  0 85  1  0  0  0  0  0  0]
 [ 0  0  0 79  0  3  0  4  5  0]
 [ 0  0  0  0 88  0  0  0  0  4]
 [ 0  0  0  0  0 88  1  0  0  2]
 [ 0  1  0  0  0  0 90  0  0  0]
 [ 0  0  0  0  0  1  0 88  0  0]
 [ 0  0  0  0  0  0  0  0 88  0]
 [ 0  0  0  1  0  1  0  0  0 90]]

Общее время работы скрипта: (0 минут 0,925 секунды)

КНН алгоритм Case — Рукописные цифры распознавания

import numpy as np
import matplotlib . pyplot as plt 
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
# 加载数据
img_arr = plt.imread('./data/8/8_88.bmp')
plt.imshow(img_arr)
<matplotlib.image.AxesImage at 0x1786b073780>

img_arr.shape  # 图片的像素为28*28,对应的numpy数组是二维
(28, 28)
# 提取样本数据
feature = []
target = []
for i in range(10): # i表示的文件夹的名称
    for j in range(1,501):
        img_path = './data/'+str(i)+'/'+str(i)+'_'+str(j)+'.bmp'
        img_arr = plt.imread(img_path)
        feature.append(img_arr)
        target.append(i)
# 提取样本数据
feature = np.array(feature)  # 必须保证是二维
target = np.array(target)
feature.shape  # 目前的特征是3维
(5000, 28, 28)
# 特征处理:将三维的特征变形成二维
feature = feature.reshape((5000,-1))
feature.shape
(5000, 784)
  • Резюме: данные функция функции хранятся в данном в 5000-мерном изображении

  • Разделение данных выборки

# 对样本数据进行打乱
np.random.seed(10)
np.random.shuffle(feature)
np.random.seed(10)
np.random.shuffle(target)
# 拆分
x_train = feature[:4950]
y_train = target[:4950]
x_test = feature[4950:]
y_test = target[4950:]
  • Инстанцировать объектную модель, а затем обучение
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(x_train,y_train)
knn.score(x_test,y_test)
0.98
print('真实的分类结果:',y_test)
print('模型的分类结果:',knn.predict(x_test))
真实的分类结果: [1 2 2 3 9 1 7 9 8 5 5 4 9 0 7 0 3 5 0 7 2 7 1 2 0 8 8 6 1 1 6 6 4 4 0 8 5
 8 2 2 4 3 3 9 4 2 6 2 9 2]
模型的分类结果: [1 2 2 3 9 1 7 9 8 5 5 4 9 0 7 0 3 5 0 7 2 7 1 2 0 8 8 6 1 1 6 6 4 4 0 8 5
 8 2 2 4 3 3 9 4 1 6 2 9 2]
  • Сохранить модель
from sklearn.externals import joblib
joblib.dump(knn,'./knn.m')
['./knn.m']
knn = joblib.load('./knn.m')
knn
KNeighborsClassifier(algorithm='auto', leaf_size=30, metric='minkowski',
           metric_params=None, n_jobs=1, n_neighbors=5, p=2,
           weights='uniform')
  • Используйте модель для идентификации внешних цифровых изображений
img_arr = plt.imread('./数字.jpg')
plt.imshow(img_arr)
<matplotlib.image.AxesImage at 0x1786b3da7b8>

img_arr.shape
(241, 257, 3)
eight_img = img_arr[180:235,90:130,:]
plt.imshow(eight_img)
<matplotlib.image.AxesImage at 0x1786bc14e48>

feature[0].shape   # 模型可以识别的图片
(784,)
  • Размерный модель может идентифицировать изображение зависит от данных выборки
    • Можно идентифицировать изображение составляет 28 * 28 пикселей
    • Картина не цвет этого измерения
    • Модель идентификации фотографии (784)
eight_img.shape
(55, 40, 3)
eight_img = eight_img.mean(axis=2)    # 降维
eight_img.shape
(55, 40)
  • Чтобы удалить изображение после того, как степень сжатия размерности пикселей и т.д.
import scipy.ndimage as ndimage
eight_img = ndimage.zoom(eight_img,zoom=(28/55,28/40))
eight_img.shape
C:\anaconda3\lib\site-packages\scipy\ndimage\interpolation.py:616: UserWarning: From scipy 0.13.0, the output shape of zoom() is calculated with round() instead of int() - for these inputs the size of the returned array has changed.
  "the returned array has changed.", UserWarning)





(28, 28)
eight_img = eight_img.reshape(1,-1)
eight_img.shape
(1, 784)
knn.predict(eight_img)
array([8])

Как использовать нейронные сети для распознавания рукописных цифр Ru Python

Основываясь на приведенном ниже примере, вы можете добавить функцию для прогнозирования в класс NeuralNetwork :

 def predict(self, image): return np.argmax(self.__feedforward(image.astype(bool).astype(int))) 

Как только вы успешно обучите свою нейронную сеть, вы можете предсказать неизвестную цифру с точностью до 97% с:

 prediction = NN.predict(image) 

Выдержка из Neural Networks – Начало работы: простой ANN с Python . Оригинальные авторы были cᴏʟᴅsᴘᴇᴇᴅ и dontloo . Сведения о атрибуции можно найти на странице участника . Источник лицензируется по CC BY-SA 3.0 и может быть найден в архиве документации . Номер ссылки: 2709 и пример ID: 9069.

В приведенном ниже списке кода делается попытка классифицировать рукописные цифры из набора данных MNIST. Цифры выглядят так:

Код будет предварительно обрабатывать эти цифры, преобразовывая каждое изображение в 2D-массив из 0 и 1, а затем использовать эти данные для обучения нейронной сети с точностью до 97% (50 эпох).

 """ Deep Neural Net (Name: Classic Feedforward) """ import numpy as np import pickle, json import sklearn.datasets import random import time import os def sigmoid(z): return 1.0 / (1.0 + np.exp(-z)) def sigmoid_prime(z): return sigmoid(z) * (1 - sigmoid(z)) def relU(z): return np.maximum(z, 0, z) def relU_prime(z): return z * (z <= 0) def tanh(z): return np.tanh(z) def tanh_prime(z): return 1 - (tanh(z) ** 2) def transform_target(y): t = np.zeros((10, 1)) t[int(y)] = 1.0 return t """--------------------------------------------------------------------------------""" class NeuralNet: def __init__(self, layers, learning_rate=0.05, reg_lambda=0.01): self.num_layers = len(layers) self.layers = layers self.biases = [np.zeros((y, 1)) for y in layers[1:]] self.weights = [np.random.normal(loc=0.0, scale=0.1, size=(y, x)) for x, y in zip(layers[:-1], layers[1:])] self.learning_rate = learning_rate self.reg_lambda = reg_lambda self.nonlinearity = relU self.nonlinearity_prime = relU_prime def __feedforward(self, x): """ Returns softmax probabilities for the output layer """ for w, b in zip(self.weights, self.biases): x = self.nonlinearity(np.dot(w, np.reshape(x, (len(x), 1))) + b) return np.exp(x) / np.sum(np.exp(x)) def __backpropagation(self, x, y): """ :param x: input :param y: target """ weight_gradients = [np.zeros(w.shape) for w in self.weights] bias_gradients = [np.zeros(b.shape) for b in self.biases] # forward pass activation = x hidden_activations = [np.reshape(x, (len(x), 1))] z_list = [] for w, b in zip(self.weights, self.biases): z = np.dot(w, np.reshape(activation, (len(activation), 1))) + b z_list.append(z) activation = self.nonlinearity(z) hidden_activations.append(activation) t = hidden_activations[-1] hidden_activations[-1] = np.exp(t) / np.sum(np.exp(t)) # backward pass delta = (hidden_activations[-1] - y) * (z_list[-1] > 0) weight_gradients[-1] = np.dot(delta, hidden_activations[-2].T) bias_gradients[-1] = delta for l in range(2, self.num_layers): z = z_list[-l] delta = np.dot(self.weights[-l + 1].T, delta) * (z > 0) weight_gradients[-l] = np.dot(delta, hidden_activations[-l - 1].T) bias_gradients[-l] = delta return (weight_gradients, bias_gradients) def __update_params(self, weight_gradients, bias_gradients): for i in xrange(len(self.weights)): self.weights[i] += -self.learning_rate * weight_gradients[i] self.biases[i] += -self.learning_rate * bias_gradients[i] def train(self, training_data, validation_data=None, epochs=10): bias_gradients = None for i in xrange(epochs): random.shuffle(training_data) inputs = [data[0] for data in training_data] targets = [data[1] for data in training_data] for j in xrange(len(inputs)): (weight_gradients, bias_gradients) = self.__backpropagation(inputs[j], targets[j]) self.__update_params(weight_gradients, bias_gradients) if validation_data: random.shuffle(validation_data) inputs = [data[0] for data in validation_data] targets = [data[1] for data in validation_data] for j in xrange(len(inputs)): (weight_gradients, bias_gradients) = self.__backpropagation(inputs[j], targets[j]) self.__update_params(weight_gradients, bias_gradients) print("{} epoch(s) done".format(i + 1)) print("Training done.") def test(self, test_data): test_results = [(np.argmax(self.__feedforward(x[0])), np.argmax(x[1])) for x in test_data] return float(sum([int(x == y) for (x, y) in test_results])) / len(test_data) * 100 def dump(self, file): pickle.dump(self, open(file, "wb")) """--------------------------------------------------------------------------------""" if __name__ == "__main__": total = 5000 training = int(total * 0.7) val = int(total * 0.15) test = int(total * 0.15) mnist = sklearn.datasets.fetch_mldata('MNIST original', data_home='./data') data = zip(mnist.data, mnist.target) random.shuffle(data) data = data[:total] data = [(x[0].astype(bool).astype(int), transform_target(x[1])) for x in data] train_data = data[:training] val_data = data[training:training+val] test_data = data[training+val:] print "Data fetched" NN = NeuralNet([784, 32, 10]) # defining an ANN with 1 input layer (size 784 = size of the image flattened), 1 hidden layer (size 32), and 1 output layer (size 10, unit at index i will predict the probability of the image being digit i, where 0 <= i <= 9) NN.train(train_data, val_data, epochs=5) print "Network trained" print "Accuracy:", str(NN.test(test_data)) + "%" 

Это самодостаточный образец кода и может запускаться без каких-либо дополнительных изменений. Убедитесь, что у вас установлена scikit numpy и scikit для вашей версии python.

Распознать рукописный текст (преимущественно цифры)

 
Артем Билецкий   (2013-11-25 19:01) [0]

Кто-нибудь в курсе как сделать? Может, что готовое есть (платное/бесплатное). Компоненты, библиотеки, да что угодно.

Спасибо


 
brother ©   (2013-11-25 19:38) [1]

fine reader с задачей справляется?


 
все арамисы, а я Дартаньян   (2013-11-25 21:07) [2]


> Кто-нибудь в курсе как сделать? Может, что готовое есть
> (платное/бесплатное). Компоненты, библиотеки, да что угодно.
Та там всё просто… Очищаем от высокочастотного шума, сегментируем, строим скелетную модель (методом выгорания, к примеру), отбрасываем конечные сегменты, загоняем в классификатор… *сатанинский смех*


 
все арамисы, а я Дартаньян   (2013-11-25 21:09) [3]

а вообще у файн-ридера был ком-интерфейсец, который всё это позволяет. вот буквально так, вызовом четырёх процедур. только там какие-то злые ограничения были в десктопной версии.


 
RDen ©   (2013-11-25 21:38) [4]


> Артем Билецкий   (25.11.13 19:01)
>
> Кто-нибудь в курсе как сделать?

нобелевскую хочешь получить?


 
KilkennyCat ©   (2013-11-25 21:56) [5]


> преимущественно цифры

во-первых, если даже хоть одна буква — то уже пофиг «преимущественно».
во-вторых, римский цифры — буквенны
в-третьих, общему алгоритму пофиг, что распознавать.


> да что угодно.

с каждым сканером в комплекте дпется версия какой-нить программы.
ну и напоследок: http://lmgtfy.com/?q=ocr


 
RDen ©   (2013-11-25 22:14) [6]


> KilkennyCat ©   (25.11.13 21:56) [5]
>
>
> > преимущественно цифры

а под цифрами, наверно ещё и числа подразумеваются…


 
robt5   (2013-11-25 22:43) [7]

в винде какбы есть рукописный ввод уже давно и соответствующие интерфейсы


 
все арамисы, а я Дартаньян   (2013-11-25 23:03) [8]


> в винде какбы есть рукописный ввод уже давно и соответствующие
> интерфейсы
рукописный ввод и распознавание сканов — это очень разные задачи. а что нужно топикстартеру, пока неясно.


 
Person ©   (2013-11-26 00:47) [9]

Сложно и дорого.

Из всех виденных мною решений с рукописным лучше всех справляется параскрипт. Если писатель может попадать в ячейку, то можно достичь весьма неплохих результатов (даже 99%, для чисел).

Home

Тоже самое, но на русском: http://idr.in.ua
В картинках: http://idr.in.ua/info/scheme-formxtra.html


 
Артем Билецкий   (2013-11-26 11:45) [10]

1. FN не справляется. Пробовал
2. Распознавание сканов (документов, которые будут отсканированы)
3. Числа (0..999)


 
брат Птибурдукова   (2013-11-26 12:14) [11]


> 1. FN не справляется. Пробовал
FN — это Fine Reader?
Попробуй ещё Abbyy Form Reader. После настройки «поле числовое» и «заполнял русский» процент успешных распознаваний сильно вырастет.


 
Артем Билецкий   (2013-11-26 12:26) [12]


> Попробуй ещё Abbyy Form Reader.

Снят с поддержки по описанию. На счет «сильно выростает». Можно подробнее? Насколько сильно?


 
брат Птибурдукова   (2013-11-26 12:44) [13]

Ну на курсах распознавание «просто каких-то закорючек» давало около 20% распознанных символов. После настройки «здесь записаны цифры, а не что попало» стало около 80% распознанных цифр. (Для текстовых полей там ещё задаётся язык заполнения, но нам это неинтересно.)  После настройки «культуры заполнителя» (ну или что-то в таком плане) распознавать стало около 95-98%%.

Но надо понимать, что на обучении и в бою результаты могут быть сильно разными.


 
Артем Билецкий   (2013-11-26 12:49) [14]


> После настройки «культуры заполнителя» (ну или что-то в
> таком плане) распознавать стало около 95-98%

Это 95-98% правильных ответов. Или 95%-98% ответов, которые, возможно, еще и содержат ошибки?

А остальные 5-3% куда?


 
брат Птибурдукова   (2013-11-26 12:56) [15]


> Артем Билецкий   (26.11.13 12:49) [14]
Честно — не особо помню уже. Насколько я помню, часть цифр подсвечивалась «возможно, распознано неправильно» (и около трети действительно было неправильно), остальные были нераспознаны. В тех, которые система объявила «уверенно распознанными», ошибок не находил.


 
[ВладОшин] ©   (2013-11-27 20:52) [16]

http://cognitiveforms.ru/products/cuneiform/
если будете смотреть и поможет, отпишитесь плиз


 
Person ©   (2013-11-28 01:44) [17]


> http://cognitiveforms.ru/products/cuneiform/
> если будете смотреть и поможет, отпишитесь плиз

А что там смотреть? Необходимо отсканировать десяток листов и послать во все 3 конторы. Ну а дальше смотреть на точность и процент ручного ввода. Как бы, все.

Из описанного мною случая выше было следующее:
1) объем 1000-1500 страниц в неделю
2) результат распознавания любой недели всегда выше 99%. Обычно по разному, т.к. новые люди приходят/уходят (что-то типа 99,2-99,3).
3) порядка 10% всегда идет на проверку человеком

Из интересного. Руководство не устроил результат в 99,2 (для понимания, это 2-3 ошибки на 500 ячеек рукописного). Посадили несколько бабушек на проверку)))
Потом решили, что и бабушки долго проверяют. Ввели контрольную ячейку. В итоге, одна бабушка могла преврать из 99,3% в 100% за 1 час.
Что-то типа такого: http://idr.in.ua/info/docscorrection.html


 
Person ©   (2013-11-28 02:04) [18]


> В итоге, одна бабушка могла преврать из 99,3% в 100% за
> 1 час.

=превратить ))


 
Person ©   (2013-11-28 02:05) [19]


> В итоге, одна бабушка могла преврать из 99,3% в 100% за
> 1 час.

=превратить ))


 
Inovet ©   (2013-11-28 04:44) [20]

Контрольная сумма нужна.


распознавание рукописных цифр —  Искусственный интеллект

Страница 1 из 4

Задача распознавания рукописных цифр является важной во многих приложениях, включая автоматизированную сортировку почты по почтовому коду, автоматизированное чтение чеков и налоговых деклараций, а также ввод данных для портативных компьютеров. В этой области достигнут быстрый прогресс отчасти благодаря применению лучших алгоритмов обучения и отчасти благодаря наличию лучших обучающих наборов. В Национальном институте стандартов и технологии (National Institute of Standards and Technology — NIST) США был создан архив, представляющий собой базу данных из 60 000 рукописных цифр с расшифровками (с так называемой разметкой), каждая из которых задана в виде изображения, состоящего из 2 0x20=400 пикселов с восьмибитовой кодировкой уровня серого. Распознавание цифр из этой базы данных стало одной из стандартных эталонных задач для сравнения новых алгоритмов обучения. Некоторые примеры цифр показаны на рис. 20.27.

Рис. 20.27. Примеры из базы данных рукописных цифр института NIST. Верхний ряд: примеры цифр 0—9, которые несложно распознать; нижний ряд: более трудные примеры тех же цифр

Для решения этой задачи было опробовано много разных подходов к обучению. Одним из первых и, по-видимому, самых простых стал классификатор по трем ближайшим соседним точкам, преимуществом которого является также то, что он не требует затрат времени на обучение. Но поскольку он представляет собой алгоритм, основанный на использовании памяти, то должен хранить все 60 000 изображений, поэтому показывает низкую производительность на этапе прогона. При использовании такого классификатора была достигнута частота ошибок при распознавании проверочного набора, равная 2,4%.

Кроме того, для решения этой задачи была разработана нейронная сеть с одним скрытым слоем, состоящая из 400 входных элементов (по одному на каждый пиксел) и 10 выходных элементов (по одному на каждый класс). С использованием перекрестной проверки было обнаружено, что наилучшую производительность обеспечивают примерно 300 скрытых элементов. Поскольку была предусмотрена полная связность между слоями, общее количество весов составляло 123300. Эта сеть позволила достичь уровня частоты ошибок 1,6%.


Как построить нейронную сеть для распознавания рукописных цифр с TensorFlow

Вступление

Нейронные сети используются как метод глубокого обучения, одно из многих подразделов искусственного интеллекта. Они были впервые предложены около 70 лет назад как попытка смоделировать работу человеческого мозга, хотя и в гораздо более упрощенной форме. Отдельные «нейроны» соединены в слои, причем веса назначены для определения того, как нейрон реагирует, когда сигналы распространяются через сеть. Ранее нейронные сети были ограничены числом нейронов, которые они могли имитировать, и, следовательно, сложностью обучения, которую они могли достичь. Но в последние годы благодаря прогрессу в разработке аппаратного обеспечения мы смогли построить очень глубокие сети и обучить их огромным наборам данных для достижения прорывов в области машинного интеллекта.

Эти открытия позволили машинам соответствовать и превосходить возможности людей при выполнении определенных задач. Одной из таких задач является распознавание объектов. Хотя машины исторически были неспособны соответствовать человеческому зрению, последние достижения в области глубокого обучения позволили построить нейронные сети, которые могут распознавать объекты, лица, текст и даже эмоции.

В этом уроке вы реализуете небольшой подраздел распознавания и распознавания цифр. Используя TensorFlow, библиотеку Python с открытым исходным кодом, разработанную лабораториями Google Brain для глубоких исследований, вы будете рисовать нарисованные от руки изображения с номерами 0-9, строить и обучать нейронная сеть для распознавания и прогнозирования правильной метки для отображаемой цифры.

Хотя вам не понадобится предыдущий опыт практического глубокого обучения или TensorFlow, чтобы следовать этому учебному пособию, мы немного ознакомимся с терминами и концепциями машинного обучения, такими как обучение и тестирование, функции и ярлыки, оптимизация и оценка. Вы можете узнать больше об этих понятиях в An Введение в машинное обучение.

Предпосылки

Для завершения этого урока вам понадобится:

  • Локальная Python 3 среда разработки, включая https : //pypi.org/project/pip/ [pip], инструмент для установки пакетов Python и venv, для создания виртуальных сред.

Шаг 1 — Настройка проекта

Прежде чем вы сможете разработать программу распознавания, вам нужно установить несколько зависимостей и создать рабочее пространство для хранения ваших файлов.

Мы будем использовать виртуальную среду Python 3 для управления зависимостями нашего проекта. Создайте новый каталог для вашего проекта и перейдите к новому каталогу:

mkdir tensorflow-demo
cd tensorflow-demo

Выполните следующие команды, чтобы настроить виртуальную среду для этого учебника:

python3 -m venv tensorflow-demo
source tensorflow-demo/bin/activate

Затем установите библиотеки, которые вы будете использовать в этом руководстве. Мы будем использовать конкретные версии этих библиотек, создав в каталоге проекта файл + needs.txt +, в котором указаны требование и версия, которая нам нужна. Создайте файл + needs.txt +:

Откройте файл в текстовом редакторе и добавьте следующие строки, чтобы указать библиотеки Image, NumPy и TensorFlow и их версии:

image==1.5.20
numpy==1.14.3
tensorflow==1.4.0

Сохраните файл и выйдите из редактора. Затем установите эти библиотеки с помощью следующей команды:

pip install -r requirements.txt

Установив зависимости, мы можем начать работу над нашим проектом.

Шаг 2 — Импорт набора данных MNIST

Набор данных, который мы будем использовать в этом руководстве, называется набором данных MNIST и является классическим в сообществе машинного обучения. Этот набор данных состоит из изображений рукописных цифр размером 28×28 пикселей. Вот несколько примеров цифр, включенных в набор данных:

изображение: https: //assets.digitalocean.com/articles/handwriting_tensorflow_python3/wBCHXId.png [Примеры изображений MNIST]

Давайте создадим программу Python для работы с этим набором данных. Мы будем использовать один файл для всей нашей работы в этом уроке. Создайте новый файл с именем + main.py +:

Теперь откройте этот файл в выбранном вами текстовом редакторе и добавьте следующую строку кода в файл для импорта библиотеки TensorFlow:

Добавьте следующие строки кода в ваш файл, чтобы импортировать набор данных MNIST и сохранить данные изображения в переменной + mnist +:

...
from tensorflow.examples.tutorials.mnist import input_data


mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)  # y labels are oh-encoded

При чтении данных мы используем горячее кодирование для представления меток (фактически нарисованная цифра, например, «3») изображений. Горячее кодирование использует вектор двоичных значений для представления числовых или категориальных значений. Поскольку наши метки предназначены для цифр 0-9, вектор содержит десять значений, по одному на каждую возможную цифру. Одно из этих значений установлено в 1, чтобы представить цифру в этом индексе вектора, а остальные установлены в 0. Например, цифра 3 представлена ​​с помощью вектора + [0, 0, 0, 1, 0, 0, 0, 0, 0, 0] +. Поскольку значение в индексе 3 хранится как 1, вектор представляет цифру 3.

Чтобы представить сами фактические изображения, 28×28 пикселей сведены в одномерный вектор, который имеет размер 784 пикселей. Каждый из 784 пикселей, составляющих изображение, сохраняется как значение от 0 до 255. Это определяет оттенки серого пикселя, поскольку наши изображения представлены только в черно-белом режиме. Таким образом, черный пиксель представлен 255, а белый пиксель — 0 с различными оттенками серого где-то посередине.

Мы можем использовать переменную + mnist +, чтобы узнать размер набора данных, который мы только что импортировали. Глядя на + num_examples + для каждого из трех подмножеств, мы можем определить, что набор данных был разбит на 55 000 изображений для обучения, 5000 для проверки и 10 000 для тестирования. Добавьте следующие строки в ваш файл:

...
n_train = mnist.train.num_examples  # 55,000
n_validation = mnist.validation.num_examples  # 5000
n_test = mnist.test.num_examples  # 10,000

Теперь, когда наши данные импортированы, пришло время подумать о нейронной сети.

Шаг 3 — Определение архитектуры нейронной сети

Архитектура нейронной сети относится к таким элементам, как количество уровней в сети, количество блоков на каждом уровне и то, как эти блоки связаны между уровнями. Поскольку нейронные сети слабо вдохновлены работой человеческого мозга, здесь термин единица используется для представления того, что мы биологически считаем нейроном. Подобно нейронам, передающим сигналы по всему мозгу, единицы принимают некоторые значения из предыдущих единиц в качестве входных данных, выполняют вычисления, а затем передают новое значение в качестве вывода другим единицам. Эти единицы имеют многоуровневую структуру, начиная как минимум с одного слоя для ввода значений и одного слоя для вывода значений. Термин «скрытый слой» используется для всех слоев между входным и выходным слоями, т.е. те, «скрытые» от реального мира.

Разные архитектуры могут давать совершенно разные результаты, поскольку производительность можно рассматривать как функцию архитектуры, в том числе от параметров, данных и продолжительности обучения.

Добавьте следующие строки кода в ваш файл, чтобы сохранить количество единиц на слой в глобальных переменных. Это позволяет нам изменять сетевую архитектуру в одном месте, и в конце урока вы можете сами проверить, как различное количество слоев и единиц будет влиять на результаты нашей модели:

...
n_input = 784  # input layer (28x28 pixels)
n_hidden1 = 512  # 1st hidden layer
n_hidden2 = 256  # 2nd hidden layer
n_hidden3 = 128  # 3rd hidden layer
n_output = 10  # output layer (0-9 digits)

Следующая диаграмма показывает визуализацию архитектуры, которую мы разработали, с каждым слоем, полностью связанным с окружающими слоями:

изображение: https: //assets.digitalocean.com/articles/handwriting_tensorflow_python3/cnwitLM.png [Диаграмма нейронной сети]

Термин «глубокая нейронная сеть» относится к числу скрытых слоев, причем «мелкий» обычно означает только один скрытый слой, а «глубокий» относится к нескольким скрытым слоям. Учитывая достаточное количество обучающих данных, неглубокая нейронная сеть с достаточным количеством единиц теоретически должна быть способна представлять любую функцию, которую может выполнять глубокая нейронная сеть. Но зачастую вычислительно более эффективно использовать более глубокую нейронную сеть меньшего размера для решения той же задачи, которая требует мелкой сети с экспоненциально большим количеством скрытых блоков. Неглубокие нейронные сети также часто сталкиваются с переоснащением, когда сеть по существу запоминает обучающие данные, которые она видела, и не может обобщать знания для новых данных. Вот почему глубокие нейронные сети используются чаще: множественные слои между необработанными входными данными и выходной меткой позволяют сети изучать функции на различных уровнях абстракции, делая саму сеть более способной к обобщению.

Другими элементами нейронной сети, которые необходимо определить здесь, являются гиперпараметры. В отличие от параметров, которые будут обновляться во время обучения, эти значения устанавливаются изначально и остаются постоянными в течение всего процесса. В вашем файле установите следующие переменные и значения:

...
learning_rate = 1e-4
n_iterations = 1000
batch_size = 128
dropout = 0.5

Скорость обучения показывает, насколько параметры будут корректироваться на каждом этапе процесса обучения. Эти корректировки являются ключевым компонентом обучения: после каждого прохода по сети мы слегка настраиваем веса, чтобы попытаться уменьшить потери. Более высокие скорости обучения могут сходиться быстрее, но также могут привести к превышению оптимальных значений при их обновлении. Количество итераций относится к тому, сколько раз мы пройдем этап обучения, а размер пакета относится к тому, сколько примеров обучения мы используем на каждом этапе. Переменная + dropout + представляет собой порог, при котором мы исключаем некоторые единицы случайным образом. Мы будем использовать + dropout + в нашем последнем скрытом слое, чтобы дать каждому юниту 50% шанс быть уничтоженным на каждом этапе обучения. Это помогает предотвратить переоснащение.

Теперь мы определили архитектуру нашей нейронной сети и гиперпараметры, которые влияют на процесс обучения. Следующим шагом является построение сети в виде графа TensorFlow.

Шаг 4 — Построение графика TensorFlow

Чтобы построить нашу сеть, мы настроим сеть как вычислительный граф для выполнения TensorFlow. Основная концепция TensorFlow — tensor, структура данных, похожая на массив или список. инициализируются, обрабатываются по мере их прохождения через граф и обновляются в процессе обучения.

Мы начнем с определения трех тензоров как placeholder, которые являются тензорами, в которые мы будем вводить значения позже. Добавьте следующее в ваш файл:

...
X = tf.placeholder("float", [None, n_input])
Y = tf.placeholder("float", [None, n_output])
keep_prob = tf.placeholder(tf.float32)

Единственный параметр, который необходимо указать при его объявлении, — это размер данных, которые мы будем вводить. Для + X + мы используем форму + [None, 784] +, где + None + представляет любое количество, так как мы будем вводить неопределенное количество 784-пиксельных изображений. Форма + Y + имеет вид + [None, 10] +, так как мы будем использовать его для неопределенного числа выходных меток с 10 возможными классами. Тензор + keep_prob + используется для управления частотой отсева, и мы инициализируем его как заполнитель, а не как неизменную переменную, потому что мы хотим использовать один и тот же тензор для обучения (когда для + dropout + установлено значение +0.5+ `) и тестирование (когда + dropout + установлено в + 1.0 + `).

Параметры, которые сеть обновит в процессе обучения, это значения + weight + и + bias +, поэтому для них нам нужно установить начальное значение, а не пустой заполнитель. Эти значения в основном там, где сеть обучается, так как они используются в функциях активации нейронов, представляя силу связей между единицами.

Поскольку значения оптимизируются во время обучения, мы можем установить их на ноль на данный момент. Но первоначальное значение на самом деле оказывает существенное влияние на конечную точность модели. Мы будем использовать случайные значения из усеченного нормального распределения для весов. Мы хотим, чтобы они были близки к нулю, чтобы они могли настраиваться как в положительном, так и в отрицательном направлении, и немного отличаться, чтобы они генерировали разные ошибки. Это гарантирует, что модель узнает что-то полезное. Добавьте эти строки:

...
weights = {
   'w1': tf.Variable(tf.truncated_normal([n_input, n_hidden1], stddev=0.1)),
   'w2': tf.Variable(tf.truncated_normal([n_hidden1, n_hidden2], stddev=0.1)),
   'w3': tf.Variable(tf.truncated_normal([n_hidden2, n_hidden3], stddev=0.1)),
   'out': tf.Variable(tf.truncated_normal([n_hidden3, n_output], stddev=0.1)),
}

Для смещения мы используем небольшое постоянное значение, чтобы гарантировать, что тензоры активируются на начальных стадиях и, следовательно, способствуют распространению. Веса и тензоры смещения хранятся в словарных объектах для удобства доступа. Добавьте этот код в ваш файл, чтобы определить смещения:

...
biases = {
   'b1': tf.Variable(tf.constant(0.1, shape=[n_hidden1])),
   'b2': tf.Variable(tf.constant(0.1, shape=[n_hidden2])),
   'b3': tf.Variable(tf.constant(0.1, shape=[n_hidden3])),
   'out': tf.Variable(tf.constant(0.1, shape=[n_output]))
}

Затем настройте слои сети, определив операции, которые будут манипулировать тензорами. Добавьте эти строки в ваш файл:

...
layer_1 = tf.add(tf.matmul(X, weights['w1']), biases['b1'])
layer_2 = tf.add(tf.matmul(layer_1, weights['w2']), biases['b2'])
layer_3 = tf.add(tf.matmul(layer_2, weights['w3']), biases['b3'])
layer_drop = tf.nn.dropout(layer_3, keep_prob)
output_layer = tf.matmul(layer_3, weights['out']) + biases['out']

Каждый скрытый слой будет выполнять матричное умножение на выходах предыдущего слоя и весах текущего слоя и добавлять смещение к этим значениям. На последнем скрытом слое мы применим операцию удаления, используя наше значение + keep_prob +, равное 0,5.

Последний шаг в построении графика — определить функцию потерь, которую мы хотим оптимизировать. Популярный выбор функции потерь в программах TensorFlow — это cross-entropy, также известная как log-loss, которая количественно определяет разницу между двумя распределениями вероятностей (предсказаниями и метками). Идеальная классификация привела бы к кросс-энтропии 0, а потери были бы полностью сведены к минимуму.

Нам также нужно выбрать алгоритм оптимизации, который будет использоваться для минимизации функции потерь. Процесс с именем gradient Descent Optimizer является распространенным методом для нахождения (локального) минимума функции путем выполнения итерационных шагов вдоль градиента в отрицательном (нисходящем) направлении. В TensorFlow уже реализовано несколько вариантов алгоритмов оптимизации градиентного спуска, и в этом руководстве мы будем использовать Adam optimizer. Это распространяется на оптимизацию градиентного спуска путем использования импульса для ускорения процесса посредством вычисления экспоненциально взвешенного среднего значения градиентов и использования его в корректировках. Добавьте следующий код в ваш файл:

...
cross_entropy = tf.reduce_mean(
   tf.nn.softmax_cross_entropy_with_logits(
       labels=Y, logits=output_layer
       ))
train_step = tf.train.AdamOptimizer(1e-4).minimize(cross_entropy)

Теперь мы определили сеть и создали ее с помощью TensorFlow. Следующим шагом является подача данных через график для обучения, а затем проверка того, что они действительно чему-то научились.

Шаг 5 — Обучение и тестирование

Процесс обучения включает подачу обучающего набора данных через график и оптимизацию функции потерь. Каждый раз, когда сеть выполняет итерацию множества обучающих изображений, она обновляет параметры, чтобы уменьшить потери, чтобы более точно предсказать показанные цифры. Процесс тестирования включает прогон нашего набора данных тестирования через обученный график и отслеживание количества изображений, которые правильно спрогнозированы, чтобы мы могли рассчитать точность.

Прежде чем начать процесс обучения, мы определим наш метод оценки точности, чтобы мы могли распечатать его на мини-пакетах данных во время обучения. Эти печатные утверждения позволят нам проверить, что от первой итерации до последней потери уменьшаются, а точность увеличивается; они также позволят нам отслеживать, достаточно ли мы выполнили итераций для достижения согласованного и оптимального результата:

...
correct_pred = tf.equal(tf.argmax(output_layer, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_pred, tf.float32))

В + correct_pred + мы используем функцию + arg_max +, чтобы сравнить, какие изображения предсказываются правильно, посмотрев на + output_layer + (предсказания) и + Y + (метки), и мы используем + равно + функция, чтобы возвратить это как список Booleans. Затем мы можем привести этот список к плавающим и вычислить среднее значение, чтобы получить общую оценку точности.

Теперь мы готовы инициализировать сеанс для запуска графа. На этом занятии мы наполним сеть нашими примерами обучения, а после обучения мы добавим в тот же график новые тестовые примеры, чтобы определить точность модели. Добавьте следующие строки кода в ваш файл:

...
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

Суть процесса обучения в глубоком обучении заключается в оптимизации функции потерь. Здесь мы стремимся минимизировать разницу между предсказанными метками изображений и истинными метками изображений. Процесс включает в себя четыре шага, которые повторяются для заданного количества итераций:

  • Распространять значения вперед через сеть

  • Вычислить потери

  • Распространять значения в обратном направлении через сеть

  • Обновить параметры

На каждом этапе обучения параметры немного корректируются, чтобы попытаться уменьшить потери для следующего этапа. По мере продвижения обучения мы должны увидеть снижение потерь, и в конечном итоге мы можем прекратить обучение и использовать сеть в качестве модели для тестирования наших новых данных.

Добавьте этот код в файл:

...
# train on mini batches
for i in range(n_iterations):
   batch_x, batch_y = mnist.train.next_batch(batch_size)
   sess.run(train_step, feed_dict={
       X: batch_x, Y: batch_y, keep_prob: dropout
       })

   # print loss and accuracy (per minibatch)
   if i % 100 == 0:
       minibatch_loss, minibatch_accuracy = sess.run(
           [cross_entropy, accuracy],
           feed_dict={X: batch_x, Y: batch_y, keep_prob: 1.0}
           )
       print(
           "Iteration",
           str(i),
           "\t| Loss =",
           str(minibatch_loss),
           "\t| Accuracy =",
           str(minibatch_accuracy)
           )

После 100 итераций каждого шага обучения, на котором мы передаем мини-серию изображений через сеть, мы распечатываем потери и точность этого пакета. Обратите внимание, что здесь не следует ожидать снижения потерь и повышения точности, поскольку значения приведены для каждой партии, а не для всей модели. Мы используем мини-пакеты изображений вместо того, чтобы передавать их по отдельности, чтобы ускорить процесс обучения и позволить сети увидеть множество различных примеров перед обновлением параметров.

После завершения обучения мы можем запустить сеанс на тестовых изображениях. На этот раз мы используем коэффициент отсева + keep_prob + + 1.0 +, чтобы гарантировать, что все юниты активны в процессе тестирования.

Добавьте этот код в файл:

...
test_accuracy = sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels, keep_prob: 1.0})
print("\nAccuracy on test set:", test_accuracy)

Теперь пришло время, чтобы запустить нашу программу и посмотреть, насколько точно наша нейронная сеть может распознавать эти рукописные цифры. Сохраните файл + main.py + и выполните следующую команду в терминале, чтобы запустить скрипт:

Вы увидите вывод, подобный следующему, хотя результаты отдельных потерь и точности могут незначительно отличаться:

OutputIteration 0     | Loss = 3.67079    | Accuracy = 0.140625
Iteration 100   | Loss = 0.492122   | Accuracy = 0.84375
Iteration 200   | Loss = 0.421595   | Accuracy = 0.882812
Iteration 300   | Loss = 0.307726   | Accuracy = 0.921875
Iteration 400   | Loss = 0.392948   | Accuracy = 0.882812
Iteration 500   | Loss = 0.371461   | Accuracy = 0.90625
Iteration 600   | Loss = 0.378425   | Accuracy = 0.882812
Iteration 700   | Loss = 0.338605   | Accuracy = 0.914062
Iteration 800   | Loss = 0.379697   | Accuracy = 0.875
Iteration 900   | Loss = 0.444303   | Accuracy = 0.90625

Accuracy on test set: 0.9206

Чтобы попытаться повысить точность нашей модели или узнать больше о влиянии настройки гиперпараметров, мы можем проверить влияние изменения скорости обучения, порога отсева, размера пакета и количества итераций. Мы также можем изменить количество единиц в наших скрытых слоях и изменить количество самих скрытых слоев, чтобы увидеть, как различные архитектуры увеличивают или уменьшают точность модели.

Чтобы продемонстрировать, что сеть фактически распознает нарисованные от руки изображения, давайте проверим это на нашем собственном изображении.

Если вы находитесь на локальном компьютере и хотите использовать собственный нарисованный от руки номер, вы можете использовать графический редактор для создания собственного изображения цифры размером 28×28 пикселей. В противном случае вы можете использовать + curl + для загрузки следующего примера тестового изображения на ваш сервер или компьютер:

curl -O https://raw.githubusercontent.com/do-community/tensorflow-digit-recognition/master/test_img.png

Откройте файл + main.py + в вашем редакторе и добавьте следующие строки кода в начало файла, чтобы импортировать две библиотеки, необходимые для работы с изображениями.

import numpy as np
from PIL import Image
...

Затем в конце файла добавьте следующую строку кода, чтобы загрузить тестовое изображение рукописной цифры:

...
img = np.invert(Image.open("test_img.png").convert('L')).ravel()

Функция + open + библиотеки + Image + загружает тестовое изображение в виде 4D-массива, содержащего три цветовых канала RGB и альфа-прозрачность. Это не то представление, которое мы использовали ранее при чтении в наборе данных с TensorFlow, поэтому нам потребуется проделать дополнительную работу, чтобы соответствовать формату.

Во-первых, мы используем функцию + convert + с параметром + L +, чтобы уменьшить представление 4D RGBA до одного цветового канала в градациях серого. Мы сохраняем это как массив + numpy + и инвертируем его, используя + np.invert +, потому что текущая матрица представляет черный как 0 и белый как 255, тогда как нам нужно обратное. Наконец, мы вызываем + ravel +, чтобы сгладить массив.

Теперь, когда данные изображения структурированы правильно, мы можем запустить сеанс так же, как и ранее, но на этот раз только для подачи в тестирование только одного изображения.

Добавьте следующий код в ваш файл, чтобы проверить изображение и распечатать выведенную этикетку.

...
prediction = sess.run(tf.argmax(output_layer, 1), feed_dict={X: [img]})
print ("Prediction for test image:", np.squeeze(prediction))

Функция + np.squeeze + вызывается для предсказания, чтобы вернуть единственное целое число из массива (т.е. перейти от [2] к 2). Полученный результат демонстрирует, что сеть распознала это изображение как цифру 2.

OutputPrediction for test image: 2

Вы можете попробовать протестировать сеть с более сложными изображениями — например, цифрами, которые похожи на другие цифры, или цифрами, которые были нарисованы плохо или неправильно — — чтобы увидеть, насколько хорошо это получается.

База данных рукописных цифр

MNIST, Янн ЛеКун, Коринна Кортес и Крис Берджес База данных рукописных цифр

MNIST, Янн ЛеКун, Коринна Кортес и Крис Берджес рукописных цифр Янн ЛеКун, Институт Куранта, Нью-Йоркский университет Коринна Кортес, Google Labs, Нью-Йорк Кристофер Дж. К. Берджес, Microsoft Research, Редмонд Воздержитесь от частого доступа к этим файлам из автоматических скриптов. Сделайте копии! ` База данных рукописных цифр MNIST, доступная на этой странице, имеет обучающий набор из 60 000 примеров и тестовый набор из 10 000 примеров.Это является подмножеством большего набора, доступного в NIST. Цифры имеют были нормализованы по размеру и центрированы в изображении фиксированного размера.

Это хорошая база данных для людей, которые хотят опробовать методы обучения. и методы распознавания образов на реальных данных при минимальных затратах усилия по предварительной обработке и форматированию.

На этом сайте доступны четыре файла:

поезд изображений idx3-ubyte.gz: изображения обучающего набора (9

2 байта)
поезд-метки-idx1-ubyte.gz: метки обучающего набора (28881 байт)
t10k-изображения-idx3-ubyte.gz: изображения тестового набора (1648877 байт)
t10k-label-idx1-ubyte.gz: метки тестового набора (4542 байта)

, обратите внимание, что ваш браузер может распаковывать эти файлы, не сообщая вам . Если загруженные вами файлы имеют больший размер, чем указано выше, они были несжатый вашим браузером. Просто переименуйте их, чтобы удалить расширение .gz. Некоторые люди спрашивали меня: «Мое приложение не может открывать ваши файлы изображений». Эти файлы не имеют стандартного формата изображения. Ты должен написать ваша собственная (очень простая) программа для их чтения.Формат файла описан внизу этой страницы.

Исходные черно-белые (двухуровневые) изображения из NIST были нормализованы по размеру. чтобы поместиться в рамку 20×20 пикселей с сохранением соотношения сторон. Результирующий изображения содержат уровни серого в результате используемого метода сглаживания алгоритмом нормализации. изображения были центрированы в изображении 28×28 вычисляя центр масс пикселей и переводя изображение чтобы разместить эту точку в центре поля 28×28.

С некоторыми методами классификации (особенно на основе шаблонов, таких как SVM и K-ближайшие соседи), частота ошибок увеличивается, когда Цифры центрируются по ограничительной рамке, а не по центру масс. если ты сделать такую ​​предварительную обработку, вы должны сообщить об этом в своем публикации.

База данных MNIST была создана на основе специальной базы данных NIST 3 и Специальная база данных 1, содержащая двоичные изображения рукописных цифр. NIST первоначально обозначили SD-3 как свой обучающий набор и SD-1 как свой тест установленный.Однако SD-3 намного чище и легче распознается, чем SD-1. В Причину этого можно найти в том, что СД-3 собиралась среди Сотрудники бюро переписи населения, а SD-1 собирали среди старшеклассников. Чтобы сделать разумные выводы из обучающих экспериментов, необходимо, чтобы результат не зависит от выбора обучающего набора и теста среди полный набор образцов. Поэтому было необходимо создать новую базу данных путем смешивания наборов данных NIST.

Обучающий набор MNIST состоит из 30 000 паттернов из SD-3 и 30 000 паттернов из SD-1.Наш тестовый набор состоял из 5000 паттернов. из SD-3 и 5000 паттернов из SD-1. Обучающий набор 60000 шаблонов содержит примеры примерно 250 авторов. Мы убедились, что наборы писателей обучающей выборки и тестовой выборки не пересекались.

SD-1 содержит 58 527 цифровых изображений, написанных 500 разными авторами. В отличие от SD-3, где блоки данных от каждого писателя появлялись в последовательность, данные в SD-1 скремблируются. Идентификационные данные писателя для SD-1: доступны, и мы использовали эту информацию, чтобы расшифровать писателей.Мы тогда разделить SD-1 на две части: персонажи, написанные первыми 250 писателями, вошли в наш новый обучающий набор. Остальные 250 писателей попали в наш тест. установленный. Таким образом, у нас было два набора почти по 30 000 примеров в каждом. Новое обучение набор был укомплектован достаточным количеством примеров из SD-3, начиная с шаблона # 0, чтобы создать полный набор из 60 000 обучающих шаблонов. Точно так же новый тест набор был дополнен примерами SD-3, начиная с шаблона №35000, чтобы сделать полный набор из 60 000 тестовых таблиц. Только подмножество из 10000 тестовых изображений (5000 с SD-1 и 5000 с SD-3) доступны на этом сайте.Полный Доступен обучающий набор из 60 000 выборок.

Многие методы были протестированы с этим обучающим набором и набором тестов. Здесь несколько примеров. Подробности о методах будут представлены в следующем бумага. В некоторых из этих экспериментов использовалась версия базы данных, в которой входные изображения с перекосом (вычислением главной оси формы ближайшего к вертикали, и смещая линии так, чтобы вертикальный). В некоторых других экспериментах обучающая выборка была дополнена искусственно искаженные версии исходных обучающих выборок.Искажения представляют собой случайные комбинации сдвигов, масштабирования, перекоса и сжатия.

КЛАССИФИКАТОР ПРЕДВАРИТЕЛЬНАЯ ОБРАБОТКА СКОРОСТЬ ОШИБОК ИСПЫТАНИЙ (%) Ссылка
Линейные классификаторы
Линейный классификатор (1-слойный NN) нет 12,0 LeCun et al. 1998
линейный классификатор (1-слойный НН) Коррекция 8.4 LeCun et al. 1998
попарный линейный классификатор Коррекция 7,6 LeCun et al. 1998
K-ближайшие соседи
K-ближайшие соседи, евклидово (L2) нет 5,0 LeCun et al. 1998
K-ближайшие соседи, евклидово (L2) нет 3,09 Кеннет Уайлдер, U.Чикаго
Ближайшие соседи, L3 нет 2,83 Kenneth Wilder, U. Chicago
K-ближайших соседей, евклидово (L2) Коррекция 2,4 LeCun et al. 1998
K-ближайшие соседи, евклидово (L2) выравнивание, удаление шума, размытие 1,80 Kenneth Wilder, U. Chicago
K-ближайшие соседи, L3 выравнивание, удаление шума, размытие 1.73 Kenneth Wilder, U. Chicago
K-ближайшие соседи, L3 выравнивание, удаление шума, размытие, сдвиг на 1 пиксель 1,33 Kenneth Wilder, U. Chicago
K-ближайшие соседи, L3 выравнивание, удаление шума, размытие, сдвиг на 2 пикселя 1,22 Kenneth Wilder, U. Chicago
K-NN с нелинейной деформацией (IDM) сдвижные кромки 0.54 Keysers et al. IEEE PAMI 2007
K-NN с нелинейной деформацией (P2DHMDM) сдвижные кромки 0,52 Keysers et al. IEEE PAMI 2007
K-NN, касательное расстояние субдискретизация до 16×16 пикселей 1,1 LeCun et al. 1998
K-NN, согласование контекста формы Извлечение контекстных признаков формы 0,63 Belongie et al.IEEE PAMI 2002
Усиленные пни
Усиленные пни нет 7,7 Kegl et al., ICML 2009
продукты из усиленных культи (3 члена) нет 1,26 Kegl et al., ICML 2009
усиленные деревья (17 листьев) нет 1,53 Kegl et al., ICML 2009
культя на участке Хаара Характеристики Haar 1.02 Kegl et al., ICML 2009
продукт пней по Хаару f. Характеристики Haar 0,87 Kegl et al., ICML 2009
Нелинейные классификаторы
40 PCA + квадратичный классификатор нет 3,3 LeCun et al. 1998
1000 RBF + линейный классификатор нет 3,6 LeCun et al.1998
SVM
SVM, ядро ​​Гаусса нет 1,4
SVM полином степени 4 Коррекция 1,1 LeCun et al. 1998
Уменьшенный набор SVM deg 5 полином Коррекция 1,0 LeCun et al. 1998
Virtual SVM deg-9 poly [искажения] нет 0.8 LeCun et al. 1998
Виртуальный SVM, deg-9 poly, 1-пиксельное дрожание нет 0,68 DeCoste and Scholkopf, MLJ 2002
Virtual SVM, deg-9 poly, 1-пиксельное дрожание Коррекция 0,68 DeCoste and Scholkopf, MLJ 2002
Virtual SVM, deg-9 poly, 2-пиксельное дрожание Коррекция 0,56 DeCoste and Scholkopf, MLJ 2002
Neural Nets
2-слойная NN, 300 скрытых единиц, среднеквадратичная ошибка нет 4.7 LeCun et al. 1998
2-х слойный NN, 300 HU, MSE, [искажения] нет 3,6 LeCun et al. 1998
2-х слойный NN, 300 HU Коррекция 1,6 LeCun et al. 1998
2-х слойный NN, 1000 скрытых блоков нет 4,5 LeCun et al. 1998
2-х слойный NN, 1000 HU, [искажения] нет 3.8 LeCun et al. 1998
3-х слойный NN, 300 + 100 скрытых блоков нет 3,05 LeCun et al. 1998
3-х слойный NN, 300 + 100 HU [искажения] нет 2,5 LeCun et al. 1998
3-х слойный NN, 500 + 150 скрытых блоков нет 2,95 LeCun et al. 1998
3-х слойный NN, 500 + 150 HU [искажения] нет 2.45 LeCun et al. 1998
3-слойный NN, 500 + 300 HU, softmax, кросс-энтропия, спад веса нет 1,53 Hinton, неопубликованный, 2005
2-слойный NN, 800 HU, потеря кросс-энтропии нет 1,6 Simard et al., ICDAR 2003
2-слойный NN, 800 HU, кросс-энтропия [аффинные искажения] нет 1,1 Simard et al., ICDAR 2003
2-слойный NN, 800 HU, MSE [упругие искажения] нет 0,9 Simard et al., ICDAR 2003
2-слойный NN, 800 HU, кросс-энтропия [упругие искажения] нет 0,7 Simard et al., ICDAR 2003
NN, 784-500-500-2000-30 + ближайший сосед, RBM + обучение NCA [без искажений] нет 1,0 Салахутдинов и Хинтон, AI-Stats 2007
6-слойный NN 784-2500-2000-1500-1000-500-10 (на GPU) [упругие искажения] нет 0.35 Ciresan et al. Neural Computation 10, 2010 и arXiv 1003.0358, 2010
комитет 25 NN 784-800-10 [упругие искажения] нормализация ширины, удаление опилок 0,39 Meier et al. ICDAR 2011
глубокая выпуклая сетка, предварительная тренировка после отмены [без искажений] нет 0,83 Deng et al. Interspeech 2010
Сверточные сети
Сверточные сети LeNet-1 субдискретизация до 16×16 пикселей 1.7 LeCun et al. 1998
Сверточная сеть LeNet-4 нет 1,1 LeCun et al. 1998
Сверточная сеть LeNet-4 с K-NN вместо последнего слоя нет 1,1 LeCun et al. 1998
Сверточная сеть LeNet-4 с локальным обучением вместо последнего слоя нет 1,1 LeCun et al. 1998
Сверточная сеть LeNet-5, [без искажений] нет 0.95 LeCun et al. 1998
Сверточная сеть LeNet-5, [огромные искажения] нет 0,85 LeCun et al. 1998
Сверточная сеть LeNet-5, [искажения] нет 0,8 LeCun et al. 1998
Сверточная сеть с усилением LeNet-4, [искажения] нет 0,7 LeCun et al. 1998
Обучаемый экстрактор признаков + SVM [без искажений] нет 0.83 Lauer et al., Pattern Recognition 40-6, 2007
Обучаемый экстрактор признаков + SVM [упругие искажения] нет 0,56 Lauer et al., Pattern Recognition 40-6, 2007
Обучаемый экстрактор признаков + SVM [аффинные искажения] нет 0,54 Lauer et al., Pattern Recognition 40-6, 2007
неконтролируемые разреженные функции + SVM, [без искажений] нет 0.59 Labusch et al., IEEE TNN 2008
Сверточная сеть, кросс-энтропия [аффинные искажения] нет 0,6 Simard et al., ICDAR 2003
Сверточная сеть, кросс-энтропия [упругие искажения] нет 0,4 Simard et al., ICDAR 2003
large conv. чистая, случайные особенности [без искажений] нет 0,89 Ranzato et al., CVPR 2007
большая усл. net, unup features [без искажений] нет 0,62 Ranzato et al., CVPR 2007
large conv. чистая, отмена предварительной тренировки [без искажений] нет 0.60 Ranzato et al., NIPS 2006
large conv. чистая, предварительная тренировка без подготовки [упругие искажения] нет 0,39 Ranzato et al., NIPS 2006
large conv.чистая, отмена предварительной тренировки [без искажений] нет 0,53 Jarrett et al., ICCV 2009
большая / глубокая конв. сетка, 1-20-40-60-80-100-120-120-10 [упругие деформации] нет 0,35 Ciresan et al. IJCAI 2011
комитет из 7 конв. сетка, 1-20-П-40-П-150-10 [упругие перекосы] нормализация ширины 0,27 + -0,02 Ciresan et al. ICDAR 2011
комитет 35 усл.сетка, 1-20-П-40-П-150-10 [упругие перекосы] нормализация ширины 0,23 Ciresan et al. CVPR 2012

Ссылки

[LeCun et al., 1998a]
Y. LeCun, L. Bottou, Ю. Бенжио и П. Хаффнер. «Градиентное обучение применимо к распознаванию документов». Proceedings of the IEEE , 86 (11): 2278-2324, ноябрь 1998 г. [он-лайн версия]


ФОРМАТЫ ФАЙЛОВ ДЛЯ БАЗЫ ДАННЫХ MNIST

Данные хранятся в очень простом формате файла, предназначенном для хранения векторов. и многомерные матрицы.Общая информация об этом формате представлена ​​на сайте конец этой страницы, но вам не нужно читать это, чтобы использовать файлы данных.

Все целые числа в файлах сначала сохраняются в MSB (с прямым порядком байтов) формат, используемый большинством процессоров сторонних производителей. Пользователи процессоров Intel и другие машины с младшим порядком байтов должны перевернуть байты заголовка.

Есть 4 файла:

train-images-idx3-ubyte: обучающий набор изображений
train-labels-idx1-ubyte: метки обучающего набора
t10k-images-idx3-ubyte: тестовый набор изображений
t10k-labels-idx1-ubyte: метки тестового набора

Обучающая выборка содержит 60000 примеров, а тестовая — 10000.

Первые 5000 примеров тестового набора взяты из оригинала. Учебный набор NIST. Последние 5000 взяты из оригинального теста NIST. установленный. Первые 5000 чище и проще, чем последние 5000.

ФАЙЛ ЭТИКЕТКИ НАБОРЫ ОБУЧЕНИЯ (train-labels-idx1-ubyte):

[смещение] [тип] [значение] [описание]
0000 32-битное целое число 0x00000801 (2049) магическое число (сначала MSB)
0004 32-битное целое число 60000 Количество предметов
0008 байт без знака ?? метка
0009 байт без знака ?? метка
……..
xxxx байт без знака ?? метка

Значения меток от 0 до 9.

ФАЙЛ ИЗОБРАЖЕНИЯ НАБОРА ОБУЧЕНИЯ (train-images-idx3-ubyte):

[смещение] [тип] [значение] [описание]
0000 32-битное целое число 0x00000803 (2051) магическое число
0004 32-битное целое число 60000 количество изображений
0008 32-битное целое число 28 количество рядов
0012 32-битное целое число 28 Число столбцов
0016 байт без знака ?? пиксель
0017 байт без знака ?? пиксель
……..
xxxx байт без знака ?? пиксель

Пиксели сгруппированы по строкам. Значения пикселей от 0 до 255. 0 означает фон. (белый), 255 означает передний план (черный).

ФАЙЛ ТЕСТОВОГО НАБОРА ЭТИКЕТКИ (t10k-labels-idx1-ubyte):

[смещение] [тип] [значение] [описание]
0000 32-битное целое число 0x00000801 (2049) магическое число (сначала MSB)
0004 32-битное целое число 10000 Количество предметов
0008 байт без знака ?? метка
0009 байт без знака ?? метка
……..
xxxx байт без знака ?? метка

Значения меток от 0 до 9.

ФАЙЛ ИЗОБРАЖЕНИЯ ТЕСТОВОГО НАБОРА (t10k-images-idx3-ubyte):

[смещение] [тип] [значение] [описание]
0000 32-битное целое число 0x00000803 (2051) магическое число
0004 32-битное целое число 10000 количество изображений
0008 32-битное целое число 28 количество рядов
0012 32-битное целое число 28 Число столбцов
0016 байт без знака ?? пиксель
0017 байт без знака ?? пиксель
……..
xxxx байт без знака ?? пиксель

Пиксели сгруппированы по строкам. Значения пикселей от 0 до 255. 0 означает фон. (белый), 255 означает передний план (черный).


ФОРМАТ ФАЙЛА IDX

формат файла IDX — это простой формат для векторных и многомерных матрицы различных числовых типов.

Базовый формат

магическое число
размер в размерности 0
размер в размерности 1
размер в размерности 2
…..
размер в размере N
данных

Магическое число — это целое число (сначала MSB). Первые 2 байта всегда 0.

Третий байт кодирует тип данных:
0x08: байт без знака
0x09: байт со знаком
0x0B: короткий (2 байта)
0x0C: int (4 байта)
0x0D: с плавающей точкой (4 байта)
0x0E: двойной (8 байт)

4-й байт кодирует размерность вектора / матрицы: 1 для векторов, 2 для матриц ….

Размеры в каждом измерении представляют собой 4-байтовые целые числа (сначала старший бит, старший разряд, как и в большинстве процессоров не Intel).

Данные хранятся как в массиве C, т.е. индекс в последнем измерении меняется быстрее всего.


Удачного взлома.


Цифровые изображения в наборе MNIST были изначально выбраны и экспериментировали Крис Берджес и Коринна Кортес, используя нормализация и центрирование ограничивающего прямоугольника. Версия Яна ЛеКуна, которая на этой странице использует центрирование по центру масс в пределах окно большего размера.

Янн ЛеКун, профессор
Институт математических наук Куранта
Нью-Йоркский университет

Коринна Кортес, научный сотрудник
Google Labs, Нью-Йорк
Corinna at google dot com

Как разработать CNN для классификации рукописных цифр MNIST

Последнее обновление 24 августа 2020 г.

Как разработать сверточную нейронную сеть с нуля для классификации рукописных цифр MNIST.

Задача классификации рукописных цифр MNIST — это стандартный набор данных, используемый в компьютерном зрении и глубоком обучении.

Хотя набор данных эффективно решен, его можно использовать в качестве основы для обучения и практики разработки, оценки и использования сверточных нейронных сетей с глубоким обучением для классификации изображений с нуля. Это включает в себя то, как разработать надежную систему тестирования для оценки производительности модели, как изучить улучшения модели и как сохранить модель, а затем загрузить ее, чтобы делать прогнозы на новых данных.

В этом руководстве вы узнаете, как с нуля разработать сверточную нейронную сеть для классификации рукописных цифр.

После прохождения этого руководства вы будете знать:

  • Как разработать тестовую программу для разработки надежной оценки модели и установления базового уровня производительности для задачи классификации.
  • Как изучить расширения базовой модели для улучшения обучения и возможностей модели.
  • Как разработать окончательную модель, оценить производительность окончательной модели и использовать ее для прогнозирования новых изображений.

Начните свой проект с моей новой книги «Глубокое обучение для компьютерного зрения», включающей пошаговых руководств и файлов исходного кода Python для всех примеров.

Приступим.

  • Обновлено декабрь 2019 г. : обновлены примеры для TensorFlow 2.0 и Keras 2.3.
  • Обновлено в январе 2020 г. : исправлена ​​ошибка, из-за которой модели определялись вне цикла перекрестной проверки.

Как разработать сверточную нейронную сеть с нуля для классификации рукописных цифр MNIST
Фотография Ричарда Аллавея, некоторые права защищены.

Обзор учебного пособия

Это руководство разделено на пять частей; их:

  1. Набор данных классификации рукописных цифр MNIST
  2. Методология оценки модели
  3. Как разработать базовую модель
  4. Как разработать улучшенную модель
  5. Как завершить модель и сделать прогнозы

Хотите результатов с помощью глубокого обучения для компьютерного зрения?

Пройдите бесплатный 7-дневный ускоренный курс электронной почты (с образцом кода).

Нажмите, чтобы зарегистрироваться, а также получите бесплатную электронную версию курса в формате PDF.

Нажмите здесь, чтобы подписаться

Среда разработки

В этом руководстве предполагается, что вы используете автономные Keras, работающие поверх TensorFlow с Python 3. Если вам нужна помощь в настройке среды разработки, см. Это руководство:

Набор данных классификации рукописных цифр MNIST

Набор данных MNIST — это аббревиатура, обозначающая модифицированный набор данных Национального института стандартов и технологий.

Это набор данных из 60000 небольших квадратных изображений размером 28 × 28 пикселей в оттенках серого, состоящих из рукописных одиночных цифр от 0 до 9.

Задача состоит в том, чтобы отнести данное изображение рукописной цифры к одному из 10 классов, представляющих целые числа от 0 до 9 включительно.

Это широко используемый и хорошо изученный набор данных, по большей части это « решено, ». Самые эффективные модели — это сверточные нейронные сети с глубоким обучением, которые достигают точности классификации выше 99% с коэффициентом ошибок от 0.4% и 0,2% в тестовом наборе данных.

В приведенном ниже примере загружается набор данных MNIST с помощью API Keras и создается график первых девяти изображений в наборе обучающих данных.

# пример загрузки набора данных mnist from keras.datasets import mnist из matplotlib import pyplot # загрузить набор данных (trainX, trainy), (testX, testy) = mnist.load_data () # суммировать загруженный набор данных print (‘Поезд: X =% s, y =% s’% (trainX.shape, trainy.shape)) print (‘Тест: X =% s, y =% s’% (testX.shape, testy.shape)) # построить первые несколько изображений для i в диапазоне (9): # определить подзаговор pyplot.subplot (330 + 1 + я) # построить необработанные данные пикселей pyplot.imshow (trainX [i], cmap = pyplot.get_cmap (‘серый’)) # показать рисунок pyplot.show ()

# пример загрузки набора данных mnist

из keras.datasets import mnist

from matplotlib import pyplot

# load dataset

(trainX, trainy), (testX, testy) = mnist.load_data ()

# суммировать загруженный набор данных

print (‘Train: X =% s, y =% s’% (trainX.shape, trainy.shape))

print (‘Test: X =% s, y =% s ‘% (testX.shape, testy.shape))

# построить первые несколько изображений

для i в диапазоне (9):

# определить подзаголовок

pyplot.subplot (330 + 1 + i)

# построить необработанные данные пикселей

pyplot.imshow (trainX [i], cmap = pyplot.get_cmap (‘gray’))

# показать рисунок

pyplot.show ()

При выполнении примера загружается набор обучающих и тестовых данных MNIST и распечатывается их форма.

Мы видим, что есть 60 000 примеров в наборе обучающих данных и 10 000 в наборе тестовых данных, и что изображения действительно квадратные с размером 28 × 28 пикселей.

Поезд: X = (60000, 28, 28), y = (60000,) Тест: X = (10000, 28, 28), y = (10000,)

Поезд: X = (60000, 28, 28), y = (60000,) Тест: X = (10000, 28, 28), y = (10000,)

Также создается график первых девяти изображений в наборе данных, показывающий естественный рукописный характер изображений, подлежащих классификации.

График подмножества изображений из набора данных MNIST

Методология оценки модели

Хотя набор данных MNIST эффективно решен, он может быть полезной отправной точкой для разработки и практики методологии решения задач классификации изображений с использованием сверточных нейронных сетей.

Вместо того, чтобы изучать литературу по хорошо работающим моделям в наборе данных, мы можем разработать новую модель с нуля.

В наборе данных уже есть четко определенный набор данных для обучения и тестирования, который мы можем использовать.

Чтобы оценить производительность модели для данного обучающего прогона, мы можем дополнительно разделить обучающий набор на набор данных для обучения и проверки. Затем можно построить график производительности набора данных по обучению и валидации для каждого прогона, чтобы представить кривые обучения и понять, насколько хорошо модель изучает проблему.

API Keras поддерживает это, указав аргумент « validation_data » функции model.fit () при обучении модели, которая, в свою очередь, вернет объект, описывающий производительность модели для выбранных потерь и метрики на каждую тренировочную эпоху.

# запись производительности модели в наборе данных проверки во время обучения history = model.fit (…, validation_data = (valX, valY))

# запись производительности модели в наборе данных проверки во время обучения

history = model.fit (…, validation_data = (valX, valY))

Чтобы оценить производительность модели по проблеме в целом, мы можем использовать k-кратную перекрестную проверку, возможно, пятикратную перекрестную проверку.Это даст некоторый учет дисперсии моделей как в отношении различий в наборах данных для обучения и тестирования, так и в отношении стохастической природы алгоритма обучения. Производительность модели может быть принята как средняя производительность в k-кратном масштабе с учетом стандартного отклонения, которое при желании может быть использовано для оценки доверительного интервала.

Мы можем использовать класс KFold из scikit-learn API, чтобы реализовать k-кратную оценку перекрестной проверки данной модели нейронной сети.Есть много способов добиться этого, хотя мы можем выбрать гибкий подход, при котором класс KFold используется только для указания индексов строк, используемых для каждого вертела.

# пример k-кратного резюме для нейронной сети данные = … # подготовить перекрестную проверку kfold = KFold (5, shuffle = True, random_state = 1) # перечислить разбиения для train_ix, test_ix в kfold.split (данные): модель = … …

# пример k-кратного cv для нейронной сети

data =…

# подготовить перекрестную проверку

kfold = KFold (5, shuffle = True, random_state = 1)

# перечислить разбиения

для train_ix, test_ix в kfold.split (данные):

model = …

Мы воздержимся от фактического набора тестовых данных и будем использовать его для оценки нашей окончательной модели.

Как разработать базовую модель

Первым шагом является разработка базовой модели.

Это критически важно, поскольку оно включает в себя разработку инфраструктуры для тестовой оснастки, чтобы любую модель, которую мы разрабатываем, можно было оценить на наборе данных, и устанавливает базовый уровень производительности модели по проблеме, по которому можно сравнивать все улучшения.

Испытательная привязь имеет модульную конструкцию, и мы можем разработать отдельную функцию для каждой детали. Это позволяет при желании модифицировать или заменять данный аспект тестовой оснастки отдельно от остальных.

Мы можем разработать эту испытательную систему с пятью ключевыми элементами. Это загрузка набора данных, подготовка набора данных, определение модели, оценка модели и представление результатов.

Загрузить набор данных

Мы кое-что знаем о наборе данных.

Например, мы знаем, что все изображения предварительно выровнены (например, каждое изображение содержит только нарисованную вручную цифру), что все изображения имеют одинаковый квадратный размер 28 × 28 пикселей и что изображения имеют оттенки серого.

Следовательно, мы можем загружать изображения и изменять форму массивов данных, чтобы они имели единственный цветовой канал.

# загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = поездX.изменить форму ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1))

# загрузить набор данных

(trainX, trainY), (testX, testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0], 28, 28, 1))

Мы также знаем, что существует 10 классов и что классы представлены как уникальные целые числа.

Таким образом, мы можем использовать одно горячее кодирование для элемента класса каждой выборки, преобразовывая целое число в двоичный вектор из 10 элементов с 1 для индекса значения класса и 0 значений для всех других классов. Этого можно добиться с помощью служебной функции to_categorical () .

# одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY)

# одно целевое значение горячего кодирования

trainY = to_categorical (trainY)

testY = to_categorical (testY)

Функция load_dataset () реализует это поведение и может использоваться для загрузки набора данных.

# загрузить поезд и тестовый набор данных def load_dataset (): # загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1)) # одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY) вернуть trainX, trainY, testX, testY

# загрузить поезд и тестовый набор данных

def load_dataset ():

# загрузить набор данных

(trainX, trainY), (testX, testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0 ], 28, 28, 1))

# целевые значения горячего кодирования one

trainY = to_categorical (trainY)

testY = to_categorical (testY)

return trainX, trainY, testX, testY

Подготовка пиксельных данных

Мы знаем, что значения пикселей для каждого изображения в наборе данных представляют собой целые числа без знака в диапазоне от черного до белого или от 0 до 255.

Мы не знаем наилучшего способа масштабирования значений пикселей для моделирования, но мы знаем, что потребуется некоторое масштабирование.

Хорошей отправной точкой является нормализация значений пикселей изображений в градациях серого, например масштабируйте их до диапазона [0,1]. Это включает в себя сначала преобразование типа данных из целых чисел без знака в числа с плавающей запятой, а затем деление значений пикселей на максимальное значение.

# преобразовать целые числа в числа с плавающей запятой train_norm = train.astype (‘float32’) test_norm = тест.astype (‘float32’) # нормализовать до диапазона 0-1 train_norm = train_norm / 255.0 test_norm = test_norm / 255.0

# преобразовать целые числа в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255,0

Функция Prep_pixels () ниже реализует это поведение и предоставляет значения пикселей как для обучающего, так и для тестового наборов данных, которые необходимо масштабировать.

# масштабный пиксель def Prep_pixels (поезд, тест): # преобразовать целые числа в числа с плавающей запятой train_norm = train.astype (‘float32’) test_norm = test.astype (‘float32’) # нормализовать до диапазона 0-1 train_norm = train_norm / 255.0 test_norm = test_norm / 255.0 # вернуть нормализованные изображения возврат train_norm, test_norm

# масштабировать пиксели

def Prep_pixels (train, test):

# преобразовать из целых чисел в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255.0

# вернуть нормализованные изображения

return train_norm, test_norm

Эта функция должна быть вызвана для подготовки значений пикселей перед любым моделированием.

Определить модель

Затем нам нужно определить базовую модель сверточной нейронной сети для проблемы.

Модель имеет два основных аспекта: интерфейс извлечения признаков, состоящий из сверточных слоев и слоев объединения, и серверный модуль классификатора, который будет делать прогноз.

Для сверточного интерфейса мы можем начать с одного сверточного слоя с небольшим размером фильтра (3,3) и небольшим количеством фильтров (32), за которым следует максимальный слой объединения. Затем карты фильтров могут быть сглажены, чтобы предоставить классификатору функции.

Учитывая, что проблема заключается в задаче классификации нескольких классов, мы знаем, что нам потребуется выходной слой с 10 узлами, чтобы предсказать распределение вероятностей изображения, принадлежащего каждому из 10 классов.Это также потребует использования функции активации softmax. Между экстрактором признаков и выходным слоем мы можем добавить плотный слой для интерпретации признаков, в данном случае со 100 узлами.

Все уровни будут использовать функцию активации ReLU и схему инициализации весов He, что является передовым опытом.

Мы будем использовать консервативную конфигурацию оптимизатора стохастического градиентного спуска со скоростью обучения 0,01 и импульсом 0,9. Категориальная функция кросс-энтропийных потерь будет оптимизирована, подходящая для мультиклассовой классификации, и мы будем отслеживать метрику точности классификации, которая подходит, учитывая, что у нас одинаковое количество примеров в каждом из 10 классов.

Функция define_model () ниже определит и вернет эту модель.

# определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (MaxPooling2D ((2, 2))) model.add (Сглаживание ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0.01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) вернуть модель

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), activate = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1)))

model.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add (Dense (100, activate = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (Dense (10, activate = ‘softmax’))

# скомпилировать модель

opt = SGD (lr = 0,01 , импульс = 0,9)

model.compile (optimizer = opt, loss =’ategorical_crossentropy ‘, metrics = [‘ precision ‘])

return model

Оценить модель

После того, как модель определена, нам нужно ее оценить.

Модель будет оцениваться с использованием пятикратной перекрестной проверки.Значение k = 5 было выбрано, чтобы обеспечить основу как для повторной оценки, так и не быть настолько большим, чтобы требовать длительного времени. Каждый набор тестов будет составлять 20% обучающего набора данных или около 12 000 примеров, что близко к размеру фактического набора тестов для этой задачи.

Обучающий набор данных перетасовывается перед разделением, и выборка перетасовывается каждый раз, так что любая модель, которую мы оцениваем, будет иметь одни и те же наборы обучающих и тестовых данных в каждом сгибе, обеспечивая сравнение моделей между яблоками и яблоками.

Мы обучим базовую модель для скромных 10 эпох обучения с размером пакета по умолчанию из 32 примеров. Набор тестов для каждой свертки будет использоваться для оценки модели как в каждую эпоху тренировочного прогона, чтобы мы могли позже создать кривые обучения, так и в конце прогона, чтобы мы могли оценить производительность модели. Таким образом, мы будем отслеживать итоговую историю каждого запуска, а также точность классификации сгиба.

Функция valu_model () , приведенная ниже, реализует это поведение, принимая набор обучающих данных в качестве аргументов и возвращая список оценок точности и историй обучения, которые можно затем обобщить.

# оценить модель с помощью k-кратной перекрестной проверки def оценивать_модель (dataX, dataY, n_folds = 5): оценки, истории = список (), список () # подготовить перекрестную проверку kfold = KFold (n_folds, shuffle = True, random_state = 1) # перечислить разбиения для train_ix, test_ix в kfold.split (dataX): # определить модель модель = define_model () # выбираем строки для обучения и тестирования trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix], dataY [test_ix] # подходящая модель история = модель.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0) # оценить модель _, acc = model.evaluate (testX, testY, verbose = 0) print (‘>% .3f’% (согласно * 100.0)) Результаты в # магазинах scores.append (acc) history.append (история) вернуть результаты, истории

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

# оценить модель с помощью k-кратной перекрестной проверки

def rating_model (dataX, dataY, n_folds = 5):

баллов, history = list (), list ()

# подготовить перекрестную проверку

kfold = KFold (n_folds, shuffle = True, random_state = 1)

# перечислить разбиения

для train_ix, test_ix в kfold.split (dataX):

# определить модель

model = define_model ()

# выбрать строки для обучения и тестирования

trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix] , dataY [test_ix]

# fit model

history = model.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0)

# оценить модель

_ , acc = model.evaluate (testX, testY, verbose = 0)

print (‘>%.3f ‘% (acc * 100.0))

# store scores

scores.append (acc)

histories.append (history)

return scores, history

Настоящие результаты

После оценки модели мы можем представить результаты.

Необходимо представить два ключевых аспекта: диагностику обучающего поведения модели во время обучения и оценку производительности модели. Их можно реализовать с помощью отдельных функций.

Во-первых, диагностика включает создание линейного графика, показывающего производительность модели на поезде и наборе тестов во время каждого раза k-кратной перекрестной проверки. Эти графики полезны для понимания того, соответствует ли модель избыточному, недостаточному или хорошо подходит для набора данных.

Мы создадим одну фигуру с двумя частями графика, одна для потерь, а другая для точности. Синие линии будут указывать на производительность модели в наборе обучающих данных, а оранжевые линии — на производительность на удерживаемом наборе тестовых данных.Функция summarize_diagnostics () ниже создает и показывает этот график с учетом собранных историй обучения.

# построить диагностические кривые обучения def summarize_diagnostics (истории): для i в диапазоне (len (истории)): # потеря сюжета pyplot.subplot (2, 1, 1) pyplot.title (‘потеря перекрестной энтропии’) pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’) pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’) # точность сюжета пиплот.подзаговор (2, 1, 2) pyplot.title (‘Точность классификации’) pyplot.plot (history [i] .history [‘точность’], color = ‘blue’, label = ‘train’) pyplot.plot (history [i] .history [‘val_accuracy’], color = ‘orange’, label = ‘test’) pyplot.show ()

# график диагностических кривых обучения

def summarize_diagnostics (history):

для i в диапазоне (len (history)):

# потеря графика

pyplot.subplot (2, 1, 1)

pyplot.title (‘Перекрестная потеря энтропии’)

pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’)

pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’)

# точность графика

pyplot.subplot (2, 1, 2)

pyplot .title (‘Точность классификации’)

pyplot.plot (history [i] .history [‘precision’], color = ‘blue’, label = ‘train’)

pyplot.plot (history [i] .history [‘val_accuracy’], color = ‘orange’, label = ‘test’)

pyplot.показать ()

Затем оценки точности классификации, полученные во время каждой кратности, можно суммировать, вычислив среднее значение и стандартное отклонение. Это обеспечивает оценку средней ожидаемой производительности модели, обученной на этом наборе данных, с оценкой средней дисперсии в среднем. Мы также подведем итоги распределения оценок, создав и отобразив график в виде прямоугольников и усов.

Функция summarize_performance () ниже реализует это для заданного списка оценок, собранных во время оценки модели.

# подвести итоги работы модели def summarize_performance (баллы): # распечатать сводку print (‘Точность: среднее =%. 3f std =%. 3f, n =% d’% (среднее (баллы) * 100, стандартное (баллы) * 100, len (баллы))) # график результатов в виде квадратов и усов pyplot.boxplot (баллы) pyplot.show ()

# суммировать производительность модели

def summarize_performance (scores):

# print summary

print (‘Точность: среднее =%.3f std =%. 3f, n =% d ‘% (среднее (баллы) * 100, std (баллы) * 100, len (баллы)))

# графики результатов в виде прямоугольников и усов

pyplot.boxplot (баллы )

pyplot.show ()

Полный пример

Нам нужна функция, которая будет управлять тестовой привязью.

Это включает вызов всех функций определения.

# запускаем тестовую программу для оценки модели def run_test_harness (): # загрузить набор данных trainX, trainY, testX, testY = load_dataset () # подготовить данные пикселей trainX, testX = Prep_pixels (trainX, testX) # оценить модель оценки, истории = оценка_модель (trainX, trainY) # кривые обучения summarize_diagnostics (истории) # подвести итоги расчетной производительности summarize_performance (баллы)

# запустить тестовую программу для оценки модели

def run_test_harness ():

# загрузить набор данных

trainX, trainY, testX, testY = load_dataset ()

# подготовить данные пикселей

trainX, testX = Prep_pixels ( trainX, testX)

# оцените модель

оценки, истории = оценка_модель (trainX, trainY)

# кривые обучения

summarize_diagnostics (истории)

# суммируйте оценочную производительность

summarize_performance (баллы)

Теперь у нас есть все необходимое; Полный пример кода для базовой модели сверточной нейронной сети в наборе данных MNIST приведен ниже.

# базовая модель cnn для mnist из среднего значения импорта из numpy import std из matplotlib import pyplot из sklearn.model_selection импорт KFold from keras.datasets import mnist from keras.utils import to_categorical из keras.models импортировать Последовательный из keras.layers импортировать Conv2D из keras.layers импорт MaxPooling2D из keras.layers import Плотный из keras.layers import Flatten от keras.optimizers импортные SGD # загрузить поезд и тестовый набор данных def load_dataset (): # загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1)) # одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY) вернуть trainX, trainY, testX, testY # масштабный пиксель def Prep_pixels (поезд, тест): # преобразовать целые числа в числа с плавающей запятой train_norm = train.astype (‘float32’) test_norm = test.astype (‘float32’) # нормализовать до диапазона 0-1 поезд_норм = поезд_норм / 255.0 test_norm = test_norm / 255.0 # вернуть нормализованные изображения вернуть train_norm, test_norm # определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (MaxPooling2D ((2, 2))) model.add (Сглаживание ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0.01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) модель возврата # оценить модель с помощью k-кратной перекрестной проверки def оценивать_модель (dataX, dataY, n_folds = 5): оценки, истории = список (), список () # подготовить перекрестную проверку kfold = KFold (n_folds, shuffle = True, random_state = 1) # перечислить разбиения для train_ix, test_ix в kfold.split (dataX): # определить модель модель = define_model () # выбираем строки для обучения и тестирования trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix], dataY [test_ix] # подходящая модель история = модель.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0) # оценить модель _, acc = model.evaluate (testX, testY, verbose = 0) print (‘>% .3f’% (согласно * 100.0)) Результаты в # магазинах scores.append (acc) history.append (история) вернуть оценки, истории # построить диагностические кривые обучения def summarize_diagnostics (истории): для i в диапазоне (len (истории)): # потеря сюжета pyplot.subplot (2, 1, 1) пиплот.title («Перекрестная потеря энтропии») pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’) pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’) # точность сюжета pyplot.subplot (2, 1, 2) pyplot.title (‘Точность классификации’) pyplot.plot (history [i] .history [‘точность’], color = ‘blue’, label = ‘train’) pyplot.plot (history [i] .history [‘val_accuracy’], color = ‘orange’, label = ‘test’) pyplot.show () # подвести итоги работы модели def summarize_performance (баллы): # распечатать сводку print (‘Точность: среднее =%.3f std =%. 3f, n =% d ‘% (среднее (баллы) * 100, стандартное (баллы) * 100, len (баллы))) # график результатов в виде квадратов и усов pyplot.boxplot (баллы) pyplot.show () # запускаем тестовую программу для оценки модели def run_test_harness (): # загрузить набор данных trainX, trainY, testX, testY = load_dataset () # подготовить данные пикселей trainX, testX = Prep_pixels (trainX, testX) # оценить модель оценки, истории = оценка_модель (trainX, trainY) # кривые обучения summarize_diagnostics (истории) # подвести итоги расчетной производительности summarize_performance (баллы) # точка входа, запускаем тестовый жгут run_test_harness ()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

21

22

23

24

25

26

27

28

29

30

34

35

36

37

38

39

40

41

42

43

44

45

46

47

0005

51

52

53

54

55

56

57

58

59

60

61

62

63

9 0004 64

65

66

67

68

69

70

71

72

73

74

75

76

70005

81

82

83

84

85

86

87

88

89

90

91

92

94

94

97

98

99

100

101

102

103

104

105

106

107

108

109

# базовая модель cnn для mnist

из numpy import mean

из numpy import std

из matplotlib import pyplot

из sklearn.model_selection import KFold

from keras.datasets import mnist

from keras.utils import to_categorical

from keras.models import Sequential

from keras.layers import Conv2D

from keras.layers import d max Dense

из keras.layers import Flatten

from keras.optimizers import SGD

# load train and test dataset

def load_dataset ():

# load dataset

(trainX, trainY), (test testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0 ], 28, 28, 1))

# one целевые значения горячего кодирования

trainY = to_categorical (trainY)

testY = to_categorical (testY)

return trainX, trainY, testX, testY

# scale

def Prep_pixels (train, test):

# преобразовать целые числа в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255.0

# вернуть нормализованные изображения

return train_norm, test_norm

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), activate = ‘relu’, kernel_initializer = ‘ he_uniform ‘, input_shape = (28, 28, 1)))

модель.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add (Dense (100, Activation = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add ( Dense (10, activate = ‘softmax’))

# скомпилировать модель

opt = SGD (lr = 0,01, импульс = 0,9)

model.compile (optimizer = opt, loss = ‘categoryorical_crossentropy’, metrics = [‘ точность ‘])

return model

# оценить модель с помощью k-кратной перекрестной проверки

def Assessment_model (dataX, dataY, n_folds = 5):

оценки, history = list (), list ()

# подготовить перекрестную проверку

kfold = KFold (n_folds, shuffle = True, random_state = 1)

# перечислить разбиения

для train_ix, test_ix в kfold.split (dataX):

# определить модель

model = define_model ()

# выбрать строки для обучения и тестирования

trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix] , dataY [test_ix]

# fit model

history = model.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0)

# оценить модель

_ , acc = model.evaluate (testX, testY, verbose = 0)

print (‘>%.3f ‘% (acc * 100.0))

# сохраняет оценки

scores.append (acc)

history.append (history)

return scores, history

# plot диагностические кривые обучения

def summarize_diagnostics ( историй):

для i в диапазоне (len (истории)):

# потеря графика

pyplot.subplot (2, 1, 1)

pyplot.title (‘Cross Entropy Loss’)

pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’)

pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’)

# точность графика

pyplot.subplot (2, 1, 2)

pyplot.title (‘ Точность классификации ‘)

pyplot.plot (history [i] .history [‘ precision ‘], color =’ blue ‘, label =’ train ‘)

pyplot.plot (history [i] .history [‘ val_accuracy ‘ ], color = ‘orange’, label = ‘test’)

pyplot.show ()

# суммировать производительность модели

def summarize_performance (scores):

# print summary

print (‘Accuracy: mean знак равно3f std =%. 3f, n =% d ‘% (среднее (баллы) * 100, std (баллы) * 100, len (баллы)))

# графики результатов в виде прямоугольников и усов

pyplot.boxplot (баллы )

pyplot.show ()

# запустить тестовую программу для оценки модели

def run_test_harness ():

# загрузить набор данных

trainX, trainY, testX, testY = load_dataset ()

данные пикселей

trainX, testX = Prep_pixels (trainX, testX)

# оцените модель

баллов, history = eval_model (trainX, trainY)

# кривые обучения

summarize_diagnostics (history)

# суммируйте

# суммируйте оценочную производительность summarize_performance (scores)

# точка входа, запустить тестовую программу

run_test_harness ()

При выполнении примера печатается точность классификации для каждого этапа процесса перекрестной проверки.Это помогает понять, что оценка модели продолжается.

Примечание : Ваши результаты могут отличаться из-за стохастической природы алгоритма или процедуры оценки или различий в числовой точности. Попробуйте запустить пример несколько раз и сравните средний результат.

Мы можем видеть два случая, когда модель достигает безупречного мастерства, и один случай, когда она достигла точности ниже 98%. Это хорошие результаты.

> 98.550 > 98,600 > 98,642 > 98,850 > 98,742

> 98,550

> 98,600

> 98,642

> 98,850

> 98,742

Затем показан диагностический график, дающий представление о поведении модели при обучении по каждой складке.

В этом случае мы можем видеть, что модель в целом хорошо подходит, при этом кривые обучения и тестирования сходятся.Нет явных признаков переоборудования или недостаточного оснащения.

Кривые потерь и точности для базовой модели во время перекрестной проверки k-Fold

Затем рассчитывается сводная характеристика модели.

Мы видим, что в этом случае оценка модели составляет около 98,6%, что является разумным.

Точность: среднее значение = 98,677 стандартное отклонение = 0,107, n = 5

Точность: среднее = 98,677 стандартное = 0.107, п = 5

Наконец, создается диаграмма в виде прямоугольников и усов, чтобы суммировать распределение оценок точности.

Ящик и диаграмма усов для оценок точности для базовой модели, оцененных с помощью перекрестной проверки k-Fold

Теперь у нас есть надежная испытательная система и хорошо работающая базовая модель.

Как разработать улучшенную модель

Есть много способов улучшить базовую модель.

Мы рассмотрим области конфигурации модели, которые часто приводят к улучшениям, так называемым низко висящим плодам.Первый — это изменение алгоритма обучения, а второй — увеличение глубины модели.

Улучшение обучения

Есть много аспектов алгоритма обучения, которые можно изучить для улучшения.

Возможно, наиболее важным преимуществом является скорость обучения, например оценка влияния меньших или больших значений скорости обучения, а также расписания, которые изменяют скорость обучения во время обучения.

Другой подход, который может быстро ускорить изучение модели и привести к значительному повышению производительности, — это пакетная нормализация.Мы оценим влияние пакетной нормализации на нашу базовую модель.

Пакетную нормализацию можно использовать после сверточных и полносвязных слоев. Это имеет эффект изменения распределения выходных данных слоя, в частности, путем стандартизации выходных данных. Это стабилизирует и ускоряет процесс обучения.

Мы можем обновить определение модели, чтобы использовать пакетную нормализацию после функции активации для сверточных и плотных слоев нашей базовой модели.Обновленная версия функции define_model () с пакетной нормализацией приведена ниже.

# определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (BatchNormalization ()) model.add (MaxPooling2D ((2, 2))) model.add (Сглаживание ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) модель.добавить (BatchNormalization ()) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0,01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) вернуть модель

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), activate = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1)))

модель.add (BatchNormalization ())

model.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘ he_uniform ‘))

model.add (BatchNormalization ())

model.add (Dense (10, activate =’ softmax ‘))

# скомпилировать модель

opt = SGD (lr = 0,01, импульс = 0,9)

model.compile (optimizer = opt, loss =’ategorical_crossentropy ‘, metrics = [‘ precision ‘])

return model

Полный список кода с этим изменением представлен ниже.

# модель cnn с пакетной нормализацией для mnist из среднего значения импорта из numpy import std из matplotlib import pyplot из sklearn.model_selection импорт KFold from keras.datasets import mnist from keras.utils import to_categorical из keras.models импортировать Последовательный из keras.layers импортировать Conv2D из keras.layers импорт MaxPooling2D из keras.layers import Плотный из keras.layers import Flatten из кераса.оптимизаторы импортируют SGD из keras.layers import BatchNormalization # загрузить поезд и тестовый набор данных def load_dataset (): # загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1)) # одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY) вернуть trainX, trainY, testX, testY # масштабный пиксель def Prep_pixels (поезд, тест): # преобразовать целые числа в числа с плавающей запятой train_norm = поезд.astype (‘float32’) test_norm = test.astype (‘float32’) # нормализовать до диапазона 0-1 train_norm = train_norm / 255.0 test_norm = test_norm / 255.0 # вернуть нормализованные изображения вернуть train_norm, test_norm # определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (BatchNormalization ()) model.add (MaxPooling2D ((2, 2))) модель.добавить (Flatten ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (BatchNormalization ()) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0,01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) модель возврата # оценить модель с помощью k-кратной перекрестной проверки def оценивать_модель (dataX, dataY, n_folds = 5): оценки, истории = список (), список () # подготовить перекрестную проверку kfold = KFold (n_folds, shuffle = True, random_state = 1) # перечислить разбиения для train_ix, test_ix в kfold.split (dataX): # определить модель модель = define_model () # выбираем строки для обучения и тестирования trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix], dataY [test_ix] # подходящая модель history = model.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0) # оценить модель _, acc = model.evaluate (testX, testY, verbose = 0) print (‘>% .3f’% (согласно * 100.0)) Результаты в # магазинах scores.append (acc) истории.добавить (история) вернуть оценки, истории # построить диагностические кривые обучения def summarize_diagnostics (истории): для i в диапазоне (len (истории)): # потеря сюжета pyplot.subplot (2, 1, 1) pyplot.title (‘потеря перекрестной энтропии’) pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’) pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’) # точность сюжета pyplot.subplot (2, 1, 2) pyplot.title (‘Точность классификации’) пиплот.сюжет (истории [i]. история [‘точность’], цвет = ‘синий’, метка = ‘поезд’) pyplot.plot (history [i] .history [‘val_accuracy’], color = ‘orange’, label = ‘test’) pyplot.show () # подвести итоги работы модели def summarize_performance (баллы): # распечатать сводку print (‘Точность: среднее =%. 3f std =%. 3f, n =% d’% (среднее (баллы) * 100, стандартное (баллы) * 100, len (баллы))) # график результатов в виде квадратов и усов pyplot.boxplot (баллы) pyplot.show () # запускаем тестовую программу для оценки модели def run_test_harness (): # загрузить набор данных trainX, trainY, testX, testY = load_dataset () # подготовить данные пикселей trainX, testX = Prep_pixels (trainX, testX) # оценить модель оценки, истории = оценка_модель (trainX, trainY) # кривые обучения summarize_diagnostics (истории) # подвести итоги расчетной производительности summarize_performance (баллы) # точка входа, запускаем тестовый жгут run_test_harness ()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

21

22

23

24

25

26

27

28

29

30

34

35

36

37

38

39

40

41

42

43

44

45

46

47

0005

51

52

53

54

55

56

57

58

59

60

61

62

63

9 0004 64

65

66

67

68

69

70

71

72

73

74

75

76

70005

81

82

83

84

85

86

87

88

89

90

91

92

94

94

97

98

99

100

101

102

103

104

105

106

107

108

109

110

109

110

# cnn модель с пакетной нормализацией для mnist

из numpy import mean

из numpy import std

из matplotlib import pyplot

from sklearn.model_selection import KFold

from keras.datasets import mnist

from keras.utils import to_categorical

from keras.models import Sequential

from keras.layers import Conv2D

from keras.layers import

from keras.layers import

from keras.layers import d

Dense

из keras.layers import Flatten

from keras.optimizers import SGD

from keras.layers import BatchNormalization

# load train and test dataset

def load_dataset ():

# load dataset ():

# load dataset trainX, trainY), (testX, testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0 ], 28, 28, 1))

# one целевые значения горячего кодирования

trainY = to_categorical (trainY)

testY = to_categorical (testY)

return trainX, trainY, testX, testY

# scale

def Prep_pixels (train, test):

# преобразовать целые числа в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255.0

# вернуть нормализованные изображения

return train_norm, test_norm

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), activate = ‘relu’, kernel_initializer = ‘ he_uniform ‘, input_shape = (28, 28, 1)))

модель.add (BatchNormalization ())

model.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘ he_uniform ‘))

model.add (BatchNormalization ())

model.add (Dense (10, activate =’ softmax ‘))

# скомпилировать модель

opt = SGD (lr = 0,01, импульс = 0,9)

model.compile (optimizer = opt, loss =’ategorical_crossentropy ‘, metrics = [‘ precision ‘])

return model

# оценить модель с помощью перекрестной проверки k-кратной проверки

def Assessment_model (dataX, dataY, n_folds = 5):

баллов, history = list (), list ()

# подготовить перекрестную проверку

kfold = KFold (n_folds, shuffle = True, random_state = 1)

# перечислить разбиения

для train_ix, test_ix в kfold.split (dataX):

# определить модель

model = define_model ()

# выбрать строки для обучения и тестирования

trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix] , dataY [test_ix]

# fit model

history = model.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0)

# оценить модель

_ , acc = model.evaluate (testX, testY, verbose = 0)

print (‘>%.3f ‘% (acc * 100.0))

# сохраняет оценки

scores.append (acc)

history.append (history)

return scores, history

# plot диагностические кривые обучения

def summarize_diagnostics ( историй):

для i в диапазоне (len (истории)):

# потеря графика

pyplot.subplot (2, 1, 1)

pyplot.title (‘Cross Entropy Loss’)

pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’)

pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’)

# точность графика

pyplot.subplot (2, 1, 2)

pyplot.title (‘ Точность классификации ‘)

pyplot.plot (history [i] .history [‘ precision ‘], color =’ blue ‘, label =’ train ‘)

pyplot.plot (history [i] .history [‘ val_accuracy ‘ ], color = ‘orange’, label = ‘test’)

pyplot.show ()

# суммировать производительность модели

def summarize_performance (scores):

# print summary

print (‘Accuracy: mean знак равно3f std =%. 3f, n =% d ‘% (среднее (баллы) * 100, std (баллы) * 100, len (баллы)))

# графики результатов в виде прямоугольников и усов

pyplot.boxplot (баллы )

pyplot.show ()

# запустить тестовую программу для оценки модели

def run_test_harness ():

# загрузить набор данных

trainX, trainY, testX, testY = load_dataset ()

данные пикселей

trainX, testX = Prep_pixels (trainX, testX)

# оцените модель

баллов, history = eval_model (trainX, trainY)

# кривые обучения

summarize_diagnostics (history)

# суммируйте

# суммируйте оценочную производительность summarize_performance (scores)

# точка входа, запустить тестовую программу

run_test_harness ()

Повторный запуск примера сообщает о производительности модели для каждого этапа процесса перекрестной проверки.

Примечание : Ваши результаты могут отличаться из-за стохастической природы алгоритма или процедуры оценки или различий в числовой точности. Попробуйте запустить пример несколько раз и сравните средний результат.

Мы можем увидеть, возможно, небольшое снижение производительности модели по сравнению с базовой линией во всех сегментах перекрестной проверки.

> 98,475 > 98,608 > 98,683 > 98,783 > 98,667

> 98.475

> 98,608

> 98,683

> 98,783

> 98,667

Создается график кривых обучения, в данном случае показывающий, что скорость обучения (улучшение по эпохам) не отличается от базовой модели.

Графики показывают, что пакетная нормализация, по крайней мере, реализованная в этом случае, не дает никаких преимуществ.

Кривые потерь и точности для модели BatchNormalization во время перекрестной проверки k-Fold

Далее представлена ​​расчетная производительность модели, показывающая производительность с небольшим снижением средней точности модели: 98.643 по сравнению с 98,677 в базовой модели.

Точность: среднее значение = 98,643 стандартное отклонение = 0,101, n = 5

Точность: среднее = 98,643 стандартное = 0,101, n = 5

Ящик и усовидный график оценок точности для модели BatchNormalization, оцененной с помощью перекрестной проверки k-Fold

Увеличение глубины модели

Есть много способов изменить конфигурацию модели, чтобы изучить улучшения по сравнению с базовой моделью.

Два общих подхода включают изменение емкости части модели извлечения признаков или изменение емкости или функции части классификатора модели. Возможно, наибольшее влияние оказало изменение средства извлечения признаков.

Мы можем увеличить глубину части модели экстрактора признаков, следуя VGG-подобному шаблону добавления дополнительных сверточных и объединяющих слоев с фильтром того же размера, увеличивая при этом количество фильтров. В этом случае мы добавим двойной сверточный слой с 64 фильтрами каждый, а затем еще один слой максимального объединения.

Обновленная версия функции define_model () с этим изменением приведена ниже.

# определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (MaxPooling2D ((2, 2))) model.add (Conv2D (64, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Conv2D (64, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’)) модель.добавить (MaxPooling2D ((2, 2))) model.add (Сглаживание ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0,01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) вернуть модель

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), Activation = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1)))

model.add (MaxPooling2D ((2, 2)))

model.add (Conv2D (64, (3, 3), Activation = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (Conv2D (64, (3, 3), activate = ‘relu’ , kernel_initializer = ‘he_uniform’))

model.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’))

модель.add (Dense (10, activate = ‘softmax’))

# скомпилировать модель

opt = SGD (lr = 0,01, импульс = 0,9)

model.compile (optimizer = opt, loss = ‘categoryorical_crossentropy’, metrics = [‘точность’])

модель возврата

Для полноты ниже приведен полный листинг кода, включая это изменение.

# более глубокая модель cnn для mnist из среднего значения импорта из numpy import std из matplotlib import pyplot из склеарна.model_selection импорт KFold from keras.datasets import mnist from keras.utils import to_categorical из keras.models импортировать Последовательный из keras.layers импортировать Conv2D из keras.layers импорт MaxPooling2D из keras.layers import Плотный из keras.layers import Flatten от keras.optimizers импортные SGD # загрузить поезд и тестовый набор данных def load_dataset (): # загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = поездX.изменить форму ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1)) # одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY) вернуть trainX, trainY, testX, testY # масштабный пиксель def Prep_pixels (поезд, тест): # преобразовать целые числа в числа с плавающей запятой train_norm = train.astype (‘float32’) test_norm = test.astype (‘float32’) # нормализовать до диапазона 0-1 train_norm = train_norm / 255.0 тест_норма = тест_норм / 255.0 # вернуть нормализованные изображения вернуть train_norm, test_norm # определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (MaxPooling2D ((2, 2))) model.add (Conv2D (64, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Conv2D (64, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (MaxPooling2D ((2, 2))) модель.добавить (Flatten ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0,01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) модель возврата # оценить модель с помощью k-кратной перекрестной проверки def оценивать_модель (dataX, dataY, n_folds = 5): оценки, истории = список (), список () # подготовить перекрестную проверку kfold = KFold (n_folds, shuffle = True, random_state = 1) # перечислить разбиения для train_ix, test_ix в kfold.split (dataX): # определить модель модель = define_model () # выбираем строки для обучения и тестирования trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix], dataY [test_ix] # подходящая модель history = model.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0) # оценить модель _, acc = model.evaluate (testX, testY, verbose = 0) print (‘>% .3f’% (согласно * 100.0)) Результаты в # магазинах scores.append (acc) истории.добавить (история) вернуть оценки, истории # построить диагностические кривые обучения def summarize_diagnostics (истории): для i в диапазоне (len (истории)): # потеря сюжета pyplot.subplot (2, 1, 1) pyplot.title (‘потеря перекрестной энтропии’) pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’) pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’) # точность сюжета pyplot.subplot (2, 1, 2) pyplot.title (‘Точность классификации’) пиплот.сюжет (истории [i]. история [‘точность’], цвет = ‘синий’, метка = ‘поезд’) pyplot.plot (history [i] .history [‘val_accuracy’], color = ‘orange’, label = ‘test’) pyplot.show () # подвести итоги работы модели def summarize_performance (баллы): # распечатать сводку print (‘Точность: среднее =%. 3f std =%. 3f, n =% d’% (среднее (баллы) * 100, стандартное (баллы) * 100, len (баллы))) # график результатов в виде квадратов и усов pyplot.boxplot (баллы) pyplot.show () # запускаем тестовую программу для оценки модели def run_test_harness (): # загрузить набор данных trainX, trainY, testX, testY = load_dataset () # подготовить данные пикселей trainX, testX = Prep_pixels (trainX, testX) # оценить модель оценки, истории = оценка_модель (trainX, trainY) # кривые обучения summarize_diagnostics (истории) # подвести итоги расчетной производительности summarize_performance (баллы) # точка входа, запускаем тестовый жгут run_test_harness ()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

21

22

23

24

25

26

27

28

29

30

34

35

36

37

38

39

40

41

42

43

44

45

46

47

0005

51

52

53

54

55

56

57

58

59

60

61

62

63

9 0004 64

65

66

67

68

69

70

71

72

73

74

75

76

70005

81

82

83

84

85

86

87

88

89

90

91

92

94

94

97

98

99

100

101

102

103

104

105

106

107

108

109

110

109

110

# более глубокая модель cnn для mnist

из numpy import mean

из numpy import std

из matplotlib import pyplot

из sklearn.model_selection import KFold

from keras.datasets import mnist

from keras.utils import to_categorical

from keras.models import Sequential

from keras.layers import Conv2D

from keras.layers import d max Dense

из keras.layers import Flatten

from keras.optimizers import SGD

# load train and test dataset

def load_dataset ():

# load dataset

(trainX, trainY), (test testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0 ], 28, 28, 1))

# one целевые значения горячего кодирования

trainY = to_categorical (trainY)

testY = to_categorical (testY)

return trainX, trainY, testX, testY

# scale

def Prep_pixels (train, test):

# преобразовать целые числа в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255.0

# вернуть нормализованные изображения

return train_norm, test_norm

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), activate = ‘relu’, kernel_initializer = ‘ he_uniform ‘, input_shape = (28, 28, 1)))

модель.add (MaxPooling2D ((2, 2)))

model.add (Conv2D (64, (3, 3), activate = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (Conv2D (64, (3, 3), Activation = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add ( Dense (100, Activation = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (Dense (10, activate = ‘softmax’))

# скомпилировать модель

opt = SGD (lr = 0.01, импульс = 0,9)

model.compile (optimizer = opt, loss =’ategorical_crossentropy ‘, metrics = [‘ precision ‘])

return model

# оценить модель с помощью k-кратной перекрестной проверки

def rating_model (dataX, dataY, n_folds = 5):

баллов, history = list (), list ()

# подготовить перекрестную проверку

kfold = KFold (n_folds, shuffle = True, random_state = 1)

# перечислить разбиения

для train_ix, test_ix в kfold.split (dataX):

# определить модель

model = define_model ()

# выбрать строки для обучения и тестирования

trainX, trainY, testX, testY = dataX [train_ix], dataY [train_ix], dataX [test_ix] , dataY [test_ix]

# fit model

history = model.fit (trainX, trainY, epochs = 10, batch_size = 32, validation_data = (testX, testY), verbose = 0)

# оценить модель

_ , acc = model.evaluate (testX, testY, verbose = 0)

print (‘>%.3f ‘% (acc * 100.0))

# сохраняет оценки

scores.append (acc)

history.append (history)

return scores, history

# plot диагностические кривые обучения

def summarize_diagnostics ( историй):

для i в диапазоне (len (истории)):

# потеря графика

pyplot.subplot (2, 1, 1)

pyplot.title (‘Cross Entropy Loss’)

pyplot.plot (history [i] .history [‘loss’], color = ‘blue’, label = ‘train’)

pyplot.plot (history [i] .history [‘val_loss’], color = ‘orange’, label = ‘test’)

# точность графика

pyplot.subplot (2, 1, 2)

pyplot.title (‘ Точность классификации ‘)

pyplot.plot (history [i] .history [‘ precision ‘], color =’ blue ‘, label =’ train ‘)

pyplot.plot (history [i] .history [‘ val_accuracy ‘ ], color = ‘orange’, label = ‘test’)

pyplot.show ()

# суммировать производительность модели

def summarize_performance (scores):

# print summary

print (‘Accuracy: mean знак равно3f std =%. 3f, n =% d ‘% (среднее (баллы) * 100, std (баллы) * 100, len (баллы)))

# графики результатов в виде прямоугольников и усов

pyplot.boxplot (баллы )

pyplot.show ()

# запустить тестовую программу для оценки модели

def run_test_harness ():

# загрузить набор данных

trainX, trainY, testX, testY = load_dataset ()

данные пикселей

trainX, testX = Prep_pixels (trainX, testX)

# оцените модель

баллов, history = eval_model (trainX, trainY)

# кривые обучения

summarize_diagnostics (history)

# суммируйте

# суммируйте оценочную производительность summarize_performance (scores)

# точка входа, запустить тестовую программу

run_test_harness ()

Запуск примера показывает производительность модели для каждого этапа процесса перекрестной проверки.

Примечание : Ваши результаты могут отличаться из-за стохастической природы алгоритма или процедуры оценки или различий в числовой точности. Попробуйте запустить пример несколько раз и сравните средний результат.

Оценка на кратность может свидетельствовать о некотором улучшении по сравнению с исходным уровнем.

> 99,058 > 99,042 > 98,883 > 99,192 > 99,133

> 99.058

> 99.042

> 98.883

> 99.192

> 99.133

Создается график кривых обучения, в данном случае показывающий, что модели по-прежнему хорошо подходят для задачи без явных признаков переобучения. Сюжеты могут даже предполагать, что дальнейшие тренировочные эпохи могут быть полезны.

Кривые потерь и точности для более глубокой модели во время перекрестной проверки k-Fold

Далее представлена ​​расчетная производительность модели, показывающая небольшое улучшение производительности по сравнению с базовой линией 98.От 677 до 99,062, с небольшим падением стандартного отклонения.

Точность: среднее значение = 99,062 стандартное отклонение = 0,104, n = 5

Точность: среднее значение = 99,062 стандартное значение = 0,104, n = 5

Ящик и диаграмма усов для оценки точности для более глубокой модели, оцененной с помощью перекрестной проверки k-Fold

Как завершить модель и сделать прогнозы

Процесс улучшения модели может продолжаться до тех пор, пока у нас есть идеи, время и ресурсы для их проверки.

В какой-то момент должна быть выбрана и принята окончательная конфигурация модели. В этом случае мы выберем более глубокую модель в качестве нашей окончательной модели.

Сначала мы завершим нашу модель, но подгоним модель ко всему набору обучающих данных и сохраним модель в файл для дальнейшего использования. Затем мы загрузим модель и оценим ее производительность на имеющемся тестовом наборе данных, чтобы получить представление о том, насколько хорошо выбранная модель действительно работает на практике. Наконец, мы будем использовать сохраненную модель, чтобы сделать прогноз на одном изображении.

Сохранить окончательную модель

Окончательная модель обычно подходит для всех доступных данных, таких как комбинация всех наборов данных для поездов и тестов.

В этом руководстве мы намеренно удерживаем тестовый набор данных, чтобы мы могли оценить производительность окончательной модели, что может быть хорошей идеей на практике. Таким образом, мы подгоним нашу модель только к набору обучающих данных.

# подходящая модель model.fit (trainX, trainY, epochs = 10, batch_size = 32, verbose = 0)

# подходит модель

модель.fit (trainX, trainY, эпохи = 10, размер_пакета = 32, подробный = 0)

После подгонки мы можем сохранить окончательную модель в файл H5, вызвав для модели функцию save () и передав выбранное имя файла.

# сохранить модель model.save (‘final_model.h5’)

# сохранить модель

model.save (‘final_model.h5’)

Обратите внимание, что для сохранения и загрузки модели Keras требуется, чтобы на вашей рабочей станции была установлена ​​библиотека h5py.

Полный пример подгонки окончательной глубинной модели к набору обучающих данных и ее сохранения в файл приведен ниже.

# сохраняем окончательную модель в файл from keras.datasets import mnist from keras.utils import to_categorical из keras.models импортировать Последовательный из keras.layers импортировать Conv2D из keras.layers импорт MaxPooling2D из keras.layers import Плотный из keras.layers import Flatten от keras.optimizers импортные SGD # загрузить поезд и тестовый набор данных def load_dataset (): # загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1)) # одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY) вернуть trainX, trainY, testX, testY # масштабный пиксель def Prep_pixels (поезд, тест): # преобразовать целые числа в числа с плавающей запятой train_norm = train.astype (‘float32’) test_norm = test.astype (‘float32’) # нормализовать до диапазона 0-1 поезд_норм = поезд_норм / 255.0 test_norm = test_norm / 255.0 # вернуть нормализованные изображения вернуть train_norm, test_norm # определить модель cnn def define_model (): model = Последовательный () model.add (Conv2D (32, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’, input_shape = (28, 28, 1))) model.add (MaxPooling2D ((2, 2))) model.add (Conv2D (64, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Conv2D (64, (3, 3), активация = ‘relu’, kernel_initializer = ‘he_uniform’)) модель.добавить (MaxPooling2D ((2, 2))) model.add (Сглаживание ()) model.add (Dense (100, активация = ‘relu’, kernel_initializer = ‘he_uniform’)) model.add (Плотный (10, активация = ‘softmax’)) # скомпилировать модель opt = SGD (lr = 0,01, импульс = 0,9) model.compile (optimizer = opt, loss = ‘category_crossentropy’, metrics = [‘precision’]) модель возврата # запускаем тестовую программу для оценки модели def run_test_harness (): # загрузить набор данных trainX, trainY, testX, testY = load_dataset () # подготовить данные пикселей trainX, testX = Prep_pixels (trainX, testX) # определить модель модель = define_model () # подходящая модель модель.fit (trainX, trainY, эпохи = 10, размер_пакета = 32, подробный = 0) # сохранить модель model.save (‘final_model.h5’) # точка входа, запускаем тестовый жгут run_test_harness ()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

21

22

23

24

25

26

27

28

29

30

34

35

36

37

38

39

40

41

42

43

44

45

46

47

0005

51

52

53

54

55

56

57

58

59

60

61

62

63

9 0004 64

# сохраняем окончательную модель в файл

из keras.наборы данных import mnist

from keras.utils import to_categorical

from keras.models import Sequential

from keras.layers import Conv2D

from keras.layers import MaxPooling2D

from keras.layers import Dense4 Flatten

из keras.optimizers import SGD

# загрузить поезд и тестовый набор данных

def load_dataset ():

# загрузить набор данных

(trainX, trainY), (testX, testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0 ], 28, 28, 1))

# one целевые значения горячего кодирования

trainY = to_categorical (trainY)

testY = to_categorical (testY)

return trainX, trainY, testX, testY

# scale

def Prep_pixels (train, test):

# преобразовать целые числа в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255.0

# вернуть нормализованные изображения

return train_norm, test_norm

# define cnn model

def define_model ():

model = Sequential ()

model.add (Conv2D (32, (3, 3), activate = ‘relu’, kernel_initializer = ‘ he_uniform ‘, input_shape = (28, 28, 1)))

модель.add (MaxPooling2D ((2, 2)))

model.add (Conv2D (64, (3, 3), activate = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (Conv2D (64, (3, 3), Activation = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (MaxPooling2D ((2, 2)))

model.add (Flatten ())

model.add ( Dense (100, Activation = ‘relu’, kernel_initializer = ‘he_uniform’))

model.add (Dense (10, activate = ‘softmax’))

# скомпилировать модель

opt = SGD (lr = 0.01, импульс = 0,9)

model.compile (optimizer = opt, loss =’ategorical_crossentropy ‘, metrics = [‘ precision ‘])

return model

# запустить тестовую программу для оценки модели

def run_test_harness ():

# загрузить набор данных

trainX, trainY, testX, testY = load_dataset ()

# подготовить данные пикселей

trainX, testX = Prep_pixels (trainX, testX)

# определить модель

define model ()

# подходит модель

модель.fit (trainX, trainY, epochs = 10, batch_size = 32, verbose = 0)

# save model

model.save (‘final_model.h5’)

# точка входа, запуск тестовой среды

run_test_harness ()

После выполнения этого примера в вашем текущем рабочем каталоге будет файл размером 1,2 мегабайта с именем « final_model.h5 ».

Оценка окончательной модели

Теперь мы можем загрузить окончательную модель и оценить ее на имеющемся тестовом наборе данных.

Это то, что мы могли бы сделать, если бы были заинтересованы в представлении эффективности выбранной модели заинтересованным сторонам проекта.

Модель может быть загружена с помощью функции load_model () .

Полный пример загрузки сохраненной модели и ее оценки на тестовом наборе данных приведен ниже.

# оценить глубинную модель на тестовом наборе данных from keras.datasets import mnist из keras.models импортировать load_model из кераса.utils import to_categorical # загрузить поезд и тестовый набор данных def load_dataset (): # загрузить набор данных (trainX, trainY), (testX, testY) = mnist.load_data () # преобразовать набор данных в один канал trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1)) testX = testX.reshape ((testX.shape [0], 28, 28, 1)) # одно горячее кодирование целевых значений trainY = to_categorical (trainY) testY = to_categorical (testY) вернуть trainX, trainY, testX, testY # масштабный пиксель def Prep_pixels (поезд, тест): # преобразовать целые числа в числа с плавающей запятой train_norm = поезд.astype (‘float32’) test_norm = test.astype (‘float32’) # нормализовать до диапазона 0-1 train_norm = train_norm / 255.0 test_norm = test_norm / 255.0 # вернуть нормализованные изображения вернуть train_norm, test_norm # запускаем тестовую программу для оценки модели def run_test_harness (): # загрузить набор данных trainX, trainY, testX, testY = load_dataset () # подготовить данные пикселей trainX, testX = Prep_pixels (trainX, testX) # модель нагрузки model = load_model (‘final_model.h5 ‘) # оценить модель на тестовом наборе данных _, acc = model.evaluate (testX, testY, verbose = 0) print (‘>% .3f’% (согласно * 100.0)) # точка входа, запускаем тестовый жгут run_test_harness ()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

21

22

23

24

25

26

27

28

29

30

34

35

36

37

38

39

40

41

42

# оценить глубокую модель на тестовом наборе данных

от keras.наборы данных import mnist

from keras.models import load_model

from keras.utils import to_categorical

# load train and test dataset

def load_dataset ():

# load dataset (

) testX, testY) = mnist.load_data ()

# преобразовать набор данных в один канал

trainX = trainX.reshape ((trainX.shape [0], 28, 28, 1))

testX = testX.reshape ((testX.shape [0], 28, 28, 1))

# целевые значения one hot encode

trainY = to_categorical (trainY)

testY = to_categorical (testY)

return trainX, trainY, testX, testY

# масштабировать пиксели

def Prep_pixels (train, test):

# преобразовать из целых чисел в числа с плавающей запятой

train_norm = train.astype (‘float32’)

test_norm = test.astype (‘float32’)

# нормализовать до диапазона 0-1

train_norm = train_norm / 255.0

test_norm = test_norm / 255.0

# вернуть нормализованные изображения

return train_norm, test_norm

# запустить тестовую программу для оценки модели

def run_test_harness ():

# загрузить набор данных

trainX, trainY, testX, testY = load_dataset ()

# подготовить пиксельные данные train

, testX = Prep_pixels (trainX, testX)

# загрузить модель

model = load_model (‘final_model.h5 ‘)

# оценить модель на тестовом наборе данных

_, acc = model.evaluate (testX, testY, verbose = 0)

print (‘>% .3f ‘% (acc * 100.0))

# точка входа, запускаем тестовый жгут

run_test_harness ()

При выполнении примера загружается сохраненная модель и оценивается модель в удерживаемом наборе тестовых данных.

Примечание : Ваши результаты могут отличаться из-за стохастической природы алгоритма или процедуры оценки или различий в числовой точности.Попробуйте запустить пример несколько раз и сравните средний результат.

Вычисляется и распечатывается точность классификации модели в тестовом наборе данных. В этом случае мы видим, что модель достигла точности 99,090% или чуть меньше 1%, что совсем неплохо и достаточно близко к расчетным 99,753% со стандартным отклонением около половины процента (например, 99 % баллов).

Сделайте прогноз

Мы можем использовать нашу сохраненную модель, чтобы делать прогнозы на новых изображениях.

Модель предполагает, что новые изображения имеют оттенки серого, что они были выровнены так, что одно изображение содержит одну центрированную рукописную цифру, и что размер изображения квадратный с размером 28 × 28 пикселей.

Ниже приведено изображение, извлеченное из тестового набора данных MNIST. Вы можете сохранить его в текущем рабочем каталоге с именем файла « sample_image.png ».

Пример рукописной цифры

Мы представим, что это совершенно новое и невидимое изображение, подготовленное соответствующим образом, и посмотрим, как мы можем использовать нашу сохраненную модель, чтобы предсказать целое число, которое представляет изображение (например,грамм. мы ожидаем « 7 »).

Во-первых, мы можем загрузить изображение, заставить его быть в формате шкалы серого и установить размер 28 × 28 пикселей. Затем загруженное изображение может быть изменено, чтобы иметь один канал и представлять одну выборку в наборе данных. Функция load_image () реализует это и возвращает загруженное изображение, готовое для классификации.

Важно отметить, что значения пикселей подготавливаются таким же образом, как значения пикселей были подготовлены для обучающего набора данных при подгонке окончательной модели, в данном случае нормализованной.

# загрузить и подготовить изображение def load_image (имя файла): # загрузить изображение img = load_img (имя файла, оттенки серого = True, target_size = (28, 28)) # преобразовать в массив img = img_to_array (img) # преобразовать в один сэмпл с 1 каналом img = img.reshape (1, 28, 28, 1) # подготовить данные пикселей img = img.astype (‘float32’) img = img / 255,0 вернуть img

# загрузить и подготовить изображение

def load_image (filename):

# загрузить изображение

img = load_img (filename, grayscale = True, target_size = (28, 28))

# преобразовать в массив

img = img_to_array (img)

# преобразовать в один образец с 1 каналом

img = img.reshape (1, 28, 28, 1)

# подготовить данные пикселей

img = img.astype (‘float32’)

img = img / 255.0

return img

Затем мы можем загрузить модель, как в предыдущем разделе, и вызвать функцию pred_classes () , чтобы предсказать цифру, которую представляет изображение.

# предсказать класс digit = model.predict_classes (img)

# прогнозировать класс

цифра = модель.pred_classes (img)

Полный пример приведен ниже.

# сделать прогноз для нового изображения. из keras.preprocessing.image import load_img из keras.preprocessing.image import img_to_array из keras.models импортировать load_model # загрузить и подготовить изображение def load_image (имя файла): # загрузить изображение img = load_img (имя файла, оттенки серого = True, target_size = (28, 28)) # преобразовать в массив img = img_to_array (img) # преобразовать в один сэмпл с 1 каналом img = img.изменить форму (1, 28, 28, 1) # подготовить данные пикселей img = img.astype (‘float32’) img = img / 255,0 вернуть img # загружаем изображение и прогнозируем класс def run_example (): # загрузить изображение img = load_image (‘sample_image.png’) # модель нагрузки модель = load_model (‘final_model.h5’) # предсказать класс digit = model.predict_classes (img) печать (цифра [0]) # точка входа, запустим пример run_example ()

1

2

3

4

5

6

7

8

9

10

11

12

13

14

18

19

20

21

22

23

24

25

26

27

28

29

30

# сделать прогноз для нового изображения.

из keras.preprocessing.image import load_img

из keras.preprocessing.image import img_to_array

из keras.models import load_model

# загрузить и подготовить изображение

def load_image (имя файла)

def load_image изображение

img = load_img (filename, grayscale = True, target_size = (28, 28))

# преобразовать в массив

img = img_to_array (img)

# преобразовать в один образец с 1 каналом

img = img.reshape (1, 28, 28, 1)

# подготовить данные пикселей

img = img.astype (‘float32’)

img = img / 255.0

return img

# загрузить изображение и спрогнозировать class

def run_example ():

# загрузить изображение

img = load_image (‘sample_image.png’)

# загрузить модель

model = load_model (‘final_model.h5’)

# предсказать класс

digit = model.predict_classes (img)

print (digit [0])

# точка входа, запустите пример

run_example ()

При выполнении примера сначала загружается и подготавливается изображение, загружается модель, а затем правильно прогнозируется, что загруженное изображение представляет собой цифру « 7 ».

Расширения

В этом разделе перечислены некоторые идеи по расширению учебника, которые вы, возможно, захотите изучить.

  • Настроить масштабирование пикселей . Узнайте, как альтернативные методы масштабирования пикселей влияют на производительность модели по сравнению с базовой моделью, включая центрирование и стандартизацию.
  • Настройте скорость обучения . Узнайте, как разные скорости обучения влияют на производительность модели по сравнению с базовой моделью, например 0,001 и 0.0001.
  • Глубина настройки модели . Изучите, как добавление дополнительных слоев к модели влияет на производительность модели по сравнению с базовой моделью, такой как другой блок сверточных и объединяющих слоев или другой плотный слой в части классификатора модели.

Если вы изучите какое-либо из этих расширений, я хотел бы знать.
Разместите свои выводы в комментариях ниже.

Дополнительная литература

В этом разделе представлены дополнительные ресурсы по теме, если вы хотите углубиться.

API

Статьи

Сводка

В этом руководстве вы узнали, как с нуля разработать сверточную нейронную сеть для классификации рукописных цифр.

В частности, вы выучили:

  • Как разработать тестовую программу для разработки надежной оценки модели и установления базового уровня производительности для задачи классификации.
  • Как изучить расширения базовой модели для улучшения обучения и возможностей модели.
  • Как разработать окончательную модель, оценить производительность окончательной модели и использовать ее для прогнозирования новых изображений.

Есть вопросы?
Задайте свои вопросы в комментариях ниже, и я постараюсь ответить.

Разрабатывайте модели глубокого обучения для Vision сегодня!

Разрабатывайте собственные модели видения за считанные минуты

… всего несколькими строками кода Python

Узнайте, как в моей новой электронной книге:
Deep Learning for Computer Vision

Он предоставляет руководств для самообучения по таким темам, как:
классификация , обнаружение объектов (yolo и rcnn) , распознавание лиц (vggface и facenet) , подготовка данных и многое другое…

Наконец-то привнесите глубокое обучение в проекты вашего видения

Пропустить академики. Только результаты.

Посмотрите, что внутри

кенсаната / чисел: рукописные цифры, немного похожие на набор данных MNIST.

Этот репозиторий пытается создать репозиторий рукописных цифр, так же, как в База данных рукописных цифр MNIST. В Швейцарии рукописные цифры иногда выглядят немного разные, поэтому мы предпринимаем эти усилия.

В этом репозитории есть два набора данных.Они описаны ниже.

Предупреждение: Если вы используете git в Windows для клонирования этого репозиторий, это займет очень много времени, потому что существует так много (крошечные) файлы в нем!

Нашей целью было 10 000 рукописных цифр, и мы достигли этой цели! Если вы хотите помочь нам набрать 20000 рукописных цифр, проверьте каталог инструментов.

Имя каталога каждого вклада соответствует следующим схема наименования:

  1. четыре цифры для идентификации человека
  2. символ подчеркивания
  3. двухбуквенный код страны (коды ISO 3166 Alpha-2) или XX , если он неизвестен (например,грамм. Швейцария CH )
  4. возраст, округленный до ближайшего десятилетия (например, от 35 до 44 лет это 4 ) или X , если неизвестно
  5. пол ( M для мужчины, F для женщины, X для неизвестного, O для другого)

В рамках коммерческого проекта обучена нейросеть на числа вырезаны из очень большого собрания документов. Есть так много цифр в этом наборе, что качество данных ниже, чем в ручной сбор.Вы можете найти этот набор в БЕСПЛАТНЫЙ каталог. Чуть более 800 000 цифр!

  • цифр могут быть неправильно отнесены к категории или иметь неправильный формат (например, 554)
  • цифр написаны от руки и напечатаны (например, 552)
  • распределение цифр неравномерное
  • Информация об авторах отсутствует

Я с радостью приму пул-реквесты, которые исправят неправильно классифицированные или неправильные цифры.

По распределению номеров:

  цифровой файл
  0 323945
  1 
  2 71820
  3 55240
  4 46143
  5 96376
  6 39868
  7 34836
  8 37124
  9 34571
  

Как создать супер простой идентификатор рукописных чисел | автор: JOSÉ MANUEL NÁPOLES DUARTE

Удобное для новичков использование косинусного подобия

Всякий раз, когда вы начинаете с машинного обучения, есть несколько хорошо известных наборов данных (набор данных Iris, например 🥀).Среди них есть один для изображений, который прост, популярен и интересен, а именно набор данных MNIST, который состоит из большого количества рукописных цифр 📝 [1].

Здесь мы собираемся использовать невероятно простую идею для получения информации из этих изображений: косинус угла между двумя векторами . Так что это будет особенно хорошо для новичков в ML или DS 😉. Вероятно, вы знакомы с скалярным произведением векторов. В этом случае вы, возможно, знаете, что его можно получить двумя способами: с помощью суммы произведения компонентов и произведения величин и косинуса угла i.е . для двух векторов, называемых A и B в трех измерениях, мы имеем:

Это расширено до нескольких (конечных) измерений и определяет так называемое сходство как косинус угла [2]:

Таким образом, два вектора, которые указывают в одном направлении, таким образом, будучи «похожими», имеют сходство , близкое к 1, и оно переходит к более низким значениям (вплоть до -1), поскольку они более различны.

Пока все хорошо, но теперь давайте обратимся к изображениям рукописных цифр и к тому, как использовать эту концепцию, чтобы определить, какие цифры среди них похожи.

Некоторые цифры MNIST. Изображение автора.

Используя Scikit-learn, можно легко получить доступ к набору данных MNIST [3]:

Здесь X содержит информацию о данных каждой цифры в векторной форме. Каждое изображение представляет собой матрицу размером 28×28 пикселей, таким образом, векторы X имеют 784 элемента. Именно эти векторы мы хотим сравнить. Чтобы сделать это как можно проще, я сосредоточусь на цифре X [1] , которая соответствует изображению нуля, как показано ниже:

График цифры, соответствующей X [1].Изображение автора.

Задача состоит в том, чтобы найти векторы, которые похожи на X [1] и предположительно также являются нулями. Следующий код решает эту проблему при условии, что вы импортировали numpy:

Здесь j = 1 (поэтому X [j] — это ноль, который нам нужен), а i пробегает первые 5000 элементов. В строке 6 у нас есть pp , обозначающее скалярное произведение между X [i] и X [j] . Затем в строке 9 он делится на произведение нормы векторов, дающих косинус угла ( Сходство ).Помните, что мы хотим, чтобы эти значения были близки к 1, поэтому в строках с 10 по 14 мы используем функцию Гаусса для фильтрации значений, близких к 1. Значение сигмы может быть скорректировано с учетом того, что самая большая сигма, мы примем больше векторов. это может быть не так похоже. В строке 13 есть условие принимать только значения высоты функции Гаусса больше 0,3, чтобы гарантировать, что все векторы соответствуют нулю, подобному выбранному. Вот результат с этими значениями:

Обнаруженные нули аналогичны первым встреченным.Изображение автора.

Потрясающе !! работает неплохо 🥂. Здесь важно отметить, что это не все нули, а только те, которые больше похожи на первые, которые мы выбрали. Но, безусловно, должны быть другие стили для написания нулей, заменяющие разные формы для одного и того же числа. Вы можете попробовать использовать другие цифры и получить хорошие результаты, если число имеет «хорошую форму». Я имею в виду, что есть некоторые цифры, которые настолько своеобразны, что их сложно идентифицировать даже человеку 😅.

Я использовал ту же идею на хакатоне, связанном с геномикой, для идентификации генов, экспрессирующихся при заболеваниях почек, и работал достаточно хорошо, чтобы удостоиться почетного упоминания 🔥.Неплохо для моего второго хакатона! Так что, помимо простоты, не стоит недооценивать эту технику.

Если вы хотите поиграть с кодом, показанным выше, вот ссылка на Colab Notebook:

Спасибо за чтение !!

Ссылки:

[1] https://en.wikipedia.org/wiki/MNIST_database.

[2] https://en.wikipedia.org/wiki/Cosine_similarity.

[3] https://scikit-learn.org/stable/modules/generated

/sklearn.datasets.load_digits.html

Превосходя 99% — Распознавание рукописных цифр MNIST | автор: Джей Гупта

 model = Sequential ([# Layer 1 
Conv2D (filters = 32, kernel_size = 5, strides = 1, activate = ‘relu’, input_shape = (32,32,1), kernel_regularizer = l2 (0.0005)), # Layer 2
Conv2D (filters = 32, kernel_size = 5, strides = 1, use_bias = False), # Layer 3
BatchNormalization (), # - - - - - - - - - - - - - - - - - #
Activation («relu»),
MaxPooling2D (pool_size = 2, strides = 2),
Dropout (0,25),
# - - - - - - - - - - - - - - - - - - - - - - - - - ## Layer 3
Conv2D (фильтры = 64, размер ядра = 3, шаги = 1, активация = 'relu', kernel_regularizer = l2 (0,0005)), # уровень 4
Conv2D (фильтры = 64, размер ядра = 3, шаги = 1, use_bias = False), # Layer 5
BatchNormalization (), # - - - - - - - - - - - - - - - - #
Activation («relu»),
MaxPooling2D (pool_size = 2, strides = 2),
Выпадение (0.25),
Flatten (),
# - - - - - - - - - - - - - - - - ## Layer 6
Dense (units = 256, use_bias = False), # Layer 7
BatchNormalization (), # - - - - - - - - - - - - - - - - #
Активация («relu»),
# - - - - - - - - - - - - - - - - ## Layer 8
Dense (units = 128, use_bias = False), # Layer 9
BatchNormalization (), # - - - - - - - - - - - - - - - - - #
Activation («relu»),
# - - - - - - - - - - - - - - - - ## Layer 10
Dense (units = 84, use_bias = False), # Layer 11
BatchNormalization (), # - - - - - - - - - - - - - - - - - #
Активация («relu»),
Выпадение (0.25),
# - - - - - - - - - - - - - - - - ## Output
Dense (units = 10, activate = 'softmax')])

Модель обучалась за 30 эпох и выдала следующий результат.

  • Точность обучения 99,82%
  • Точность набора разработчика 99,62%
  • Точность тестового набора 99,41%

Упомянутые оптимизации помогли значительно повысить точность модели за пределы 99%.

Мы можем отметить, что все еще есть некоторые признаки переобучения, поскольку точность тестового набора снижается.Не стесняйтесь поэкспериментировать и постарайтесь еще больше уменьшить дисперсию. Если вы считаете, что есть другие способы улучшить модель, оставьте, пожалуйста, комментарий.

Весь код и результаты доступны на GitHub здесь.

Ссылки

[1] LeCun et al., Градиентное обучение, применяемое к распознаванию документов (1998), Proc of the IEEE, November 1998

[2] Эндрю Нг и др., Улучшение глубоких нейронных сетей: настройка гиперпараметров , Регуляризация и оптимизация, Курс Coursera

[3] Y.Ghouza, Введение в CNN Keras — 0,997 (лучшие 6%) (2017), Конкурс Kaggle Digit Recognizer Competition

[4] Шривастава, Нитиш и др., Dropout: простой способ предотвратить переоснащение нейронных сетей, (2014) JMLR

Узнай свои рукописные числа | by Ole Kröger

В последней записи в блоге вы узнали, как оцифровать одну рукописную цифру. Минусом было то, что вам нужно захватить одну цифру, а изображение должно быть квадратичным.

Но это не так.Пришло время сделать еще один шаг. Из этой статьи вы узнаете, как «находить» цифры на листе бумаги и распознавать их.

Я не хочу лгать: на данный момент работает только в том случае, если лист пустой и вы пишете с хорошим контрастом. И, к сожалению, на бумаге больше ничего не должно быть. Если есть другие темные «точки», они также будут распознаваться как цифры. В MNIST нет изображений для нецифровых изображений, поэтому для нашей нейронной сети нет примеров счетчиков.

Но давайте начнем с нашего кода: убедитесь, что вы прочитали мою предыдущую запись в блоге о распознавании цифр.

Вначале я хотел бы сохранить текущий экземпляр нашей обученной модели. Нет необходимости обучать модель каждый раз, когда мы вызываем программу.

Для этого вам необходимо заменить эти строки

 # инициализировать все переменные 
init = tf.initialize_all_variables () # создать сеанс
sessions = tf.Session ()
sessions.run (init)

следующими:

 # мы будем использовать , используя  image + ". png" 
image = sys.argv [1]
train = False , если len (sys.argv) == 2 else sys.argv [2]
checkpoint_dir = "cps /" saver = tf.train.Saver ()
sessions = tf. Session ()
# инициализировать все переменные и запустить init
sessions.run (tf.initialize_all_variables ())

Здесь папка cps / должна существовать в вашей корневой папке («cps» = наши контрольные точки папка)

Первая строка проверяет, хотим ли мы обучить модель. Если вы хотите, вам нужно запустить программу с:

 python2 step2.py IMAGE_NAME  True  

Следующий шаг — проверить, хотим ли мы обучать или использовать контрольную точку:

, если поезд: 
# создать папку MNIST_data с набором данных MNIST , если необходимо
mnist = input_data .read_data_sets ("MNIST_data /", one_hot = True) # использовать 1000 пакетов с a размером из 100 каждый до обучить нашу сеть
для i в диапазоне (1000) :
batch_xs, batch_ys = mnist.train.next_batch (100)
# запустить функцию train_step с заданным изображением значений (x) и реальный output (y_)
sessions.run (train_step, feed_dict = {x : batch_xs, y_: batch_ys})
saver.save (sess, checkpoint_dir + 'model.ckpt') correiction = tf.equal (tf.argmax (y, 1), tf.argmax (y_, 1))
precision = tf .reduce_mean (tf. cast (right_prediction, "float"))
print sessions.run (precision, feed_dict = {x: mnist.test.images, y_: mnist.test.labels})
else :
# Здесь вы восстанавливаете переменные w и b.
# Обратите внимание, что график - это , ровно , так как было , когда переменные , были
# сохранены в , перед тренировочным запуском .
ckpt = tf.train.get_checkpoint_state (checkpoint_dir)
если ckpt и ckpt.model_checkpoint_path:
saver. восстановить (сессия, ckpt.model_checkpoint_path)
else :
print 'Контрольная точка не найдена'
exit (1)

В ветку if мы добавили только строку

 saver.save (sessions, checkpoint_dir + 'model.ckpt') 

Ветвь else восстанавливает КПП.

Общий подход заключается в том, что мы хотим прочитать изображение, которое содержит наши рукописные цифры. Затем нам понадобятся две версии этого изображения: неизмененный оригинал и черно-белый, которые мы можем проанализировать в несколько этапов.

 # прочитать исходное изображение 
color_complete = cv2.imread ("img / blog /" + image + ".png") # читать черно-белое изображение
gray_complete = cv2.imread ("img / blog /" + image + ".png", cv2.CV_LOAD_IMAGE_GRAYSCALE) # лучше черный и белая версия
(thresh, gray_complete) = cv2.threshold (255-gray_complete, 128, 255, cv2.THRESH_BINARY | cv2.THRESH_OTSU)
cv2.imwrite ("pro-img /comp.png", gray_complete) digit_image = -np .ones (gray_complete.shape)

Здесь мы сначала читаем оригинал, который нам нужен, чтобы отобразить наши зеленые прямоугольники и показать наш прогноз.Затем мы делаем шаги, которые мы сделали в предыдущей записи блога.

Последняя строка создает матрицу размером с наше изображение и заполняет ее значением -1. Внутри этого массива мы сохраним место, где мы уже нашли цифру, поэтому невозможно распознать одну и ту же цифру дважды. Это ускоряет процесс и останавливает алгоритм, чтобы создать беспорядок цифр.

Чтобы найти цифры внутри нашего большого изображения, мы будем обрезать его разными способами. Если внутри нашей обрезанной части есть только одна цифра, мы можем легко найти наименьший прямоугольник вокруг этой цифры.

Прошу прощения за следующую вложенную структуру из четырех циклов for.

 height, width = gray_complete.shape "" "
обрезка на несколько изображений
" ""
для cropped_width в диапазоне (100, 300, 20):
для cropped_height в диапазоне (100, 300, 20):
для shift_x в диапазоне (0, width-cropped_width, cropped_width / 4):
для shift_y в диапазоне (0, height-cropped_height, cropped_height / 4):

Здесь мы определяем наименьшую и наибольшую ширину и высоту одной цифры (cropped_width и cropped_height).Затем мы должны сдвинуть прямоугольник с помощью циклов shift_x и shift_y for.

Весь следующий код будет внутри этих вложенных циклов.

Наше обрезанное изображение называется серым:

 gray = gray_complete [ shift  _y:  shift  _y + cropped_height,  shift  _x:  shift  _x + cropped_width] 

Если обрезанное изображение почти пустое (пустое) мы можем перейти к следующему:

  if  np.count_nonzero (gray) <= 20: 
continue

А если где-то прорезать цифру, что означает отсутствие белой границы, мы можем продолжить а также:

 , если  (np.sum (gray [0])! = 0)  или  (np.sum (gray [:, 0])! = 0)  или  (np.sum (gray [-1])! = 0)  или  (np.sum (gray [:, - 1])! = 0): 
continue

Мы хотим сохранить верхнее левое и нижнее правое положение нашего прямоугольника, чтобы показать прямоугольник в конце.

 top_left = np.array ([ shift  _y,  shift  _x]) 
bottom_right = np.array ([ shift _y + cropped_height, shift _x + cropped_width])

Теперь мы можем найти наименьший прямоугольник так же, как и в прошлый раз.

 , а  np.sum (серый [0]) == 0: 
top_left [0] + = 1
серый = серый [1:] , а np.sum (серый [:, 0]) == 0:
top_left [1] + = 1
серый = np. удалить (серый, 0,1) , а np.sum (gray [-1]) == 0:
bottom_right [0] - = 1
gray = gray [: - 1] , а np.sum (серый [:, - 1]) == 0:
bottom_right [1] - = 1
серый = np. удалить (серый, -1,1)

, но нам нужно изменить верхнюю левую и нижнюю правую точки внутри циклов.

Теперь мы можем проверить, есть ли уже цифра внутри текущего прямоугольника, используя наш массив digit_image.

 actual_w_h = bottom_right-top_left 
if (np.count_nonzero (digit_image [top_left [0]: bottom_right [0], top_left [1]: bottom_right [1]] + 1)>
0,2 * actual_w_h [0] * actual_w_h [1]):
продолжить

Что именно мы делаем?

Сначала мы получаем прямоугольник внутри нашего digit_image, используя:

  digit_image  [top_left [0]: bottom_right [0],  top_left  [1]: bottom_right [1]] 

но на этапе инициализации все заполненный -1, который, очевидно, не равен нулю.Поэтому мы добавляем +1 перед подсчетом количества ненулевых значений. Если это число больше 20% от фактического изображения, мы бы сказали, что пространство уже используется, и, возможно, мы уже нашли именно эту цифру.

Ниже выполняется предварительная обработка одной цифры, как в прошлый раз. Нам нужно изменить его размер до изображения 28×28, но мы хотим сохранить соотношение, поэтому мы добавляем несколько черных линий, имейте в виду, что изображение в данный момент инвертировано вверху, внизу или слева и справа.

 рядов, столбцы = серый.shape 
compl_dif = abs (строки-столбцы)
half_Sm =comp_dif / 2
half_Big = half_Sm if half_Sm * 2 ==comp_dif else half_Sm + 1
if

0 rows> cols: np. lib.pad (серый, ((0,0), (half_Sm, half_Big)), 'constant')
else :
серый = np.lib.pad (серый, ((half_Sm, half_Big), (0, 0)), 'constant')

Здесь нам нужна меньшая и большая половина, чтобы в конце было квадратное изображение.

И затем мы изменяем его размер до нашего внутреннего ограничивающего прямоугольника 20×20, добавляем черные линии, чтобы получить изображение 28×28, и смещаем его, используя центр масс.

 серый = cv2.resize (серый, (20, 20)) 
серый = np.lib.pad (серый, ((4,4), (4,4)), 'константа') shiftx, shiftty = getBestShift (серый)
смещенный = сдвиг (серый, shiftx, сдвигающийся)
серый = сдвинутый

Чтобы получить наш прогноз, мы должны сгладить изображение и использовать значения от 0 до 1.

  сгладить  = серый.flatten () / 255.0 

Для получения нашего прогноза нам потребуются следующие линии тензорного потока:

 prediction = [tf.reduce_max (y), tf.argmax (y, 1) [0]] 
pred = sessions.run (prediction, feed_dict = {x: [flatten]})
print pred

Первое значение внутри pred — это вероятность того, что второе значение, которое представляет наш прогноз, является правильным. Что ж, вероятность измеряется нашим алгоритмом и, вероятно, не так надежна.

В верхней части наших вложенных lopps мы использовали наш массив digit_image, теперь пришло время заполнить его некоторым значением, потому что теперь мы нашли цифру:

 digit_image [top_left [0]: bottom_right [0], top_left [1] : bottom_right [1]] = pred [1] 

Хорошо, на самом деле не цифра, а просто несколько точек на белой бумаге, но мы думаем, что это цифра.

Давайте добавим нашу зеленую границу и наш прогноз к нашему исходному изображению:

 cv2.rectangle (color_complete, tuple (top_left [:: - 1]), tuple (bottom_right [:: - 1]), color = (0,255, 0), толщина = 5) font = cv2.FONT_HERSHEY_SIMPLEX 
# предсказанная цифра
cv2.putText (color_complete, str (pred [1]), (top_left [1], bottom_right [0] +50),
font, fontScale). = 1,4, цвет = (0,255,0), толщина = 4)
# процент
cv2.putText (color_complete, format (pred [0] * 100, «. 1f») + «%», (top_left [1] + 30, bottom_right [0] +60), шрифт
, fontScale = 0.8, цвет = (0,255,0), толщина = 2)

После циклов мы теперь хотим сохранить наше изображение:

 cv2.imwrite ("pro-img / digitized_image.png", color_complete) 

Как хороший наш подход? Во-первых, это довольно просто. Мы не можем работать со всеми размерами цифр, потому что ширина обрезки определяется внутри кода.

Но если это не проблема, большая проблема состоит в том, что чистый лист бумаги должен содержать только числа.

Чтобы избежать этого, нам понадобится другая нейронная сеть, которая может сказать нам, содержит ли обрезанная часть изображения число или нет.Что-то вроде встречных примеров для MNIST. Затем мы можем добавить их в наши обучающие примеры и добавить еще одно значение 11, которое не представляет собой цифру (сокращенно NaD: D). Если наше предсказание имеет максимальное значение на этом одиннадцатом значении, мы можем его проигнорировать.

Вы можете загрузить весь код из моего репозитория OpenSourcES GitHub.

Если вас интересуют другие сообщения о машинном обучении и других вещах: посетите OpenSourcES.

Этот пост изначально размещен в моем блоге OpenSourcES.

Классификация рукописных цифр с использованием CNN

Эта статья была опубликована в рамках Data Science Blogathon

Введение

(CNN) для классификации рукописных цифр из популярного набора данных.

Рисунок 1: Набор данных MNIST (Изображение предоставлено en.wikipedia.org/wiki/MNIST_database)

Обязательный

Хотя каждый шаг будет подробно объяснен в этом руководстве, он, безусловно, принесет пользу тем, кто уже имеет некоторые теоретические знания о работе CNN.Также неплохо иметь некоторые знания о TensorFlow, но это не обязательно.

Сверточная нейронная сеть

Для тех из вас, кто плохо знаком с этой концепцией, CNN — это метод глубокого обучения для автоматической классификации входных данных (ну, после того, как вы предоставите правильные данные). За прошедшие годы CNN научилась классифицировать изображения для компьютерных образов, и теперь она также используется в сфере здравоохранения. Это указывает на то, что CNN является надежным алгоритмом глубокого обучения для автоматизированного сквозного прогнозирования.CNN, по сути, автоматически извлекает «полезные» функции из заданных входных данных, что делает это для нас очень простым!

Рисунок 2: Сквозной процесс CNN

Модель CNN состоит из трех основных уровней: сверточный уровень , уровень (и) объединения, и полностью связанный уровень .

(1) Сверточный слой : этот слой извлекает входные объекты высокого уровня из входных данных и передает эти объекты на следующий слой в виде карт объектов.

(2) Уровень объединения : Он используется для уменьшения размеров данных путем применения объединения на карте функций для создания новых карт функций с уменьшенными размерами. PL принимает максимум или среднее значение на старой карте функций в пределах заданного шага.

(3) Уровень с полным подключением : Наконец, задача классификации выполняется на уровне FC. Оценки вероятности рассчитываются для каждой метки класса с помощью популярной функции активации, называемой функцией softmax.

Для получения более подробной информации я настоятельно рекомендую вам ознакомиться с этим замечательным руководством по Analytics Vidhya.

Набор данных

Набор данных, который здесь используется, представляет собой набор данных классификации цифр MNIST . Keras — это API глубокого обучения, написанный на Python, а MNIST — это набор данных, предоставляемый этим API. Этот набор данных состоит из 60 000 обучающих изображений и 10 000 тестовых изображений. Это достойный набор данных для людей, которым необходимо попробовать себя в распознавании образов, поскольку мы сделаем это всего за минуту!

Когда вызывается API Keras, возвращаются четыре значения, а именно: x_train, y_train, x_test и y_test .Не волнуйтесь, я расскажу вам об этом.

Загрузка набора данных

Используемый язык — python. Я собираюсь использовать Google Colab для написания и выполнения кода Python. Вы также можете выбрать блокнот jupyter. Я выбираю Google Colab, потому что он обеспечивает легкий доступ к записным книжкам в любое время и в любом месте. Также возможно подключить записную книжку colab к репозиторию GitHub.

Кроме того, код, используемый в этом руководстве, доступен в этом репозитории Github. Так что, если вы где-то застряли, обязательно проверьте этот репозиторий.Чтобы это руководство оставалось актуальным для всех, мы разберемся с наиболее важным кодом.

  1. Создайте блокнот и назовите его.
  2. После загрузки необходимых библиотек загрузите набор данных MNIST, как показано ниже:
 (X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data () 

Как мы обсуждали ранее, этот набор данных возвращает четыре значения в том же порядке, как указано выше. Кроме того, x_train, y_train, x_test и y_test являются представлениями для обучающих и тестовых наборов данных.Чтобы понять, как набор данных делится на обучение и тестирование, посмотрите изображение ниже, которое я использовал во время сеанса, на котором я говорил о C

.

Рисунок 3: Разделение набора данных на обучающий и тестовый набор

Вуаля ! Вы только что загрузили свой набор данных и готовы перейти к следующему шагу, который должен обработать данные

Обработка набора данных

Данные необходимо обрабатывать, очищать, исправлять, чтобы улучшить их качество. CNN будет лучше всего учиться на наборе данных, который не содержит никаких нулевых значений, имеет все числовые данные и масштабируется.Итак, здесь мы выполним несколько шагов, чтобы убедиться, что наш набор данных идеально подходит для обучения модели CNN. С этого момента, пока мы не создадим модель CNN, мы будем работать только с обучающим набором данных.

Если вы напишете X_train [0], то получите 0-е изображение со значениями от 0 до 255 (0 означает черный, а 255 означает белый). Результатом является двумерная матрица (конечно, мы не будем знать, что представляет собой рукописная цифра X_train [0]. Чтобы узнать это, напишите y_train [0], и вы получите 5 на выходе.Это означает, что 0-е изображение этого обучающего набора данных представляет собой число 5.

Итак, давайте масштабируем эти обучающие и тестовые наборы данных, как показано ниже:

 X_train = X_train / 255
X_test = X_test / 255 

После масштабирования мы должны преобразовать двумерную матрицу в одномерный массив, используя это:

 X_train = X_train.reshape (-1,28,28,1) # обучающий набор 
 X_test = X_test.reshape (-1,28,28,1) # набор тестов 

Теперь, когда набор данных выглядит хорошо, самое время создать сверточную нейронную сеть.

Создание и обучение CNN

Давайте создадим модель CNN с помощью библиотеки TensorFlow. Модель создана следующим образом:

 convolutional_neural_network = models.Sequential ([
    Layers.Conv2D (Filters = 25, kernel_size = (3, 3), Activation = 'relu', input_shape = (28,28,1)),
    Layers.MaxPooling2D ((2, 2)), 
 слоев.Conv2D (Filters = 64, kernel_size = (3, 3), Activation = 'relu'),
    Layers.MaxPooling2D ((2, 2)),
    Layers.Conv2D (фильтры = 64, размер_ядра = (3, 3), активация = 'relu'),
    слои.MaxPooling2D ((2, 2)), 
 слоя. Плоский (),
    Layers.Dense (64, активация = 'relu'),
    Layers.Dense (10, активация = 'softmax')
]) 

Потратьте некоторое время, чтобы позволить всему этому коду погрузиться в работу. Важно, чтобы вы понимали каждую его часть. В модели CNN, созданной выше, есть входной слой, за которым следуют два скрытых слоя и, наконец, выходной слой. Проще говоря, функции активации отвечают за принятие решения о том, двигаться вперед или нет.В глубокой нейронной сети, такой как CNN, есть много нейронов, и в зависимости от функций активации нейроны запускаются, и сеть движется вперед. Если вы плохо разбираетесь в функциях активации, используйте «relu», так как он используется наиболее часто.

После того, как модель создана, пора скомпилировать ее, и соответствует модели . В процессе подгонки модель просматривает набор данных и понимает отношения. Он будет учиться на протяжении всего процесса столько раз, сколько было определено.В нашем примере мы определили 10 эпох. В ходе этого процесса модель CNN будет учиться и также делать ошибки. За каждую ошибку (т. Е. Неверный прогноз), которую делает модель, существует штраф, который отражается в значении потерь для каждой эпохи (см. GIF ниже). Короче говоря, модель должна давать как можно меньше потерь и как можно более высокую точность в конце последней эпохи.

GIF 1: Обучение CNN и повышение точности в каждую эпоху

Делать прогнозы

Чтобы оценить созданную таким образом модель CNN, вы можете запустить:

 convolutional_neural_network.оценить (X_test, y_test) 

Пришло время использовать наш тестовый набор данных, чтобы увидеть, насколько хорошо будет работать модель CNN.

 y_predicted_by_model = convolutional_neural_network.predict (X_test) 

Приведенный выше код будет использовать модель convolutional_neural_network, чтобы делать прогнозы для тестового набора данных и сохранять его в кадре данных y_predicted_by_model. Для каждой из 10 возможных цифр будет рассчитана оценка вероятности. Класс с наивысшей оценкой вероятности — это прогноз, сделанный моделью.Например, если вы хотите узнать, какая цифра в первой строке тестового набора:

 y_predicted_by_model [0] 

Результат будет примерно таким:

 массив ([3.4887790e-09, 3.4696127e-06, 7.7428967e-07, 2.9782784e-08,
       6.3373392e-08, 6.1983449e-08, 7.4500317e-10, 9.9999511e-01,
       4.2418694e-08, 3.8616824e-07], dtype = float32) 

Поскольку действительно сложно идентифицировать метку выходного класса с наивысшей оценкой вероятности, давайте напишем другой код:

 нп.argmax (y_predicted [0]) 

И с этим вы получите одну из десяти цифр в качестве вывода (от 0 до 9).

Заключение

В этом блоге мы начнем с обсуждения сверточной нейронной сети и ее важности. В руководстве также рассказывается, как набор данных делится на набор данных для обучения и тестирования. В качестве примера был взят популярный набор данных под названием MNIST для прогнозирования рукописных цифр от 0 до 9. Набор данных был очищен, масштабирован и сформирован. С помощью TensorFlow была создана модель CNN, которая в конечном итоге была обучена на обучающем наборе данных.Наконец, прогнозы были сделаны с использованием обученной модели.

Я бы посоветовал читателям попробовать это самостоятельно, немного изменив гиперпараметры модели, чтобы посмотреть, смогут ли они достичь более высокой точности или нет. Если вы столкнетесь с какой-либо проблемой, сообщите нам об этом в разделе комментариев, и мы будем рады поддержать.

Список литературы

  1. Команда, К.
Автор записи

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *