2

Написал для себя маленькую нейронку для распознавания цифр из базы MNIST (from scratch так сказать). С готовыми данными справляется нормально, но когда я хочу распознавать свои рукописные цифры, получаются ошибки - тут объснили почему. Хотел спросить, а на какие матрицы мне умножать картинку, чтобы получить сдвиг цифры или ее поворот?

вывод моей программы

  • Удалите метку [обработка-данных]. Она слишком общая и сейчас сжигается. – Глеб Oct 22 '23 at 08:10

1 Answers1

3

В общем, пока вопрос лежал, нашел ответы на него сам. Привожу код

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
from scipy import ndimage
from PIL import ImageEnhance, Image

data = pd.read_csv('....digit-recognizer\train.csv')

data = np.array(data) image = data[1][1:]

def add_some_noise(image):

image.shape = (28,28)

image = image / 1

temp_file = Image.fromarray(image).convert('L')
temp_size = np.random.randint(10,35)
temp_file = temp_file.resize((temp_size,temp_size))

image = np.array(temp_file.crop((temp_file.size[0] / 2 - 14, temp_file.size[1] / 2 - 14, temp_file.size[1] / 2 + 14, temp_file.size[1] / 2 + 14)))


temp_file = ndimage.rotate(image, random.randint(-20, 20), reshape=False, prefilter=False) / 1
temp_file = Image.fromarray(temp_file).convert("L")

enhancer = ImageEnhance.Sharpness(temp_file)
factor = np.random.random(1)[0] * 10
temp_file = enhancer.enhance(factor)
image = np.array(temp_file)

image = np.roll(image, random.randint(-4,4), axis = 1)
image = np.roll(image, random.randint(-2,2), axis = 0)

pixels = [250, 150,  100, 50 , 0]
noise = np.random.choice(pixels, 784,  p=[0.003, 0.005,  0.007,  0.015, 0.97])

noise.shape = (28,28)

image = image + (1 * image < 50) * noise

image.shape = (1,784)

return image[0]

image = image / 1

метод fromarray почему-то работает c float, но не int

    temp_file = Image.fromarray(image).convert('L')
    temp_size = np.random.randint(10,35)
    temp_file = temp_file.resize((temp_size,temp_size))
image = np.array(temp_file.crop((temp_file.size[0] / 2 - 14, temp_file.size[1] / 2 - 14, temp_file.size[1] / 2 + 14, temp_file.size[1] / 2 + 14)))

Изменяю рандомно размер изображения и потом делаю вырез 28x28

temp_file = scipy.ndimage.rotate(image, random.randint(-20, 20), reshape=False, prefilter=False) / 1 

Поворот изображения. Деление на 1, чтобы совпали типы данных. (возвращает картинку)

temp_file = Image.fromarray(temp_file).convert("L")

массив из картинки

factor = np.random.random(1)[0] * 10
temp_file = enhancer.enhance(factor)
image = np.array(temp_file)

изменяем резкость или размываем

image = np.roll(image, random.randint(-2,2), axis = 0)

сдвиг по осям

pixels = [250, 150,  100, 50 , 0]
noise = np.random.choice(pixels, 784,  p=[0.003, 0.005,  0.007,  0.015, 0.97])

noise.shape = (28,28)

image = image + (1 * image < 100) * noise

добавление шума

(1 * image < 100) * noise

именно в те места, где не изображена сама цифра

Результат

введите сюда описание изображения

Вообще, очень классно, что доступно там много инструментов на python)

  • 1
    Молодец, что разобрались. Да, обычно используют повороты, сдвиги, шум. В некоторых случаях ещё отражение (если кошки-собачки, например), но в случае цифр отражение не нужно, тут ориентация фиксированная. Так то ещё бывает используют размытие, сдвиг яркости, ну, много чего можно придумать. Всё это расширяет базу обучения. – CrazyElf Oct 23 '23 at 06:18
  • 1
    Да, замечание: код в вопросах и ответах должен быть со всеми импортами! Сейчас чтобы запустить ваш код нужно самому догадаться, какие библиотеки и как подключить. А это бывает нелегко. Добавьте все нужные импорты в код. Код должен быть самодостаточным для запуска. В случае, если всё нужное есть в вопросе и в ответе приводятся только изменения код, импорты можно не приводить. Но только в этом случае. – CrazyElf Oct 23 '23 at 06:20
  • @CrazyElf а могу ли я первоначальные и зашумленные данные использовать вместе, дабы увеличить выборку? Если да, то большой ли имеет смысл так делать? – Тима Oct 23 '23 at 09:43
  • 1
    А что за модели то? Для таких картинок, которые со свигами, нужно уже сети со слоями CNN строить, с пуллингом и т.д., т.е. с поиском определённых фрагментов на картинке и их сочетаний. Сети, которые угадывают цифры по наличию сигнала в конкретной ячейке сетки на зашумлённых данных естественно работать уже не будут. Кроме того, нужно смотреть глазами, как вы картинки зашумили. Может какие-то методы портят картинку настолько, что в ней уже невозможно признаки найти ) Но это можно увидеть только если глазами посмотреть. Такие преобразования лучше убрать. – CrazyElf Oct 23 '23 at 09:47
  • 1
    Да, конечно, весь смысл именно в том, что зашумлённые картинки дополняют данные для обучения, а не заменяют их. Хотя, смотря как именно зашумлять. Зависит от конкретики. Да, и ещё нужно помнить, что на MNIST невозможна метрика 100%, потому что там есть некоторое количество картинок, которым нельзя однозначно лейбл проставить, либо он там вообще неправильно проставлен. 100% можно получить только моделью, которая прямо вот запомнит лейблы этих неправильных картинок (что не есть хорошо). – CrazyElf Oct 23 '23 at 09:49
  • @CrazyElf самые простые с прямолинейным проходом, которые вручную можно реализовать. Ну что ж, если не получится с такими, буду дальше изучать тему и пробовать реализовывать, авось получится) Вдохновился видео - https://youtu.be/hfMk-kjRv4c , захотел также сделать. Спасибо за помощь – Тима Oct 23 '23 at 10:02
  • 1
    Для простых моделей шум губителен. Да даже просто сдвиг. Поэтому CNN и придумали для картинок ) – CrazyElf Oct 23 '23 at 10:05
  • @CrazyElf вроде получилось) обучил до 82% и теперь не угадывает мои рукописи только иногда. Жаль здесь нельзя картинками поделиться – Тима Oct 23 '23 at 10:43
  • В ответ можно добавлять картинки ) – CrazyElf Oct 23 '23 at 10:51