Написание нейросети на Python: от простого перцептрона до глубоких моделей

Раздел: Машинное обучение и ИИ -> Нейросети и ИИ

Реализация нейросети с помощью TensorFlow и Keras

Как быстро создать и обучить нейросеть для классификации изображений, не вдаваясь в низкоуровневые детали?

Библиотека TensorFlow с высокоуровневым API Keras предоставляет удобные инструменты для построения нейросетей. Пример ниже демонстрирует создание полносвязной сети для распознавания рукописных цифр MNIST.


import tensorflow as tf
from tensorflow.keras import layers, models

# Загрузка данных
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# Построение модели
model = models.Sequential([
    layers.Flatten(input_shape=(28, 28)),
    layers.Dense(128, activation='relu'),
    layers.Dropout(0.2),
    layers.Dense(10, activation='softmax')
])

# Компиляция
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Обучение
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test))

Python пишем нейросеть (написание нейросети на python)

После обучения модель можно сохранить и использовать для предсказаний. Важно: нормализация данных и подбор гиперпараметров существенно влияют на результат.

Типичные проблемы:

  • Переобучение: помогает регуляризация (Dropout, L2) и увеличение данных.
  • Затухающие градиенты: используются активации ReLU или их варианты.
  • Дисбаланс классов: взвешивание потерь или аугментация.

Варианты реализации нейросети

Как написать нейросеть с нуля на NumPy, чтобы понять её внутреннее устройство?

Для учебных целей полезно реализовать простой перцептрон или сеть с одним скрытым слоем, используя только NumPy. Такой код позволяет проследить процесс прямого распространения, вычисления градиентов и обратного распространения ошибки.


import numpy as np

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

def sigmoid_derivative(x):
    return x * (1 - x)

# Входные данные (XOR)
X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([[0],[1],[1],[0]])

# Параметры
np.random.seed(42)
w1 = np.random.rand(2, 4)
w2 = np.random.rand(4, 1)
learning_rate = 0.1

for epoch in range(10000):
    # Прямой проход
    l1 = sigmoid(np.dot(X, w1))
    l2 = sigmoid(np.dot(l1, w2))
    # Ошибка
    error = y - l2
    # Обратное распространение
    d2 = error * sigmoid_derivative(l2)
    d1 = d2.dot(w2.T) * sigmoid_derivative(l1)
    w2 += l1.T.dot(d2) * learning_rate
    w1 += X.T.dot(d1) * learning_rate

print("Результат после обучения:")
print(l2)

нейросеть для генерации кода python (нейросеть для генерации кода на python)

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

Возможные ошибки:

  • Неправильное вычисление производной (забыть учесть цепное правило).
  • Слишком малая скорость обучения приводит к медленной сходимости, большая - к расходимости.
  • Необходимость инициализации весов малыми случайными числами.

Как использовать PyTorch для построения нейросети с динамическим графом вычислений?

PyTorch широко применяется в исследованиях благодаря гибкости и удобству отладки. Пример ниже создаёт такую же сеть, как в Keras, но с явным определением класса модели.


import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms

# Определение модели
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(784, 128)
        self.fc2 = nn.Linear(128, 10)
        self.dropout = nn.Dropout(0.2)

    def forward(self, x):
        x = x.view(-1, 784)
        x = torch.relu(self.fc1(x))
        x = self.dropout(x)
        x = self.fc2(x)
        return x

model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)

# Загрузка данных
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.1307,), (0.3081,))])
train_loader = torch.utils.data.DataLoader(
    datasets.MNIST('./data', train=True, download=True, transform=transform),
    batch_size=64, shuffle=True)

# Цикл обучения
for epoch in range(5):
    for batch_idx, (data, target) in enumerate(train_loader):
        optimizer.zero_grad()
        output = model(data)
        loss = criterion(output, target)
        loss.backward()
        optimizer.step()
    print(f'Epoch {epoch+1}, Loss: {loss.item():.4f}')

Python нейросеть тексты (нейросеть для работы с текстом на python)

PyTorch даёт полный контроль над процессом обучения и позволяет легко использовать GPU (через .to('cuda')). Основной недостаток - больше кода по сравнению с Keras.

Типичные проблемы:

  • Несоответствие размерностей тензоров при прямом проходе.
  • Забытый вызов optimizer.zero_grad() перед каждым батчем.
  • Необходимость явно перемещать данные и модель на устройство (CPU/GPU).

Какие готовые архитектуры (например, из библиотеки timm) можно использовать для быстрого решения задач?

Для многих стандартных задач (классификация, детекция) существуют предобученные модели, которые можно адаптировать под свои данные (transfer learning). Пример с использованием Keras и предобученной ResNet50:


from tensorflow.keras.applications import ResNet50
from tensorflow.keras.layers import Dense, GlobalAveragePooling2D
from tensorflow.keras.models import Model

base_model = ResNet50(weights='imagenet', include_top=False, input_shape=(224,224,3))
x = base_model.output
x = GlobalAveragePooling2D()(x)
x = Dense(1024, activation='relu')(x)
predictions = Dense(10, activation='softmax')(x)
model = Model(inputs=base_model.input, outputs=predictions)

# Заморозка весов базовой модели
for layer in base_model.layers:
    layer.trainable = False

model.compile(optimizer='adam', loss='categorical_crossentropy', metrics=['accuracy'])

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

Проблемы:

  • Несоответствие размеров входных изображений: требуется ресайз до 224×224.
  • Обучение только классификатора может не дать хорошей точности на сильно отличающихся данных.
  • Может потребоваться тонкая настройка (fine-tuning) всей модели.

Расширенные примеры программирования нейросетей на Python

1. Полносвязная сеть для MNIST с сохранением чекпоинтов и визуализацией кривых обучения

Пример

