Conjunto de dados MNIST
O conjunto de dados MINST significa "Modified National Institute of Standards and Technology". O conjunto de dados contém uma grande coleção de dígitos manuscritos que é comumente usado para treinar vários sistemas de processamento de imagem. O conjunto de dados foi criado remisturando amostras dos conjuntos de dados originais do NIST, que foram retiradas de funcionários do American Census Bureau e estudantes do ensino médio. Ele foi projetado para ajudar os cientistas a desenvolver e testar algoritmos de aprendizado de máquina em reconhecimento de padrões e aprendizado de máquina. Ele contém 60.000 imagens de treinamento e 10.000 imagens de teste, cada uma das quais é uma imagem em tons de cinza de tamanho 28x28 pixels.
Carregando conjunto de dados MNIST usando TensorFlow/Keras
Este excerto de código carrega o exemplo do conjunto de dados MNIST usando Keras, obtém as imagens e rótulos de treino e, em seguida, apresenta quatro imagens numa linha com os seus respetivos rótulos. Cada imagem é mostrada a preto e branco (escala de cinzentos).
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
import numpy as np
from tensorflow.keras.datasets import mnist
import matplotlib.pyplot as plt
import numpy as np
# Load the MNIST dataset
(X_train, y_train), (_, _) = mnist.load_data()
# Print 4 images in a row
plt.figure(figsize=(10, 5))
for i in range(4):
plt.subplot(1, 4, i+1)
plt.imshow(X_train[i], cmap='gray')
plt.title(f"Label: {y_train[i]}")
plt.axis('off')
plt.tight_layout()
plt.show()

