"""
# Распознавание предметов одежды из набора MNIST
"""
"""
Импортируем необходимые библиотеки
"""
""" объект последовательной модели нейронной сети """
from tensorflow.keras.models import Sequential
""" полносвязный слой нейронной сети """
from tensorflow.keras.layers import Dense
""" вспомогательный модуль Keras для предварительной обработки данных """
from tensorflow.keras import utils
""" библиотекf для работы с матрицами (многомерными тензорами) и линейной алгеброй """
import numpy as np
""" библиотека для считывания и записи файлов в формате ".csv" и других табличных форматах,
    а также для их быстрой и удобной обработки """
import pandas as pd
""" библиотека для работы с операционной системой """
import os 

"""Зафиксируем генератор случайных чисел. Его не менять!!!"""
from numpy.random import seed
seed(2020)
from tensorflow.random import set_seed
set_seed(2020)
""" библиотека для визуализации данных """
import matplotlib.pyplot as plt
%matplotlib inline 
""" посмотрим, какие файлы храняться в директории """
for dirname, _, filenames in os.walk('/kaggle/input/'):
    for filename in filenames:
        print(os.path.join(dirname, filename))
"""
Загружаем наборы данных для обучения и тестирования
"""
"""функция "read_csv" презназначена для считывания файлов в формате ".csv"
filepath_or_buffer - путь к файлу,
index_col - необязательный параметр, который указывает какую колонку использовать, как индекс.
Если параметр не указан, что pandas создаст столбец с индексами самостоятельно
Подробнее о возможностях функции https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.read_csv.html"""
train_df = pd.read_csv(filepath_or_buffer='/kaggle/input/nnfashinmnist/train.csv', index_col='id')
test_df = pd.read_csv(filepath_or_buffer='/kaggle/input/nnfashinmnist/test.csv', index_col='id')
sample_submission = pd.read_csv(filepath_or_buffer='/kaggle/input/nnfashinmnist/sample_submission.csv', index_col='id')
"""
Извлекаем данные из таблиц pandas в числовые массивы (векторы и матрицы) numpy, которе можно подать на вход нейронной сети
"""
"""iloc позволяет считать необходимые строки и столбцы, обращаясь к ним не по именам, а по порядковой нумерации
Подробнее про функцию iloc https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.iloc.html
Запись train_df['label'], извлекает из всей таблицы столбец с названием 'label' 
.values - преобразовывает pandas DataFrame (объект таблицы) в numpy массив"""
x_train, y_train = train_df.iloc[:,:-1].values, train_df['label'].values
x_test = test_df.values
"""
Проверяем совпадает ли количество признаков в тренировочном и тестовом наборах
"""
assert x_train.shape[1] == x_test.shape[1], 'Количество признаков в тренировочном и тестовом наборах должно совпадать'
"""
Создаем соответствие номеров классов с их названиями
"""
classes = {0:'футболка', 1:'брюки', 2:'свитер', 3:'платье', 4:'пальто',
           5:'туфли', 6:'рубашка', 7:'кроссовки', 8:'сумка', 9:'ботинки'}
"""
Смотрим примеры изображений в наборе
"""
plt.figure(figsize=(10,10))
for i in range(100,150):
    plt.subplot(5,10,i-100+1)
    plt.xticks([])
    plt.yticks([])
    plt.grid(False)
    plt.imshow(x_train[i].reshape((28,28)), cmap=plt.cm.binary)
    plt.xlabel(classes[y_train[i]])
"""
Нормализация данных
"""
# Векторизованные операции
# Применяются к каждому элементу массива отдельно
x_train = x_train / 255.0
# Все преобразования с тренировочным наборам повторяем и для тестового
x_test = x_test / 255.0
"""
Работа с метками правильных ответов
"""
print(y_train[100])
"""
**Преобразуем метки в формат one hot encoding**
"""
y_train = utils.to_categorical(y_train)
"""
Правильный ответ в формате one hot encoding
"""
print(y_train[100])
"""
## Создаем нейронную сеть
"""
"""
**Описываем архитектуру нейронной сети**
"""
seed(2020)
set_seed(2020)
# Создаем последовательную модель
model = Sequential()
# Входной полносвязный слой, 800 нейронов, 784 входа в каждый нейрон
model.add(Dense(units=800, input_dim=784, activation="relu"))
model.add(Dense(units=400, activation="relu"))
# Выходной полносвязный слой, 10 нейронов (по количеству рукописных цифр)
model.add(Dense(units=10, activation="softmax"))
"""
**Компилируем сеть**
"""
seed(2020)
set_seed(2020)
model.compile(loss="categorical_crossentropy", optimizer="SGD", metrics=["accuracy"])
print(model.summary())
"""
## Обучаем нейронную сеть[](http://)
"""
seed(2020)
set_seed(2020)
history = model.fit(x_train, y_train, 
                    batch_size=128,
                    epochs=100,
                    validation_split=0.2,
                    verbose=1)
"""
## Анализ качества модели с помощью проверочных кривых
"""
"""
Изменение точности на обучающих и проверочных данных
"""
plt.plot(history.history['accuracy'], 
         label='Доля правильных ответов на обучающем наборе')
plt.plot(history.history['val_accuracy'], 
         label='Доля правильных ответов на проверочном наборе')
plt.xlabel('Эпоха обучения')
plt.ylabel('Доля правильных ответов')
plt.legend()
plt.show()
"""
Изменение потерь на обучающих и проверочных данных
"""
plt.plot(history.history['loss'], 
         label='Оценка потерь на обучающем наборе')
plt.plot(history.history['val_loss'], 
         label='Оценка потерь на проверочном наборе')
plt.xlabel('Эпоха обучения')
plt.ylabel('Оценка потерь')
plt.legend()
plt.show()
"""
## Готовим данные для теста на liderboard
"""
"""
Распознаем тестовый набор данных
"""
"""делаем предсказания по всем тестовым данным"""
predictions = model.predict(x_test)
"""извлекаем номера предсказаний с максимальными вероятностями по всем объектам тестового набора"""
predictions = np.argmax(predictions, axis=1)
predictions
"""
Пишем результаты предсказаний в шаблон "sample_submission"
"""
"""используем файл с правильным шаблоном формата записи ответов и пишем в него наши предсказания"""
sample_submission['label'] = predictions
"""
Записываем ответы для проверки на liderboard
"""
"""to_csv - пишет табличные данные в файл '.csv' """
sample_submission.to_csv('sample_submission.csv')
"""
**Если на основе сравнения тренировочных и проверочных данных вы пришли к выводу, что избавились от переобучения,сравните значение "accuracy" на последней эпохе обучения и на тесте, после "submission".**

**Эти 2 оценки должны расходиться меньше чем на 2% (или 0.02)**
"""