import tensorflow as tf
from tensorflow.keras import layers, models, callbacks
import matplotlib.pyplot as plt

# Загрузка и подготовка данных
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# Модель
model = models.Sequential([
    layers.Flatten(input_shape=(28, 28)),
    layers.Dense(512, activation='relu'),
    layers.BatchNormalization(),
    layers.Dropout(0.3),
    layers.Dense(256, activation='relu'),
    layers.Dropout(0.3),
    layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Колбэки
checkpoint = callbacks.ModelCheckpoint('mnist_model.keras', save_best_only=True, monitor='val_accuracy')
early_stop = callbacks.EarlyStopping(patience=3, restore_best_weights=True)

# Обучение
history = model.fit(x_train, y_train,
                    epochs=20,
                    batch_size=128,
                    validation_split=0.2,
                    callbacks=[checkpoint, early_stop])

# Визуализация
plt.plot(history.history['accuracy'], label='Точность обучения')
plt.plot(history.history['val_accuracy'], label='Точность валидации')
plt.xlabel('Эпоха')
plt.ylabel('Точность')
plt.legend()
plt.savefig('training_curve.png')
plt.show()
Результат: график точности обучения и валидации сохраняется в файл training_curve.png. Модель с наилучшей точностью на валидации сохранена в mnist_model.keras.

2. Сверточная нейросеть (CNN) для классификации CIFAR-10 с аугментацией данных

Пример

import tensorflow as tf
from tensorflow.keras import layers, models, datasets
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# Загрузка CIFAR-10
(x_train, y_train), (x_test, y_test) = datasets.cifar10.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# Аугментация
datagen = ImageDataGenerator(
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True)
datagen.fit(x_train)

# Модель
model = models.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.Conv2D(64, (3,3), activation='relu'),
    layers.Flatten(),
    layers.Dense(64, activation='relu'),
    layers.Dense(10, activation='softmax')
])

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

# Обучение с аугментацией
model.fit(datagen.flow(x_train, y_train, batch_size=64),
          epochs=30,
          validation_data=(x_test, y_test))
Точность на тестовом наборе CIFAR-10 обычно достигает 70-75% после 30 эпох. Аугментация помогает бороться с переобучением.

3. Рекуррентная сеть (LSTM) для прогнозирования временных рядов

Пример

import numpy as np
import tensorflow as tf
from tensorflow.keras import layers, models

# Синтетические данные: синус + шум
x = np.linspace(0, 100, 1000)
y = np.sin(x) + 0.1*np.random.randn(1000)

# Формирование последовательностей (окно 20 шагов)
def create_sequences(data, seq_length):
    xs, ys = [], []
    for i in range(len(data)-seq_length):
        xs.append(data[i:i+seq_length])
        ys.append(data[i+seq_length])
    return np.array(xs), np.array(ys)

X, Y = create_sequences(y, 20)
X = X.reshape((X.shape[0], X.shape[1], 1))

# Модель
model = models.Sequential([
    layers.LSTM(50, activation='relu', input_shape=(20, 1)),
    layers.Dense(1)
])
model.compile(optimizer='adam', loss='mse')

# Обучение
model.fit(X, Y, epochs=100, verbose=0)

# Предсказание
pred = model.predict(X[-10:], verbose=0)
print(pred.flatten())
Вывод: массив из 10 предсказанных значений, близких к реальным синусоидальным значениям.

4. Использование предобученной модели (Transfer Learning) с PyTorch для классификации

Пример

import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import models, transforms, datasets

# Загрузка предобученной ResNet18
model = models.resnet18(pretrained=True)

# Замена последнего слоя на новую голову (10 классов)
num_ftrs = model.fc.in_features
model.fc = nn.Linear(num_ftrs, 10)

# Заморозка всех слоёв, кроме последнего
for param in model.parameters():
    param.requires_grad = False
for param in model.fc.parameters():
    param.requires_grad = True

# Оптимизатор и функция потерь
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.fc.parameters(), lr=0.001)

# Данные (пример: ImageFolder)
# train_loader = ...
# Цикл обучения опущен для краткости
После обучения только головы классификатора точность на новом датасете из 10 классов может достигать 90+% при достаточном количестве данных.

5. Генерация текста с помощью простой RNN (char-level) на TensorFlow

Пример

import tensorflow as tf
import numpy as np

# Текст для обучения (например, Шекспир)
text = "To be or not to be, that is the question..."
# Словарь символов
chars = sorted(set(text))
char2idx = {c:i for i,c in enumerate(chars)}
idx2char = {i:c for c,i in char2idx.items()}

# Векторизация
text_as_int = np.array([char2idx[c] for c in text])
seq_length = 10
sequences = []
for i in range(0, len(text_as_int)-seq_length):
    sequences.append(text_as_int[i:i+seq_length+1])

X = np.array([s[:-1] for s in sequences])
y = np.array([s[-1] for s in sequences])

# Модель
model = tf.keras.Sequential([
    tf.keras.layers.Embedding(len(chars), 16),
    tf.keras.layers.SimpleRNN(32),
    tf.keras.layers.Dense(len(chars), activation='softmax')
])
model.compile(loss='sparse_categorical_crossentropy', optimizer='adam')
model.fit(X, y, epochs=50, verbose=0)

# Генерация нового текста
start = "To be or n"
for _ in range(20):
    inp = np.array([char2idx[c] for c in start[-seq_length:]]).reshape(1,-1)
    pred = model.predict(inp, verbose=0)[0]
    next_char = idx2char[np.random.choice(len(chars), p=pred)]
    start += next_char
print(start)
Пример вывода: "To be or not to be, that is the question..." (возможно, с ошибками из-за короткого обучения).

Написание нейросети на Python - comments

En
Python пишем нейросеть (python)