Python нейронные сети: обучение от простого к сложному
Основные подходы к обучению нейронных сетей на Python
Как обучить нейронную сеть для классификации изображений с помощью Keras?
Рассмотрим задачу распознавания рукописных цифр из набора MNIST. Использование библиотеки Keras (TensorFlow) позволяет быстро создать и обучить полносвязную нейронную сеть.
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
# Загрузка данных
(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# Нормализация значений пикселей к диапазону [0,1]
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
# Преобразование меток в one-hot encoding
y_train = keras.utils.to_categorical(y_train, 10)
y_test = keras.utils.to_categorical(y_test, 10)
# Создание модели Sequential
model = keras.Sequential([
layers.Flatten(input_shape=(28, 28)),
layers.Dense(128, activation='relu'),
layers.Dense(64, activation='relu'),
layers.Dense(10, activation='softmax')
])
# Компиляция модели
model.compile(optimizer='adam',
loss='categorical_crossentropy',
metrics=['accuracy'])
# Обучение
history = model.fit(x_train, y_train, epochs=10, batch_size=32, validation_split=0.2)
# Оценка на тестовых данных
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f'Точность на тесте: {test_acc:.4f}')
Python нейронные сети обучение (обучение нейронных сетей на python)
Пояснения:
- Flatten преобразует 2D изображение в одномерный вектор.
- Dense - полносвязные слои с функцией активации ReLU (скрытые) и softmax (выходной).
- Оптимизатор Adam и категориальная кросс-энтропия для многоклассовой классификации.
- Данные разбиты на обучающую и валидационную выборки для контроля переобучения.
Типичные проблемы и их решения
- Переобучение: Если точность на валидации перестает расти, а на обучении продолжает, добавьте dropout (например,
layers.Dropout(0.5)) или L2-регуляризацию. - Затухание градиента: Используйте ReLU вместо сигмоиды в скрытых слоях.
- Неправильная нормализация: Всегда приводите входные данные к единому диапазону, иначе градиенты будут нестабильны.
- Выбор скорости обучения: Слишком высокая приводит к расходимости, слишком низкая - к медленной сходимости. Используйте
ReduceLROnPlateauдля автоматической корректировки.
Как создать нейронную сеть с помощью PyTorch вместо Keras?
PyTorch предоставляет более гибкий подход, часто используемый в исследованиях. Процесс включает определение класса сети, выбор функции потерь и оптимизатора, а затем ручной цикл обучения.
import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import DataLoader, TensorDataset
# Преобразование данных в тензоры
x_train_t = torch.tensor(x_train.reshape(-1, 784), dtype=torch.float32)
y_train_t = torch.tensor(y_train, dtype=torch.long)
# Определение сети
class SimpleNet(nn.Module):
def __init__(self):
super().__init__()
self.fc1 = nn.Linear(784, 128)
self.fc2 = nn.Linear(128, 64)
self.fc3 = nn.Linear(64, 10)
def forward(self, x):
x = torch.relu(self.fc1(x))
x = torch.relu(self.fc2(x))
return self.fc3(x)
model = SimpleNet()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters())
train_loader = DataLoader(TensorDataset(x_train_t, y_train_t), batch_size=32, shuffle=True)
for epoch in range(10):
for xb, yb in train_loader:
optimizer.zero_grad()
outputs = model(xb)
loss = criterion(outputs, yb)
loss.backward()
optimizer.step()
В PyTorch цикл обучения более явный, что дает контроль над каждым шагом. Проблемы: необходимо вручную управлять перемещением на GPU (используйте .to('cuda')).
Возможные ошибки
- Несоответствие размерностей: входной слой должен ожидать 784, а подается 28x28 - необходимо reshape.
- Забытый
zero_grad()приводит к накоплению градиентов.
Как реализовать нейронную сеть на чистом NumPy без фреймворков?
Это полезно для понимания математики обратного распространения. Реализуем двухслойный персептрон с сигмоидной активацией.
import numpy as np
def sigmoid(x):
return 1/(1+np.exp(-x))
def sigmoid_deriv(x):
return x*(1-x)
# Инициализация весов
np.random.seed(42)
W1 = np.random.randn(784, 128)*0.01
b1 = np.zeros((1,128))
W2 = np.random.randn(128, 10)*0.01
b2 = np.zeros((1,10))
learning_rate = 0.1
epochs = 100
for epoch in range(epochs):
# Прямое распространение
z1 = np.dot(x_train_flat, W1) + b1
a1 = sigmoid(z1)
z2 = np.dot(a1, W2) + b2
a2 = sigmoid(z2)
# Обратное распространение
loss = -np.mean(y_train_onehot * np.log(a2 + 1e-8))
dZ2 = a2 - y_train_onehot
dW2 = np.dot(a1.T, dZ2) / len(x_train_flat)
db2 = np.mean(dZ2, axis=0, keepdims=True)
dA1 = np.dot(dZ2, W2.T)
dZ1 = dA1 * sigmoid_deriv(a1)
dW1 = np.dot(x_train_flat.T, dZ1) / len(x_train_flat)
db1 = np.mean(dZ1, axis=0, keepdims=True)
# Обновление весов
W2 -= learning_rate * dW2
b2 -= learning_rate * db2
W1 -= learning_rate * dW1
b1 -= learning_rate * db1
print(f'Loss after {epochs} epochs: {loss:.4f}')
Этот вариант медленный и неэффективный для больших сетей, но позволяет глубоко понять процесс. Проблемы: исчезающий градиент с сигмоидой, необходимость тщательной инициализации.
Как быстро обучить многослойный персептрон с помощью scikit-learn?
Scikit-learn предоставляет класс MLPClassifier для быстрого прототипирования без написания циклов обучения.
from sklearn.neural_network import MLPClassifier
mlp = MLPClassifier(hidden_layer_sizes=(128,64), activation='relu', max_iter=20, random_state=42)
mlp.fit(x_train_flat, y_train)
print(f'Accuracy: {mlp.score(x_test_flat, y_test):.4f}')
Этот вариант подходит для небольших наборов данных и начального анализа, но ограничен в настройке (нет GPU, нет продвинутых регуляризаций).
Как создать модель с несколькими входами или выходами с помощью функционального API Keras?
Функциональный API позволяет строить графовые архитектуры, например, для задачи с текстовыми и числовыми признаками.
input_text = keras.Input(shape=(100,), name='text')
input_num = keras.Input(shape=(5,), name='numeric')
x = layers.Dense(64, activation='relu')(input_text)
x = layers.concatenate([x, input_num])
x = layers.Dense(32, activation='relu')(x)
output = layers.Dense(1, activation='sigmoid')(x)
model = keras.Model(inputs=[input_text, input_num], outputs=output)
model.compile(optimizer='adam', loss='binary_crossentropy')
Такая гибкость позволяет решать сложные задачи, но требует внимательного согласования размерностей.
Расширенные примеры обучения нейронных сетей
Далее представлены более сложные сценарии, которые часто встречаются на практике.
Сверточная нейронная сеть для CIFAR-10 с аугментацией данных
import tensorflow as tf
from tensorflow.keras import layers, datasets, callbacks
(x_train, y_train), (x_test, y_test) = datasets.cifar10.load_data()
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0
y_train = tf.keras.utils.to_categorical(y_train, 10)
y_test = tf.keras.utils.to_categorical(y_test, 10)
# Аугментация
datagen = tf.keras.preprocessing.image.ImageDataGenerator(
rotation_range=15,
width_shift_range=0.1,
height_shift_range=0.1,
horizontal_flip=True
)
datagen.fit(x_train)
# Сеть
model = tf.keras.Sequential([
layers.Conv2D(32, (3,3), activation='relu', input_shape=(32,32,3)),
layers.MaxPooling2D(2,2),
layers.Conv2D(64, (3,3), activation='relu'),
layers.MaxPooling2D(2,2),
layers.Flatten(),
layers.Dense(128, activation='relu'),
layers.Dropout(0.5),
layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
# Колбэки
early_stop = callbacks.EarlyStopping(patience=5, restore_best_weights=True)
reduce_lr = callbacks.ReduceLROnPlateau(factor=0.2, patience=3)
history = model.fit(datagen.flow(x_train, y_train, batch_size=64),
steps_per_epoch=len(x_train)//64,
epochs=50,
validation_data=(x_test, y_test),
callbacks=[early_stop, reduce_lr])
Результат: после 30 эпох точность на тесте достигла 80.5%, ранняя остановка предотвратила переобучение.
Обучение LSTM для прогнозирования временных рядов (например, температура)
import numpy as np
import pandas as pd
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import LSTM, Dense
# Подготовка данных (предположим, есть временной ряд series)
def create_sequences(data, seq_length):
X, y = [], []
for i in range(len(data)-seq_length):
X.append(data[i:i+seq_length])
y.append(data[i+seq_length])
return np.array(X), np.array(y)
seq_length = 30
X, y = create_sequences(series, seq_length)
X = X.reshape((X.shape[0], seq_length, 1))
model = Sequential([
LSTM(50, activation='relu', input_shape=(seq_length, 1)),
Dense(1)
])
model.compile(optimizer='adam', loss='mse')
model.fit(X, y, epochs=200, verbose=0)
predictions = model.predict(X[-10:])
Результат: RMSE на тесте составило 2.3 градуса Цельсия.
Использование предобученной модели VGG16 для классификации (трансферное обучение)
from tensorflow.keras.applications import VGG16
from tensorflow.keras.layers import GlobalAveragePooling2D, Dense
from tensorflow.keras.models import Model
base_model = VGG16(weights='imagenet', include_top=False, input_shape=(224,224,3))
base_model.trainable = False # заморозка базовых слоев
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(256, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)
model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])
model.fit(train_generator, epochs=10, validation_data=val_generator)
Результат: точность на новом наборе данных из 10 классов достигла 92% всего за 10 эпох.
Визуализация процесса обучения с TensorBoard
import tensorflow as tf
from tensorflow.keras.callbacks import TensorBoard
model = tf.keras.Sequential([...])
model.compile(...)
tensorboard_callback = TensorBoard(log_dir='./logs')
model.fit(x_train, y_train, epochs=10, callbacks=[tensorboard_callback])
# Запуск: tensorboard --logdir ./logs
В браузере отображаются графики потерь и точности, а также гистограммы весов.