Carregando o conjunto de dados MNIST usando o PyTorch
Neste exemplo, exploraremos para carregar o exemplo de pytorch do conjunto de dados mnist. PyTorch oferece um utilitário semelhante através de torchvision.datasets, o que é muito conveniente, especialmente quando combinado com torchvision.transforms para executar pré-processamento básico, como converter imagens para o formato tensor.
import matplotlib.pyplot as plt
import torch
from torchvision import datasets, transforms
# Define the transformation to convert images to PyTorch tensors
transform = transforms.Compose([transforms.ToTensor()])
# Load the MNIST dataset with the specified transformation
mnist_pytorch = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
# Create a DataLoader to load the dataset in batches
train_loader_pytorch = torch.utils.data.DataLoader(mnist_pytorch, batch_size=1, shuffle=False)
# Create a figure to display the images
plt.figure(figsize=(15, 3))
# Print the first few images in a row
for i, (image, label) in enumerate(train_loader_pytorch):
if i < 5: # Print the first 5 samples
plt.subplot(1, 5, i + 1)
plt.imshow(image[0].squeeze(), cmap='gray')
plt.title(f"Label: {label.item()}")
plt.axis('off')
else:
break # Exit the loop after printing 5 samples
plt.tight_layout()
plt.show()
Reconhecimento de dígitos manuscritos usando Python
Vamos implementar um aplicativo de reconhecimento de dígitos manuscrito usando o conjunto de dados MNIST. Usaremos um tipo especial de rede neural profunda chamada Redes Neurais Convolucionais. No final, vamos construir uma GUI na qual pode-se desenhar o dígito e reconhecê-lo imediatamente.
%pip install numpy, tensorflow, keras, pillow,
Importar as bibliotecas e carregar o conjunto de dados
A biblioteca Keras já contém alguns conjuntos de dados e o MNIST é um deles. Assim, podemos importar facilmente o conjunto de dados e começar a trabalhar com ele. O método 'mnist.load_data()' nos retorna os dados de treinamento, seus rótulos e também os dados de
import keras
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Dropout, Flatten
from keras.layers import Conv2D, MaxPooling2D
from keras import backend as K
# the data, split between train and test sets
(x_train, y_train), (x_test, y_test) = mnist.load_data()
print(x_train.shape, y_train.shape)
Pré-processar os dados
Os dados de imagem não podem ser alimentados diretamente no modelo, então precisamos executar algumas operações e processar os dados para torná-los prontos para nossa rede neural. A dimensão dos dados de formação é (60000, 28, 28). O modelo CNN exigirá mais uma dimensão, por isso remodelamos a matriz para dar forma (60000, 28, 28, 1).
x_train = x_train.reshape(x_train.shape[0], 28, 28, 1)
x_test = x_test.reshape(x_test.shape[0], 28, 28, 1)
input_shape = (28, 28, 1)
# Define the number of classes
num_classes = 10
# convert class vectors to binary class matrices
y_train = keras.utils.to_categorical(y_train, num_classes)
y_test = keras.utils.to_categorical(y_test, num_classes)
x_train = x_train.astype('float32')
x_test = x_test.astype('float32')
x_train /= 255
x_test /= 255
print('x_train shape:', x_train.shape)
print(x_train.shape[0], 'train samples')
print(x_test.shape[0], 'test samples')
Criar o modelo
Um modelo CNN geralmente consiste em camadas convolucionais e de pooling. Ele funciona melhor para dados que são representados como estruturas de grade, e é por isso que os CNNs funcionam bem para problemas de classificação de imagens. A camada de abandono é usada para desativar alguns dos neurônios durante o treinamento, reduzindo o overfitting do modelo. Em seguida, compilaremos o modelo com o otimizador Adadelta.
batch_size = 128
num_classes = 10
epochs = 10
model = Sequential()
model.add(Conv2D(32, kernel_size=(3, 3),activation='relu',input_shape=input_shape))
model.add(Conv2D(64, (3, 3), activation='relu'))
model.add(MaxPooling2D(pool_size=(2, 2)))
model.add(Dropout(0.25))
model.add(Flatten())
model.add(Dense(256, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(num_classes, activation='softmax'))
model.compile(loss=keras.losses.categorical_crossentropy,optimizer=keras.optimizers.Adadelta(),metrics=['accuracy'])
Treinar o modelo
A função 'model.fit()' do Keras iniciará o treinamento do modelo. Usa os dados de treinamento, dados de validação, épocas e tamanho do lote.
Leva algum tempo para treinar o modelo. Após o treino, guardamos os pesos e a definição do modelo no ficheiro 'mnist.h5'.
hist = model.fit(x_train, y_train,batch_size=batch_size,epochs=epochs,verbose=1,validation_data=(x_test, y_test))
print("The model has successfully trained")
model.save('mnist.h5')
print("Saving the model as mnist.h5")

Avaliar o modelo
Temos 10.000 imagens em nosso conjunto de dados que serão usadas para avaliar o funcionamento do nosso modelo. Os dados de teste não foram envolvidos no processo de treinamento, portanto, são dados novos para o nosso modelo. O conjunto de dados MNIST é bem equilibrado, então podemos esperar alcançar cerca de 99% de precisão.
score = model.evaluate(x_test, y_test, verbose=0)
print('Test loss:', score[0])
print('Test accuracy:', score[1])
Criar GUI para prever dígitos
Agora para a GUI, criamos um novo arquivo onde construímos uma janela interativa para desenhar dígitos em uma tela. Com um botão, podemos reconhecer o dígito. A biblioteca Tkinter faz parte da biblioteca padrão do Python. Criamos uma função 'predict_digit()' que toma a imagem como entrada e, em seguida, usa o modelo treinado para prever o dígito.
Em seguida, criamos a classe 'App', que é responsável por construir a GUI para o nosso aplicativo. Criamos uma tela onde podemos desenhar capturando os eventos do mouse. Com um botão, acionamos a função 'predict_digit()' e exibimos os resultados.
from keras.models import load_model
from tkinter import *
import tkinter as tk
import win32gui
from PIL import ImageGrab, Image
import numpy as np
model = load_model('mnist.h5')
def predict_digit(img):
#resize image to 28x28 pixels
img = img.resize((28,28))
#convert rgb to grayscale
img = img.convert('L')
img = np.array(img)
#reshaping to support our model input and normalizing
img = img.reshape(1,28,28,1)
img = img/255.0
#predicting the class
res = model.predict([img])[0]
return np.argmax(res), max(res)
class App(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.x = self.y = 0
# Creating elements
self.canvas = tk.Canvas(self, width=300, height=300, bg = "white", cursor="cross")
self.label = tk.Label(self, text="Thinking..", font=("Helvetica", 48))
self.classify_btn = tk.Button(self, text = "Recognise", command = self.classify_handwriting)
self.button_clear = tk.Button(self, text = "Clear", command = self.clear_all)
# Grid structure
self.canvas.grid(row=0, column=0, pady=2, sticky=W, )
self.label.grid(row=0, column=1,pady=2, padx=2)
self.classify_btn.grid(row=1, column=1, pady=2, padx=2)
self.button_clear.grid(row=1, column=0, pady=2)
#self.canvas.bind("<Motion>", self.start_pos)
self.canvas.bind("<B1-Motion>", self.draw_lines)
def clear_all(self):
self.canvas.delete("all")
def classify_handwriting(self):
HWND = self.canvas.winfo_id() # get the handle of the canvas
rect = win32gui.GetWindowRect(HWND) # get the coordinate of the canvas
im = ImageGrab.grab(rect)
digit, acc = predict_digit(im)
self.label.configure(text= str(digit)+', '+ str(int(acc*100))+'%')
def draw_lines(self, event):
self.x = event.x
self.y = event.y
r=8
self.canvas.create_oval(self.x-r, self.y-r, self.x + r, self.y + r, fill='black')
app = App()
mainloop()

- Make a submission
