{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.11.13","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":5196,"sourceType":"datasetVersion","datasetId":3147}],"dockerImageVersionId":31153,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"code","source":"import numpy as np \nimport pandas as pd ","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2025-10-13T17:00:29.027575Z","iopub.execute_input":"2025-10-13T17:00:29.028348Z","iopub.status.idle":"2025-10-13T17:00:29.032260Z","shell.execute_reply.started":"2025-10-13T17:00:29.028319Z","shell.execute_reply":"2025-10-13T17:00:29.031514Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Инициализация данных","metadata":{}},{"cell_type":"code","source":"df = pd.read_csv('/kaggle/input/mnist-digit-recognizer/train.csv')\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T16:50:45.293337Z","iopub.execute_input":"2025-10-13T16:50:45.293638Z","iopub.status.idle":"2025-10-13T16:50:47.526398Z","shell.execute_reply.started":"2025-10-13T16:50:45.293617Z","shell.execute_reply":"2025-10-13T16:50:47.525470Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Подготовка данных","metadata":{}},{"cell_type":"code","source":"df.sort_values('label', inplace=True)\ndf","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:31:44.903948Z","iopub.execute_input":"2025-10-13T15:31:44.904264Z","iopub.status.idle":"2025-10-13T15:31:45.083703Z","shell.execute_reply.started":"2025-10-13T15:31:44.904213Z","shell.execute_reply":"2025-10-13T15:31:45.082590Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"counts = df['label'].value_counts().reindex(range(10), fill_value=0)\ncounts","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:31:45.084727Z","iopub.execute_input":"2025-10-13T15:31:45.085351Z","iopub.status.idle":"2025-10-13T15:31:45.099534Z","shell.execute_reply.started":"2025-10-13T15:31:45.085318Z","shell.execute_reply":"2025-10-13T15:31:45.098647Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"**Берем из df по 1000 лэйблов на символ**","metadata":{}},{"cell_type":"code","source":"df_10000 = pd.DataFrame()\ndf_10000 = pd.concat([df_10000, df[:1000]], ignore_index=True)\nc = 1\nfor i in range(len(counts)):\n    c += counts[i]\n    df_10000 = pd.concat([df_10000, df[c:c+1000]], ignore_index=True)\n\ndf_10000.info()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:31:45.101204Z","iopub.execute_input":"2025-10-13T15:31:45.101521Z","iopub.status.idle":"2025-10-13T15:31:45.253618Z","shell.execute_reply.started":"2025-10-13T15:31:45.101493Z","shell.execute_reply":"2025-10-13T15:31:45.252626Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"df_10000 = df_10000.iloc[np.random.permutation(len(df_10000))]\ndf_10000","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:34:43.905476Z","iopub.execute_input":"2025-10-13T15:34:43.906074Z","iopub.status.idle":"2025-10-13T15:34:43.956834Z","shell.execute_reply.started":"2025-10-13T15:34:43.906045Z","shell.execute_reply":"2025-10-13T15:34:43.955803Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"img_height = 28\nimg_width = 28\nimg_channels = 1\nnum_classes = df_10000['label'].nunique()\n\nprint(f\"Image dimensions: {img_height}x{img_width}x{img_channels}\")\nprint(f\"Number of classes: {num_classes}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:42:28.755611Z","iopub.execute_input":"2025-10-13T15:42:28.755916Z","iopub.status.idle":"2025-10-13T15:42:28.763621Z","shell.execute_reply.started":"2025-10-13T15:42:28.755893Z","shell.execute_reply":"2025-10-13T15:42:28.762379Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.utils import to_categorical\n\npredictors = df_10000.drop(columns=['label']).values.astype('float32') / 255.0\npredictors = predictors.reshape(-1, img_height, img_width, img_channels)\ntarget = to_categorical(df_10000['label'], num_classes)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:42:47.257744Z","iopub.execute_input":"2025-10-13T15:42:47.258045Z","iopub.status.idle":"2025-10-13T15:42:47.319943Z","shell.execute_reply.started":"2025-10-13T15:42:47.258024Z","shell.execute_reply":"2025-10-13T15:42:47.318962Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"from tensorflow.keras.preprocessing.image import ImageDataGenerator\n\naugmenter = ImageDataGenerator(\n    rotation_range=20,\n    zoom_range=0.2\n)\n\naugmented_iter = augmenter.flow(\n    predictors,\n    batch_size=predictors.shape[0],\n    shuffle=False\n)\n\naugmented_images = next(augmented_iter)\n\npredictors_aug = np.concatenate([predictors, augmented_images], axis=0)\ntarget_aug = np.concatenate([target, target], axis=0)\n\nextra_needed = 200000 - predictors_aug.shape[0]\n\nif extra_needed > 0:\n    extra_iter = augmenter.flow(\n        predictors,\n        batch_size=extra_needed,\n        shuffle=False\n    )\n    \n    extra_images = next(extra_iter)\n    predictors_aug = np.concatenate([predictors_aug, extra_images], axis=0)\n    target_aug = np.concatenate([target_aug, target[:extra_needed]], axis=0)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:42:51.862270Z","iopub.execute_input":"2025-10-13T15:42:51.862777Z","iopub.status.idle":"2025-10-13T15:42:56.031432Z","shell.execute_reply.started":"2025-10-13T15:42:51.862753Z","shell.execute_reply":"2025-10-13T15:42:56.030745Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"idx = np.random.permutation(predictors_aug.shape[0])\npredictors_aug = predictors_aug[idx]\ntarget_aug = target_aug[idx]","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:42:56.742499Z","iopub.execute_input":"2025-10-13T15:42:56.742806Z","iopub.status.idle":"2025-10-13T15:42:56.787987Z","shell.execute_reply.started":"2025-10-13T15:42:56.742785Z","shell.execute_reply":"2025-10-13T15:42:56.787238Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"print(f\"Augmented predictors shape: {predictors_aug.shape}\")\nprint(f\"Augmented target shape: {target_aug.shape}\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:44:03.987200Z","iopub.execute_input":"2025-10-13T15:44:03.987841Z","iopub.status.idle":"2025-10-13T15:44:03.992284Z","shell.execute_reply.started":"2025-10-13T15:44:03.987813Z","shell.execute_reply":"2025-10-13T15:44:03.991182Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Построение модели","metadata":{}},{"cell_type":"code","source":"import tensorflow as tf\nfrom keras.applications import MobileNetV2\nfrom keras.models import Sequential\nfrom keras.layers import Input, Dense, Flatten, Resizing, Lambda, Dropout\n\nbase_model = MobileNetV2(weights='imagenet', include_top=False, input_shape=(96, 96, 3))\nbase_model.trainable = False\n\nmodel = Sequential([\n    Input(shape=(img_height, img_width, img_channels)),\n    Resizing(96, 96),\n    Lambda(lambda x: tf.image.grayscale_to_rgb(x)),\n    base_model,\n    Flatten(),\n    Dense(num_classes, activation='softmax')\n])\n\nmodel.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=1.0), loss='categorical_crossentropy', metrics=['accuracy'])\nmodel.summary()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:44:25.409294Z","iopub.execute_input":"2025-10-13T15:44:25.410090Z","iopub.status.idle":"2025-10-13T15:44:27.600511Z","shell.execute_reply.started":"2025-10-13T15:44:25.410063Z","shell.execute_reply":"2025-10-13T15:44:27.599726Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Обучение модели","metadata":{}},{"cell_type":"code","source":"from tensorflow.keras.callbacks import ReduceLROnPlateau\nfrom tensorflow.keras.callbacks import EarlyStopping\n\n\nreduce_lr  = ReduceLROnPlateau(monitor='val_accuracy', factor=0.1, patience=3, min_lr=1e-6)\nearly_stopping = EarlyStopping(monitor='val_accuracy', patience=10, restore_best_weights=True)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:44:48.168486Z","iopub.execute_input":"2025-10-13T15:44:48.169062Z","iopub.status.idle":"2025-10-13T15:44:48.177703Z","shell.execute_reply.started":"2025-10-13T15:44:48.169030Z","shell.execute_reply":"2025-10-13T15:44:48.176750Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_history = model.fit(predictors_aug, target_aug, validation_split=0.2, epochs=100, batch_size=256, callbacks=[reduce_lr, early_stopping], verbose=1)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T15:44:53.532864Z","iopub.execute_input":"2025-10-13T15:44:53.533505Z","iopub.status.idle":"2025-10-13T16:38:30.145818Z","shell.execute_reply.started":"2025-10-13T15:44:53.533478Z","shell.execute_reply":"2025-10-13T16:38:30.145012Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Визуализация обучения","metadata":{}},{"cell_type":"code","source":"import matplotlib.pyplot as plt\n\nplt.figure(figsize=(10, 5))\nplt.plot(train_history.history['accuracy'], label='train accuracy')\nplt.plot(train_history.history['val_accuracy'], label='validation accuracy')\nplt.xlabel('Epoch')\nplt.ylabel('Accuracy (%)')\nplt.legend()\nplt.show()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2025-10-13T16:40:00.029710Z","iopub.execute_input":"2025-10-13T16:40:00.030029Z","iopub.status.idle":"2025-10-13T16:40:00.269758Z","shell.execute_reply.started":"2025-10-13T16:40:00.030005Z","shell.execute_reply":"2025-10-13T16:40:00.268782Z"}},"outputs":[],"execution_count":null}]}