-
Notifications
You must be signed in to change notification settings - Fork 0
/
ML_CNN
156 lines (130 loc) · 9.94 KB
/
ML_CNN
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
# Импорт модулz операционной системы
import os
# Переменные окружения для конфигурации TensorFlow
os.environ['TF_ENABLE_ONEDNN_OPTS'] = '0' # Отключаем оптимизации oneDNN
os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' # Уменьшаем количество логов
# Импорт остальных библиотек
import matplotlib.pyplot as plt
import tensorflow as tf
from tensorflow.keras import datasets, layers, models
from tensorflow.keras.models import load_model
from tensorflow.keras.preprocessing.image import ImageDataGenerator
from tensorflow.keras.layers import Input
from tensorflow.keras.utils import plot_model
# Загрузка и нормализация данных CIFAR-10
(train_images, train_labels), (test_images, test_labels) = datasets.cifar10.load_data()
train_images, test_images = train_images / 255.0, test_images / 255.0
# Определение классов для CIFAR-10
class_names = ['airplane', 'automobile', 'bird', 'cat', 'deer', 'dog', 'frog', 'horse', 'ship', 'truck']
# Отрисовка первых 25 изображений из обучающего набора данных с названиями классов в качестве меток
plt.figure(figsize=(10, 10)) # Создание фигуры для отрисовки
for i in range(25): # Цикл для отрисовки 25 изображений
plt.subplot(5, 5, i + 1) # Создание подграфика для каждого изображения
plt.xticks([]) # Удаление меток на оси X
plt.yticks([]) # Удаление меток на оси Y
plt.grid(False) # Отключение сетки
plt.imshow(train_images[i], cmap=plt.cm.binary) # Отображение i-го изображения
plt.xlabel(class_names[train_labels[i][0]]) # Подпись с названием класса
plt.show() # Показать изображения
# Функция для случайного отражения изображений
def random_flip(image, label):
image = tf.image.random_flip_left_right(image)
return image, label
# Создание датасетов для обучения и тестирования
train_dataset = tf.data.Dataset.from_tensor_slices((train_images, train_labels))
test_dataset = tf.data.Dataset.from_tensor_slices((test_images, test_labels))
# Применение аугментации и батчинга
train_dataset = train_dataset.map(random_flip).batch(32).prefetch(tf.data.AUTOTUNE)
test_dataset = test_dataset.batch(32).prefetch(tf.data.AUTOTUNE)
# Путь к модели
model_path = 'Model_CNN.keras' # Укажите путь к вашей модели или название для новой
# Загрузка или создание модели
if os.path.exists(model_path):
model = load_model(model_path)
print("Модель загружена.")
else:
model = models.Sequential([
Input(shape=(32, 32, 3)), # Указываем форму входных данных для модели
layers.Conv2D(32, (3, 3), activation='relu', padding='same'), # Первый сверточный слой с сохранением размерности
layers.BatchNormalization(), # Слой пакетной нормализации
layers.Conv2D(32, (3, 3), activation='relu', padding='same'), # Второй сверточный слой
layers.BatchNormalization(), # Слой пакетной нормализации
layers.MaxPooling2D((2, 2)), # Слой пулинга для уменьшения размерности
layers.Dropout(0.2), # Слой Dropout для предотвращения переобучения, отключает 20% нейронов
layers.Conv2D(64, (3, 3), activation='relu', padding='same'), # Третьий сверточный слой с большей глубиной
layers.BatchNormalization(), # Слой пакетной нормализации
layers.Conv2D(64, (3, 3), activation='relu', padding='same'), # Четвертый сверточный слой
layers.BatchNormalization(), # Слой пакетной нормализации
layers.MaxPooling2D((2, 2)), # Слой пулинга для уменьшения размерности
layers.Dropout(0.3), # Увеличиваем Dropout до 30% для дополнительной борьбы с переобучением
layers.Conv2D(128, (3, 3), activation='relu', padding='same'), # Пятый сверточный слой с большей глубиной
layers.BatchNormalization(), # Слой пакетной нормализации
layers.Conv2D(128, (3, 3), activation='relu', padding='same'), # Шестой сверточный слой с большей глубиной
layers.BatchNormalization(), # Слой пакетной нормализации
layers.MaxPooling2D((2, 2)), # Слой пулинга для уменьшения размерности
layers.Dropout(0.4), # Увеличение Dropout до 40% для дополнительной борьбы с переобучением
layers.Flatten(), # Выравниваем данные для полносвязного слоя
layers.Dense(128, activation='relu'), # Полносвязный слой
layers.Dropout(0.5), # Самый высокий уровень Dropout для предотвращения переобучения
layers.Dense(10, activation='softmax') # Выходной слой с 10 классами
])
print("Новая модель создана.")
# Компиляция модели с адаптивной скоростью обучения
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001) # Оптимизатор Adam с заданной скоростью обучения
model.compile(optimizer=optimizer,
loss='sparse_categorical_crossentropy', # Функция потерь для классификации
metrics=['accuracy']) # Метрика оценки - точность
# Параметры аугментации данных
datagen = ImageDataGenerator(
rotation_range=15, # Добавляет повороты на 15 градусов для имитации разных углов зрения
width_shift_range=0.1, # Сдвигает изображения по горизонтали на 10% их ширины
height_shift_range=0.1, # Сдвигает изображения по вертикали на 10% их высоты
shear_range=0.1, # Применяет сдвиг для имитации изменения перспективы
zoom_range=0.2, # Применяет случайное увеличение/уменьшение изображений
horizontal_flip=True, # Добавляет отражение изображений по горизонтали
fill_mode='nearest' # Заполняет новые пиксели, появляющиеся после трансформации ближайшими значениями
)
# Добавление пакетной нормализации
for i, layer in enumerate(model.layers):
if 'conv' in layer.name:
model.layers.insert(i+1, layers.BatchNormalization())
# Выводит сводку о модели
model.summary()
# Визуализация архитектуры модели
plot_model(model, to_file='model_architecture.png', show_shapes=True, show_layer_names=True)
# Функция адаптивного обучения
def lr_schedule(epoch):
# Функция для адаптивного изменения скорости обучения
lr = 0.001 # Начальная скорость обучения
if epoch > 10:
lr *= 0.5 # Уменьшает скорость обучения вдвое после 10 эпох
elif epoch > 20:
lr *= 0.2 # Уменьшает скорость обучения до 20% после 20 эпох
return lr
# Коллбек для динамического изменения скорости обучения
lr_scheduler = tf.keras.callbacks.LearningRateScheduler(lr_schedule)
# Коллбек для ранней остановки обучения, если потери на валидационном наборе не улучшаются в течение 5 эпох
early_stopping = tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=5)
# Обучение модели с аугментацией данных и коллбеками
history = model.fit(
datagen.flow(train_images, train_labels, batch_size=32),
epochs=50, # Устанавливаем общее число эпох
validation_data=(test_images, test_labels), # Используем тестовый набор как валидационный
callbacks=[lr_scheduler, early_stopping], # Добавляем сюда созданные коллбеки
verbose=1 # Режим вывода: одна строка на эпоху
)
# Построение графиков точности на обучающем и валидационном наборах данных
plt.plot(history.history['accuracy'], label='Точность на обучающем наборе')
plt.plot(history.history['val_accuracy'], label='Точность на валидационном наборе')
plt.xlabel('Эпоха')
plt.ylabel('Точность')
plt.legend(loc='lower right')
plt.show()
# Оценка модели
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=2)
print(f"Точность на тестовом наборе: {test_acc:.2f}")
# Сохранение модели после обучения
model.save(model_path)
print("Модель сохранена.")
# Выводим сводку обновленной модели
model.summary()