Keras - обучение сети распознаванию рукописных цифр | #8 нейросети на Python

Поділитися
Вставка
  • Опубліковано 30 чер 2020
  • Создаем полносвязную сеть в Keras для распознавания рукописных цифр из базы MNIST. Рассматриваются вопросы подготовки тестовой, обучающей и проверочной выборок. Критерий качества (loss function) - категориальная кросс-энтропия (categorical_crossentropy). Добавление метрики 'accuracy' - доля правильно распознанных образцов. Использование параметра validation_split - для выделения из обучающей выборки набора наблюдений для валидации. Оценка качества работы обученной сети на тестовом множестве.
    Телеграм-канал: t.me/machine_learning_selfedu
    Инфо-сайт: proproprogs.ru
    Исходник (lesson 8. keras_digits.py): github.com/selfedu-rus/neural...
    Документация по Keras: ru-keras.com

КОМЕНТАРІ • 170

  • @user-xj1vc6oo7k
    @user-xj1vc6oo7k 3 роки тому +123

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

    • @mmm43kir
      @mmm43kir 3 роки тому +7

      да. Для меня это лучший сериал 2020 года.

  • @user-of4dn2wz1k
    @user-of4dn2wz1k 3 роки тому +48

    Многие платные курсы в разы хуже чем этот, спасибо автору++

  • @komazmt
    @komazmt 2 роки тому +28

    Здравствуйте, во-первых, конечно хочу сказать огромное спасибо за ценные знания и приятную подачу. Я новичок, но у меня всё получилось.
    Вообще я хотел распознавать цифры при помощи веб-камеры в реальном времени. Обученную модель сохранил в файл, далее загрузил в другом проекте где при помощи openCV получал видео с вебки, обрабатывал и преобразовывал в вид (28, 28, 1). Но нейросеть упорно видела везде пять. Изрисовал много бумаги, отдалял-приближал, перекрутил кучу настроек в cv2, сдался и лёг спать. Но потом встал, включил компьютер, инвертнул цвет с чёрного на белый и всё заработало. Сейчас пишу коммент и думаю, что всё логично, что «пустоты» фона это в массивах нули, соответственно чёрный цвет, а сами контуры цифр белые с максимальными значениями. Но догадаться было просто удачей😆

  • @-USER_NAME
    @-USER_NAME Рік тому +6

    Почти три года ( день в день) изучаю программирование, посидел на разных языках. Но сильнее ваших уроков не встречал . И вот почему. Есть уроки которые объясняют очень простые вещи подробно , таких процентов 70 . Есть уроки которые объясняют ребята с большим опытом ,но они ценят свое время и чаще воспринимают это как способ доп заработка поэтому кратенько сухо . Ещё бывают, толком сам не понял начинает объяснять вижу подчёркнута добрая часть кода , оп затемнение и проект компилируется, у них ,а я плююсь пытаюсь найти решение проблем с версией корявого кода и тд .
    И получается в первом случае слишком низкий уровень во втором слишком высокий к которому ещё нужно хорошо подготовиться .
    Но вот чтоб так подробно, такие сложные вещи, это что то не с этой планеты . Спасибо вам большое, счастья,здоровья, долгих лет . 😁

  • @paulkarkarin466
    @paulkarkarin466 Рік тому +8

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

  • @andrewmaishev2834
    @andrewmaishev2834 3 роки тому +14

    Спасибо огромное! Материал подаёте очень подробно и ясно - и это ваш козырь!
    Изучаю НС пока только по вашему каналу. Пожалуйста, не останавливайтесь :)

  • @user-zt4wx1ks6z
    @user-zt4wx1ks6z Рік тому +3

    Сергей, Вы большой молодец. Спасибо за курсы!!! Я очень рад, что нашел Ваш канал=)

  • @NizZerbergmaN
    @NizZerbergmaN 2 роки тому +3

    Настолько шикарный контент, что даже такой куркуль как я подписываюсь как спонсор канала.

  • @maximbravtsev3648
    @maximbravtsev3648 11 місяців тому +2

    Огромное спасибо за объяснение базовых основ!

  • @sledleo
    @sledleo Рік тому +1

    Шеф, супер тема! И подача просто огонь, даже тупым как я доходит слёту!
    Спасибо за труды и просвещение нас недалеких!!! Респект!!!!

  • @Vivavatnik
    @Vivavatnik 3 роки тому +1

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

  • @eswcpoker6562
    @eswcpoker6562 3 роки тому +5

    отличный канал . Хотелось бы в дальнейшем видео про обучение с подкреплением увидеть на python

  • @viktorpavlov4499
    @viktorpavlov4499 3 роки тому +1

    Спасибо большое за урок!

  • @user-qe5gw9yh8g
    @user-qe5gw9yh8g 3 роки тому +1

    превосходный материал и его подача

  • @TyomaStrum
    @TyomaStrum 3 роки тому +3

    Очень хорошее пояснение, поймет любой, поверьте, даже я в свои 15 лет

  • @user-xv4bo4te5w
    @user-xv4bo4te5w 4 місяці тому +1

    Привет, Автор. Не знаю, найдешь ли ты мой комментарий в столь большом количестве уведомлений. Да и не помню, писал ли я тебе что-то подобное...Прости, память на мелочи у меня ужасна😅
    Но хочу сказать огромное спасибо за данный плейлист. А также прошу никогда не удалять его. Настолько понятное и бесплатное объяснение я больше нигде не найду. Спасибо за твои труды. Не смотря на малый доход, ты все равно создал его. Еще раз спасибо❤

  • @user-uf3qh3fr7d
    @user-uf3qh3fr7d Рік тому +1

    Спасибо четко объясняешь)

  • @user-gp5hg2xu2s
    @user-gp5hg2xu2s 2 роки тому +1

    супер уроки!

  • @RaceOTT
    @RaceOTT Рік тому +1

    Повторив НС из видео, в блоке "model.compile" выходила ошибка "ValueError: Error when checking input: expected flatten_input to have 4 dimensions, but got array with shape (60000, 28, 28)"
    Почитав комменты, проставил "Flatten(input_shape=(28, 28))" - без единички в конце и всё заработало.
    А так, большое спасибо автору за очень классные видео!

  • @user-gx1zf3nf5y
    @user-gx1zf3nf5y Рік тому +1

    Спасибо большое!

  • @user-ni9dc6fs5y
    @user-ni9dc6fs5y 9 місяців тому +1

    Невероятно крутой канал! Всё очень понятно объясняет автор. Возник вопрос: а как убирать ошибки, которые рассмотрели в конце? Надеюсь, следующий урок про это!

  • @RomanUnreal
    @RomanUnreal 5 місяців тому +5

    Если у кого не получается такая же точность распознавания, проверьте, может у вас закончились вычислительные единицы гугл колаб, он теперь ПЛАТНЫЙ.

  • @hinomuratomisaburo4901
    @hinomuratomisaburo4901 3 роки тому +4

    Блин круто 😃👈👈

  • @irvinexxi
    @irvinexxi 2 роки тому +2

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

  • @annaponomarova3472
    @annaponomarova3472 3 роки тому +1

    Amazing!!!!!!!!

  • @user-tb4pe2tt8e
    @user-tb4pe2tt8e 3 роки тому +2

    Спасибо очень интересно!

  • @user-ju1gt8zr5p
    @user-ju1gt8zr5p 8 місяців тому +1

    Я люблю тебя, лучшее обяснение. Где ты работаеш?

  • @antonevdokimov8218
    @antonevdokimov8218 3 роки тому +1

    🔥🔥🔥🔥🔥🔥🔥🔥🔥

  • @sergeygetto7480
    @sergeygetto7480 2 роки тому +1

    Пробовал с различным числом слоёв и нейронов. В принципе 128 подходят отлично, единственное, что дало небольшой + к верным ответам нейронной сети - это количество эпох. На самом деле много делать не надо, так как начинает скакать шанс на дополнительной выборке, а так самый оптимальный найденный вариант около 7 эпох.

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

      Да, верно, это очень простая задачка, вроде "Hello World!" в программировании. Ради интереса попробуйте распознать базу изображений CIFAR-10, там намного сложнее )

    • @sergeygetto7480
      @sergeygetto7480 2 роки тому +1

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

  • @user-he5bd6zs6n
    @user-he5bd6zs6n 9 місяців тому +1

    Спасибо. Хороший материал. Не совсем понятно,как интерпретировать выходные значения вероятности (тайм код 19.33) Это что за цифры проценты или ещё что-то? По идее сумма вероятностей всех классов не может быть больше 1. А здесь 4.78..., 5,05...., 9,99.... итд. Эти цифры как нибудь соотносятся с метрикой точности?

  • @vladimirtyushkin8580
    @vladimirtyushkin8580 2 роки тому +1

    Спасибо за лекци, очень интересно но есть один вопрос, почему после обучения модели, для предикшена нужен трехмерный тензор,а не Flatten из пикселей изображения?

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

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

  • @user-lu8vw1ud1f
    @user-lu8vw1ud1f 3 роки тому

    Спасибо за видео. Подскажите можно ли картинку закинуть с помощью js в питон, который обработает и результат передаст назад в js?

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      можно, посмотрите в сторону Ajax

  • @freshmen5491
    @freshmen5491 3 роки тому +2

    Знаю что автор в отпуске, но как можно с ним связаться. Не сейчас, а вообще🙂

  • @user-cc1yw4pv3e
    @user-cc1yw4pv3e 2 роки тому +3

    эмм, неужели ни у кого не было проблем с импортом tensorflow? "Another metric with the same name already exists."

  • @ivanuppercube931
    @ivanuppercube931 2 роки тому

    а можно каким то образом подключить похожую нейросеть в игровой движок?

  • @user-ir2hh9lr1q
    @user-ir2hh9lr1q 3 роки тому

    Спасибо за видео. Скажите если у меня картинка на которой изображено 7+8, 5+3, 4+1 можно ли вашим способом оцифровать всю картинку или надо по одной цифре задавать?

    • @selfedu_rus
      @selfedu_rus  3 роки тому

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

    • @user-ir2hh9lr1q
      @user-ir2hh9lr1q 3 роки тому

      @@selfedu_rus а этот метод где то уже показан? Я сколько смотрю у всех по одной цифре

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      @@user-ir2hh9lr1q Это уже вы сами должны реализовать, используя знания по цифровой обработке изображений.

  • @deadmorose4741
    @deadmorose4741 6 місяців тому

    А есть ссылка на итоговый коллаб?

  • @dimapugach5586
    @dimapugach5586 2 роки тому +1

    Спасибо за прекрасный курс, прошел весь и появился вопрос: как преобразовать изображение в формате .png, чтобы можно было его пропустить через эту сеть?

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      Такой вопрос в телеграм-канал лучше

    • @dimapugach5586
      @dimapugach5586 2 роки тому

      @@selfedu_rus можно ссылку в таком случае?

  • @user-uk4ww6ln7q
    @user-uk4ww6ln7q Рік тому

    А validation_split каждый раз одни и теже отки берет? Или каждый раз разные? Есть ли какой-нить seed у этого параметра?

    • @selfedu_rus
      @selfedu_rus  Рік тому

      насколько помню, разбивает случайным образом

  • @user-of3pm6oi1m
    @user-of3pm6oi1m 2 роки тому +1

    В данный момент mnist не скачивается с помощью данной команды:
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    Как я понял, там какая-то проблема в самом keras, скоро должны пофиксить.
    А пока проблему удалось решить путем скачивания набора данных mnist напрямую и его импорта таким образом:
    path = './mnist.npz'
    f = np.load(path)
    x_train, y_train = f['x_train'], f['y_train']
    x_test, y_test = f['x_test'], f['y_test']
    f.close()

  • @mar_kha
    @mar_kha 2 роки тому +3

    Собираюсь посмотреть видео, но прежде, хочу спросить:
    🖥️ Есть ли приложение для распознавания русского рукописного текста и перевода в текстовый формат?
    Те, что я находила:
    - функционал ограничен (распознование только английского текста)
    - некорректны (вместо текста какие-то квакозябры)
    ___
    Устроилась лаборантом на кафедру информатики.
    Дали задание: набрать рукописные конспекты в Word (составлял профессор, которому сделали операцию на глазах, и сам он не в состоянии справиться с работой).
    В одном учебном пособии (а их минимум 5 штук) около сотни страниц рукописного текста!
    Я конечно могу набрать - не проблема, да вот хотелось бы оптимизировать процесс (всё-таки на программиста учусь не ради "корочки" , а чтоб быть полезной обществу)
    ___
    И вот я здесь, чтоб самостоятельно (почти - ещё у преподавателей буду консультироваться) разобраться в теме нейросетей, и разработать приложение (цель амбициозная, но мне необходимо поспешить - неизвестно, сколько профессору жить осталось).
    Надеюсь данное видео поможет разобраться со сложившейся ситуацией

    • @selfedu_rus
      @selfedu_rus  2 роки тому +2

      FineReader лучшая прога по распознаванию

    • @mar_kha
      @mar_kha 2 роки тому +1

      @@selfedu_rus Спасибо)
      Решила набрать текст голосом

  • @user-kg7pn2sn6t
    @user-kg7pn2sn6t 10 місяців тому +1

    Большое спасибо, Сергей, классно объясняете. Остался вопрос, на который чат gtp так и не ответил правильно: почему кросс энтропия? Ведь значения ноль при умножении на логарифм пресказания убирает из ошибки, а это ошибка и её нужно уменьшать. Чат ответил, что не участвует в предсказании, поэтому не нужен.

    • @selfedu_rus
      @selfedu_rus  10 місяців тому

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

    • @user-kg7pn2sn6t
      @user-kg7pn2sn6t 10 місяців тому

      Спасибо. Такой ход мыслей у меня был как догадка.

  • @user-jb1mv6kq4l
    @user-jb1mv6kq4l 2 роки тому +1

    А можно после обучения нс закинуть туда изображение с соответствующим разрешением или написать код в котором можно будет самим нарисовать цифру? И как это реализовать?

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      да и на следующем занятии я это показываю

  • @user-kg7pn2sn6t
    @user-kg7pn2sn6t 9 місяців тому +1

    Ещё раз большое спасибо за классные лекции. По этой лекции остался вопрос по синкасису питона. Нигде не нашёл правила, по которому если координатами списка является список с булевыми компонентами, где у вас maska, то в операторе присваивания выделяются только компоненты true. Это действительно есть такой синтаксис? Он только у python?

    • @selfedu_rus
      @selfedu_rus  9 місяців тому

      Спасибо! Про True - это порядок работы библиотеки NumPy, которая совместно применяется с Keras и Tensorflow

    • @user-kg7pn2sn6t
      @user-kg7pn2sn6t 9 місяців тому +1

      Большое спасибо. Сидим с сыном и разбираемся. Очень интересно.

  • @sergeyperevozchik3733
    @sergeyperevozchik3733 2 роки тому +2

    -Индекс получается седьмой.
    Может все таки восьмой?

  • @alexanderdushenin7035
    @alexanderdushenin7035 3 роки тому

    Добрый вечер. Подскажите, пожалуйста:
    1) Почему у меня при распознавании тестовой выборки (model.evaluate(x_test,y_test_cat)) значение метрики составляет 8% (а не 97%, как у Вас)?
    2) Для чего мы делим на 255? То, что стандартизация - это я понимаю. Непонятно, что мы в итоге подаём на вход НС

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      На первый вопрос сложно ответить вот так вот. Если метрика такая же как и в видео, и выборка та же самая, то значение должно быть близко к 97% Если не так - где то ошибка.
      По второму вопросу. Деление на 255 - это стандартизация входных данных, чтобы они менялись в диапазоне от 0 до 1. Это делается, чтобы диапазон входных значений при обучении и при эксплуатации НС был одним и тем же - это важно. Ну а подаем на вход НС стандартизированную обучающую выборку (изображения цифр).

    • @alexanderdushenin7035
      @alexanderdushenin7035 3 роки тому +1

      Спасибо. По поводу второго вопроса - я имел в виду принцип подачи изображения на НС. Но, посмотрев следующее видео, я все понял)

  • @vladislavkondak3055
    @vladislavkondak3055 3 роки тому +2

    Добрый день. Можно ли этой же нейронной сетью распознать произвольную фотографию? Если да, то как это сделать?

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

      Это будет не лучшее решение. Для обработки изображений рекомендуется использовать сверточные сети (об этом дальше в курсе). Мало того, существуют стандартные структуры сверточных НС VGG-16 и VGG-19, поставляемые с Keras, которые хорошо решают эту задачу. (Также см. в этом курсе).

    • @vladislavkondak3055
      @vladislavkondak3055 3 роки тому +1

      @@selfedu_rus Спасибо!

  • @user-yi6kc5ys2n
    @user-yi6kc5ys2n 3 роки тому

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

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

      Тестовая выборка тоже имеет вид трехмерного тензора. Когда мы их загружаем mnist.load_data(), то на выходе уже имеем нужный формат.

    • @user-yi6kc5ys2n
      @user-yi6kc5ys2n 3 роки тому

      @@selfedu_rus тогда не соображу пока, почему отдельный элемент этой же выборки не в нужном формате?

    • @user-yi6kc5ys2n
      @user-yi6kc5ys2n 3 роки тому +1

      Наверное, понял. Тестовая выборка в данном случае представлена, как 10000 слоев двумерных массивов и в целом это трёхмерный тензор. А если из неё вырезать одно изображение, то это будет двумерный массив. Правильно?

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

      @@user-yi6kc5ys2n да, верно!

  • @tsoer2976
    @tsoer2976 3 роки тому

    Добрый день хочу уточнить. Нет у меня, четкого понимая, время на видео 13:29 компиляция модели. аргумент optimezator='adam' необходим, чтобы находить лямбда(шаг), аргумент loss='categorial_crossentropy' нужен для формирования функции которая вычисляет ошибку. Последний для формирования отчета хорошо ли обучена наша модель. Если не верно прошу Вас объяснить, где и почему. Спасибо за видео

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      Не совсем. Оптимизиатор - это способ улучшить алгоритм градиентного спуска, при этом шаг сходимости определен по умолчанию как 0,001 (вроде бы, см. документацию по Keras). Если шаг нужно поменять, то следует создать свой оптимизатор адам с помощью класса Adam(lr=0,01) - здесь lr - шаг сходимости. Далее, про функцию потерь верно, а метрика - это процент ошибок. Мы определяем дополнительно свои метрики, т.к. именно они нам нужны для анализа работы сети. Но градиентный спуск не может их минимизировать напрямую, т.к. там отсутствуют частные производные. Поэтому выбираем функцию потерь, которая, как нам кажется, будет минимизировать нужную нам метрику, в данном случае accuracy. Примерно так.

    • @tsoer2976
      @tsoer2976 3 роки тому

      @@selfedu_rus Тогда совсем не понял. Как происходит обратное распространение ошибки? Если смотреть ваше уроки. То оптимизатор нам не нужен. Для получения коэффициентов(весов) достаточно рассчитать фикцию потерь и множить ее на производную функции выхода слоя. В какой момент нам становится необходим оптимизатор? То есть я вижу логику, так взяли случайные веса прошли вперед по сети -> получили выход -> сравнили с результатом и получили ошибку с помощью фикции loss-> откорректировали веса обратным распространением. Конец первой эпохи и так идем по всему дата сету. После сделали оценку качества модели. Скажите где я пропускаю градиентный спуск совсем запутался

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

      @@tsoer2976 В объяснении алгоритма back propagation его и нет - там только стандартный градиентный спуск. Оптимизатор модифицирует градиентный спуск для более быстрого нахождения точки минимума. Некоторую инофрмацию об этом можно посмотреть здесь ua-cam.com/video/xDpe9KlYj9Q/v-deo.html

  • @fedor_vaskin
    @fedor_vaskin Рік тому +1

    Здравствуйте! Сергей, подскажите, пожалуйста, используется ли здесь у Вас норма обучения? Где её нужно указывать? Не очень понял этот момент.

    • @selfedu_rus
      @selfedu_rus  Рік тому

      Что такое "норма обучения"? Впервые слышу.

    • @fedor_vaskin
      @fedor_vaskin Рік тому

      @@selfedu_rus обычно отмечают как "мю".

    • @selfedu_rus
      @selfedu_rus  Рік тому

      @@fedor_vaskin шаг обучения? он в Keras в градиентном спуске автоматически реализован с поправкой на используемый оптимизатор

    • @fedor_vaskin
      @fedor_vaskin Рік тому

      @@selfedu_rus спасибо! То есть его в ручную самому никак не поменять, чтобы "поиграть" с разными шагами, посмотреть, как шаг влияет на обучаемость сети?

    • @selfedu_rus
      @selfedu_rus  Рік тому

      в настройках метода fit можно для выбранного оптимизатора менять начальное значение шага (только тогда оптимизатор должен быть создан как объект, например, Adam(lr=0.0001), здесь lr - начальный шаг... точно название параметра не помню, посмотрите в документации)

  • @MurzNN
    @MurzNN 8 місяців тому +1

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

    • @selfedu_rus
      @selfedu_rus  8 місяців тому

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

  • @sergeyv1534
    @sergeyv1534 3 роки тому

    22:51
    Можете пояснить этот момент с маской более подробно? Почему был выбран вариант записи «mask = pred == y_test» в противовес «mask = pred != y_test»? Инверсия маски при помощи тильды «~» - это синтаксис самого Keras (в самом Python такого не встречал)? Попробовал оба варианта (во втором случае с «!=» также убиралась тильда «~») - существенных отличий в результате не заметил.

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

      так работают списки пакета numpy, мы им можем передавать (в качестве индексов) булевый массив и он вернет только те элементы, где стоит True

    • @sergeyv1534
      @sergeyv1534 3 роки тому

      @@selfedu_rus Если правильно понимаю, особых различий в формах записи нет: «mask = pred == y_test» далее индекс с «~» и «mask = pred != y_test» указание индекса без «~».

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

      @@sergeyv1534 да, все верно

  • @md5alx
    @md5alx 3 роки тому +1

    Спасибо огромное за Ваш труд!!!
    Вопрос можно ?? Как распознавать десятичные числа и выше. Как пример число 123456.
    Спасибо.

    • @selfedu_rus
      @selfedu_rus  3 роки тому +1

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

    • @user-ni9dc6fs5y
      @user-ni9dc6fs5y 9 місяців тому

      ​@@selfedu_rusздравствуйте! А как научить разделять изображение на отдельные числа?

    • @selfedu_rus
      @selfedu_rus  9 місяців тому

      @@user-ni9dc6fs5y Это уже нужно применять различные техники из обработки изображений (целое научное направление). Многое зависит от решаемой задачи.

  • @user-cc7fi2ul3z
    @user-cc7fi2ul3z 3 роки тому +1

    Здравствуйте, а как импортирвать датасет, который у меня на компьютере лежит?

    • @selfedu_rus
      @selfedu_rus  3 роки тому +2

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

  • @user-km9re6om7j
    @user-km9re6om7j 3 роки тому +1

    Какие - то космические 99% получились у вас))

  • @utka111
    @utka111 Рік тому +1

    Здравствуйте, Сергей! Как можно с вами связаться? Можете дать e-mail?

  • @user-nk2ms3rs4s
    @user-nk2ms3rs4s 6 місяців тому +1

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

    • @selfedu_rus
      @selfedu_rus  6 місяців тому

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

    • @YbisZX
      @YbisZX Місяць тому

      @@selfedu_rus Вы используете функцию to_categorical(), но она только номера в one-hot векторы преобразовывает. А если нужно буквы распознавать? Я сам написал факторизацию под символы, но неужели в keras нет готового решения для перевода любых обозначений классов в категории?
      # Категоризация любых обозначений классов в one-hot векторы
      y_set = np.unique(y_train) # желательно объединить y_train с y_test (не потерять редкие классы)
      y_train_cat = np.array([y_set==y for y in y_train]).astype('float64')
      y_test_cat = np.array([y_set==y for y in y_test]).astype('float64')
      # Восстановление обозначений классов по векторам softmax:
      y_pred = y_set[np.argmax(y_pred_cat, axis=1)]

  • @1980PaulL
    @1980PaulL 3 роки тому +2

    У меня ошибку выдает Error when checking input: expected flatten_11_input to have 4 dimensions, but got array with shape (60000, 28, 28) после попытки обучить модель (model.fit(x_train, y_train_cat, batch_size=32, epochs=5, validation_split=0.2))

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      у вас входной тензор 4-х мерный, а должен быть 3-х мерный

    • @1980PaulL
      @1980PaulL 3 роки тому +3

      @@selfedu_rus, я заменил Flatten(input_shape=(28,28,1) на Flatten(input_shape=(28,28), все заработало. И цифры правильно распознает

  • @wian39
    @wian39 2 роки тому +1

    Добрый день. Пробую распознать свои рукописные цифры данной нейросетью. Создаю список с названиями файлов и загружаю изображения (уже 28х28), используя Pillow (image = Image.open(file).convert('L')), затем преобразую в массив numpy и стандартизирую. Добавляю получившиеся массивы в список и создаю массив numpy на основе этого списка. Далее подаю нейросети, но она видит везде тройки. В чем может быть ошибка? Помимо Pillow пробовал использовать OpenCV, но происходило всё то же самое.

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      Формат изображения должен быть 28x28 grayscale (градации серого) один цветовой канал. Возможно здесь ошибка.

    • @wian39
      @wian39 2 роки тому

      @@selfedu_rus , после преобразовании картинки в массив shape показывает (28, 28), а конечный массив, который подаётся на нейросеть (10, 28, 28). Попробовал сделать тоже самое, только на OpenCV видит те же тройки. Код:
      filenames = [...]
      data = [ ]
      for file in filenames:
      image = cv2.imread(file, cv2.IMREAD_GRAYSCALE)
      img = image / 255
      data.append(img)
      ara = np.array(data)
      pred = model.predict(ara)
      res = np.argmax(pred, axis=1)
      print(res)
      upd: т.е. я загружаю картинки уже приведённые к размеру 28х28. Или стоит загружать обычные, приводя внутри программы их размер к нужному?

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      @@wian39 нужно добавить 1-ю ось (например, с помощью метода expand_dims() массива array numpy)

    • @wian39
      @wian39 2 роки тому

      @@selfedu_rus Добавляя эту ось к изображению, на выходе получаю ошибку: ValueError: Input 0 of layer "sequential" is incompatible with the layer: expected shape=(None, 28, 28, 1), found shape=(None, 1, 28, 28). Конечный массив в этом случае получается (10, 1, 28, 28). Для сравнения взял изображение из тестовой выборки сделал для него всё тоже самое, на выходе получил верный результат. Попробовал сделать это для 1-го своего изображения, predict сработал, но распозналась тройка вместо нужной семёрки
      upd: Если сделать reshape массива, который подаётся на predict, к размеру (10, 28, 28,1), то сам predict работает, однако выдаёт те же тройки. Возможно проблема в том, что мои изображения умещаются в 10х10 пикселей, хотя в mnist изображения выглядят раза в 2 больше.
      upd: Подогнал размер цифры примерно под размер цифры в mnist, всё одно: видит тройку

    • @selfedu_rus
      @selfedu_rus  2 роки тому

      @@wian39 посмотрите внимательно формат осей в mnist и сделайте по аналогии для одного изображения

  • @nik0294
    @nik0294 3 роки тому +2

    Привет. А как обучить нейросеть своими данными вместо mnist

    • @selfedu_rus
      @selfedu_rus  3 роки тому +2

      Очень просто, составляете свой набор данных (изображений, например) в виде многомерного массива NumPy и подаете на вход сети.

    • @nik0294
      @nik0294 3 роки тому +2

      @@selfedu_rus Ура у меня это получилось. СПАСИБО!!!

  • @user-qb5bo3jv3e
    @user-qb5bo3jv3e 2 роки тому

    Интересно, для Flatten input_shape выглядит так: (28,28,1), однако ближе к концу видео вы подаете на вход сети x, который равен x = np.expand_dims(x_test[n], axis=0). Но если посмотреть print("x.shape", x.shape), то окажется, что его форма имеет вид не (28,28,1) как это ожидает Flatten, а (1,28,28) и несмотря на это все работает. Как это следует понимать?)

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

      в Keras первая размерность - это всегда batch_size, то есть, размер мини-батча. Явно не прописывается, но автоматически добавляется.

    • @user-qb5bo3jv3e
      @user-qb5bo3jv3e 2 роки тому

      @@selfedu_rus Спасибо, просто не совсем понятно, как размерность входных данных согласуется с размерностью, которая задана для слоя Flatten. Размерность x это (1,28,28) тут все понятно. У нас батч, состоящий из одной картинки размера 28х28. На вход сети мы подаем картинки. То есть данные, размера 28х28. Согласно этой логике, input_shape на Flatten слое должен быть (28,28) а не (28,28,1) т.к это уже получается трехмерные данные, а мы на вход ведь подаем двумерные данные, вот что к сожалению непонятно...

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

      @@user-qb5bo3jv3e Последнее число - это количество каналов: 1 - градация серого (как правило); 3 - RGB (или какие-либо еще), поэтому, прописывая 28,28,1 мы тем самым оговариваем картинку с одним цветовым каналом.

    • @user-qb5bo3jv3e
      @user-qb5bo3jv3e 2 роки тому

      @@selfedu_rus Интересно, спасибо. Однако сеть ведь не знает что мы работаем с изображениями, разве в таком случае мы можем рассуждать в терминах изображений? (т.е упомянать градации серого и т.д). Я попробовал указать input_shape как (28,28) вместо (28,28,1) для Flatten, и все работает точно так же. Получается что последнюю единичку можно не писать?

    • @selfedu_rus
      @selfedu_rus  2 роки тому +2

      @@user-qb5bo3jv3e Сети все равно что поступает на вход, она лишь строит модель зависимости входов от выходов не более того. Насчет единички, возможно, ее можно и не указывать, но для цветного точно нужно.

  • @user-zf1ck5ul4s
    @user-zf1ck5ul4s 2 роки тому +2

    Здравствуйте! Спасибо за ваш прекрасный канал. Решил поэкспериментировать с вашим кодом где я преобразую 784 просто в строку без этих вот команд. Результат вроде бы должен быть одним и тем же. Но при обучении очень высокая ошибка, а у вас она порядка тысячной.. у меня больше 2-х. Почему так? Вы может и не ответите мне, но я все же рискну и спрошу у вас)))
    import os
    os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'
    import numpy as np
    import matplotlib.pyplot as plt
    from tensorflow.keras.datasets import mnist # библиотека базы выборок Mnist
    from tensorflow import keras
    from tensorflow.keras.layers import Dense, Flatten
    (x_train, y_train), (x_test, y_test) = mnist.load_data()
    # стандартизация входных данных
    x_train = x_train / 255
    x_train_my = x_train.flatten()
    x_test = x_test / 255
    x_test_my = x_test.flatten()
    y_train_cat = keras.utils.to_categorical(y_train, 10)
    y_test_cat = keras.utils.to_categorical(y_test, 10)
    plt.imshow(x_train[2], cmap=plt.cm.binary)
    plt.show()
    x_train_my_2 = []
    x_test_my_2 = []
    for i in range(0, int(len(x_train_my)/784)):
    x_train_my_2.append(x_train_my[i:784 + i])
    for ii in range(0, int(len(x_test_my)/784)):
    x_test_my_2.append(x_test_my[ii:784 + ii])
    j = 59999
    print(len(x_train_my_2[j]))
    print(y_train_cat[j])
    model = keras.Sequential()
    model.add(Dense(128, input_shape=(784,), activation='relu'))
    model.add(Dense(10, activation='softmax'))
    print(model.summary())
    model.compile(optimizer=keras.optimizers.Adam(0.001),
    loss='categorical_crossentropy',
    metrics=['accuracy'])
    model.fit(np.array(x_train_my_2), y_train_cat, batch_size=32, epochs=5, validation_split=0.2)
    model.evaluate(np.array(x_test_my_2), y_test_cat)
    А вот что выдает при обучении:
    Epoch 1/5
    1500/1500 [==============================] - 4s 3ms/step - loss: 2.3098 - accuracy: 0.1074 - val_loss: 2.3103 - val_accuracy: 0.1040
    Epoch 2/5
    1500/1500 [==============================] - 3s 2ms/step - loss: 2.3006 - accuracy: 0.1151 - val_loss: 2.3081 - val_accuracy: 0.1073
    Epoch 3/5
    1500/1500 [==============================] - 4s 2ms/step - loss: 2.2931 - accuracy: 0.1226 - val_loss: 2.3148 - val_accuracy: 0.1024
    Epoch 4/5
    1500/1500 [==============================] - 4s 2ms/step - loss: 2.2795 - accuracy: 0.1344 - val_loss: 2.3242 - val_accuracy: 0.1042
    Epoch 5/5
    1500/1500 [==============================] - 4s 2ms/step - loss: 2.2580 - accuracy: 0.1529 - val_loss: 2.3411 - val_accuracy: 0.1020
    очевидно что ничего не распознается правильно

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

      Проверьте в строчке x_train_my = x_train.flatten() возможно здесь структура тензора нарушается, он должен быть (batch_size, count_digits), а вы все в один вектор развертываете. И, насколько я помню, на вход можно подавать изображение, а затем, применять слой Flatten - это разные вещи (с вашей реализацией).

    • @user-zf1ck5ul4s
      @user-zf1ck5ul4s 2 роки тому +1

      @@selfedu_rus спасибо вам большое что ответили) У меня как раз и была цель для лучшего понимания развернуть все это в один вектор. Чтобы потом получив весовые коэффициенты организовать просто путем перемножения матриц проверит нейросеть что она выдает те же значения. Потому что например в матлабе пакет neiral network toolbox вводит своих пользователей в заблуждение и получив весовые коэффициенты оттуда и применяя функции активации получается абсолютно другой результат. А следовательно обученную нейронную сеть у них нельзя использовать в других программах. Вот поэтому я решил проверить на это же Keras) буду разбираться. Спасибо ещё раз вам огромное за столь быстрый ответ)

  • @nikolaydd6219
    @nikolaydd6219 2 роки тому +2

    4:40 Что значит: нейрон bias это смещение? Кто и куда смещается? Смотрел другие модели нейронал, там небыло такого нейрона

    • @selfedu_rus
      @selfedu_rus  2 роки тому +2

      см. 2-е занятие (по XOR) там я это подробно объясняю

    • @nikolaydd6219
      @nikolaydd6219 2 роки тому +1

      @@selfedu_rus Спасибо. Я смотрел но не понял)

  • @Dmitrii82
    @Dmitrii82 3 роки тому

    а где найти описания этих команд? flatten dense и тд.

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      в официальной документации по Keras: keras.io/guides/

  • @rpuropu
    @rpuropu 3 роки тому

    а где размер y_train_cat задаётся? не понятен этот момент. через два урока вы очень детально поясните как можно вручную рандомно сделать валидационную выборку.. но я вот хотел поменять число батчей.. для этого хочу высчитать размерность... всего там 70 000 ... 10 000 тестовых это в самой библиотеке прпоисано что ли? а я вот хочу что бы у меня тестовая выборка из 10 000 каждый раз сама рандомилась от всех 70 тысяч.. есть методы?
    или в load_data() что-то там вшито... и там можно не писать mnist... а как тогда сделать заготовку... куда можно будет приписать load_data()

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      При загрузке данных вы получаете весь объем данных, которые условно разбиты на обучающую и тестовую выборки. Вы можете взять обучающую из 60 000 образцов и уменьшить ее до любого другого числа и то же самое с тестовой. Также можете перемешать обучаюущую и тестовую выборки и самостоятельно решить сколько взять для обучения и сколько для теста. А как конкретно сделать - средствами NumPy + функции для перемешивания наблюдений о которых я говорил на занятиях.

    • @rpuropu
      @rpuropu 3 роки тому +1

      ​@@selfedu_rus сначала понял, потом не понял)).. извините и все равно спасибо) пойду чужие коды искать как у кого реализовано.. сейчас нашел вариант с раскладыванием по разным папкам.. детали ещё не ясны

  • @user-gx1zf3nf5y
    @user-gx1zf3nf5y Рік тому

    А какой алгоритм здесь используется? Сеть хебба, розенблатта или что?

  • @nikolaydd6219
    @nikolaydd6219 2 роки тому +1

    А как передавать нейронке печатные буквы, ведь они разной ширины. Например буква П может уместится в 28х28 а вот буква Щ уже не поместится, либо ТОЧКА, она вообще в длину пару пикселей. Как распознавать печатный текст, а не по одной буквы рукописного?

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

      это уже другая задача, здесь мы полагаем, что буквы умещаются в 28x28 пикселей

    • @nikolaydd6219
      @nikolaydd6219 2 роки тому

      @@selfedu_rus А какие-то рекомендации есть =)? Думается мне, что например выходной нейрон ТОЧКИ должен считать только те веса, в входные нейроны которых умещается заданная буква, а веса от остальных нейронов по нулям. Такой подход сработает?

    • @selfedu_rus
      @selfedu_rus  2 роки тому +1

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

  • @_nickname_nickname_
    @_nickname_nickname_ 3 роки тому +1

    У меня была проблема, при обучении и валидации всё норм, а при тесте выдает ошибку 97%))
    Делал всё как у вас, посмотрел код на гите - всё как у вас. Может я где-то у вас это не заметил, но допер как решить проблему - надо добавить 2 строчки:
    x_test = x_test / 255
    y_test = y_test / 255
    и тогда всё заработало норм. Не понимаю как у вас без этого работает.
    А еще после первой эпохи у меня accuracy равен 1
    upd
    чот я вообще не понимаю - поставил 1 скрытый нейрон вместо 128 и 2 эпохи, на тестовой выборке вывелось:
    313/313 [==============================] - 1s 2ms/step - loss: 0.1420 - accuracy: 1.0000
    upd_2
    Короче я удалил строки со стандартизацией и всё стало нормально выдавать, как у вас)
    upd_3
    Вернул обратно стандартизация (x/y)_train, а категории поставил выше - стало точнее считать.
    upd_4
    В выделении неверных вариантов зачем строка "p_false = pred[~mask]" ?

    • @selfedu_rus
      @selfedu_rus  3 роки тому

      У меня тоже есть эти строчки (см. файл lesson 8. keras_digits.py на гите - ссылка под видео)

    • @_nickname_nickname_
      @_nickname_nickname_ 3 роки тому +1

      @@selfedu_rus В этом плане ошибку у себя нашел, всё как всегда по не внимательности. Вместо x_test = x_test / 255 написал у_test = у_test / 255 и начались танцы с бубном. Еще не понимаю, почему не работает x_test /= 255 ?

  • @Federation1323
    @Federation1323 3 роки тому +1

    ты бох

  • @iwantapetfox9262
    @iwantapetfox9262 3 роки тому

    Результат всегда 0. Как исправить?

  • @torbokovsanat
    @torbokovsanat 3 роки тому

    +

  • @rpuropu
    @rpuropu 3 роки тому +1

    у меня 91-92%.. постоянно) .. не моё?)

    • @selfedu_rus
      @selfedu_rus  3 роки тому

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

    • @rpuropu
      @rpuropu 3 роки тому +1

      @@selfedu_rus я заново по всем окнам в юпитере прошелся, получил 97%..) Спасибо) ради свёрточной я здесь и нахожусь) если честно я удивился что у вас она есть в альбоме с простым названием Нейронные сети. Как-то скромно. а это же уже диплёрнинг. Еслиб не гугл, то я бы даже не догадался заглянуть в этот альбом. так бы и изучал нампай, матплотлиб, жду пандоса, может повезёт и он будет?)

  • @uglevod184
    @uglevod184 6 місяців тому +1

    вот такой вот RElu...что за relu

    • @selfedu_rus
      @selfedu_rus  6 місяців тому

      f(x) = x, x >= 0 и f(x) = 0, иначе

  • @mark-tin
    @mark-tin 2 роки тому +2

    Вроде понятно, но ничего не понятно.

  • @korsman723
    @korsman723 8 місяців тому

    Много словоблудия, ноль практики. Структура объясняется очень оторвано от контекста, не понятно и откровенно говоря становится скучно смотреть

  • @forpublic777
    @forpublic777 3 роки тому

    Со всем уважением, но слух режет от того что вы ставите ударение на первом слоге на слове сЕти.
    Привычней в единственном числе ставить на втором слоге (нейронные сЕти, нейронной сетИ).

    • @selfedu_rus
      @selfedu_rus  3 роки тому +3

      Правильно произносить сЕти

    • @forpublic777
      @forpublic777 3 роки тому

      @@selfedu_rus все с Горбачева пошло с его мЫшлением, вместо мышлЕнием

    • @selfedu_rus
      @selfedu_rus  3 роки тому +3

      @@forpublic777 проверочное слово сЕть

  • @dzakarath
    @dzakarath Рік тому +1

    строка from transform.keras.datasets import mnist не только в VSC но и в колаборатории не работает, что делать?

  • @user-mu5cj4hv9l
    @user-mu5cj4hv9l 7 місяців тому +2

    3:45, а вы точно человек, а не нейросеть?)

  • @dgofman1975
    @dgofman1975 Рік тому +2

    Данные уже нормализированы не знаю зачем дважды нормализировать?
    # стандартизация входных данных
    #x_train = x_train / 255
    #x_test = x_test / 255
    Советую показать раздницу между редикт и тест значениями
    x_false = x_test[~mask]
    y_false = y_test[~mask]
    pred_false = pred[~mask]
    print(x_false.shape)
    # Вывод первых 25 неверных результатов
    plt.figure(figsize=(10,5))
    for i in range(25):
    plt.subplot(5,5,i+1)
    plt.text(0, 0, "Значение {} != {}".format(y_false[i], pred_false[i]))
    plt.xticks([])
    plt.yticks([])
    plt.imshow(x_false[i], cmap=plt.cm.binary)
    в последних версиях tensorflow keras.layers импортируется так
    from keras.layers import Dense, Flatten

    • @selfedu_rus
      @selfedu_rus  Рік тому

      просто принято подавать значения в диапазоне от 0 до 1 (для некоторых функций активаций полезно, например, сигмоида, гиперболический тангенс)

  • @fruktiliyagoda6555
    @fruktiliyagoda6555 11 місяців тому +1

    Что такое 'camp=plt.cm.binary'? У меня вообще выдаёт, что не существует такого. Удаляю, всё работает

    • @watson6954
      @watson6954 10 місяців тому

      Это влияет на отображение цвета на графиках. По умолчанию они цветные (viridis). Команда 'cmap = plt.cm.binary' (у Вас, кстати, ошибка в написании, поэтому команда не работает) делает изображение черно-белым.

    • @fruktiliyagoda6555
      @fruktiliyagoda6555 10 місяців тому

      @@watson6954 большое спасибо. Я и не заметил этой ошибки