Font size
  • A-
  • A
  • A+
Site color
  • R
  • A
  • A
  • A
Skip to main content
AI4VET AI4VET
  • Home
  • Calendar
  • More
You are currently using guest access
Log in
AI4VET
Home Calendar
Expand all Collapse all
  1. AI/ML Fundamentals
  2. AIML-PT
  3. 2. Machine Learning (PT)
  4. Exercício 2.A: Conjuntos de dados populares MNIST

Exercício 2.A: Conjuntos de dados populares MNIST

colab

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()

Completion requirements:
  • Make a submission
Previous activity 2.9 Conjuntos de formação, validação e ensaio
Next activity Exercício 2.B: Conjuntos de dados populares - ImageNet
You are currently using guest access (Log in)
Data retention summary
Get the mobile app
Get the mobile app
Play Store App Store
Powered by Moodle

This theme was proudly developed by

Conecti.me