{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### ЛАБОРАТОРНАЯ РАБОТА №1.2\n",
"## ИЗУЧЕНИЕ ОСНОВНЫХ ПОНЯТИЙ ТЕОРИИ ИСКУССТВЕННЫХ НЕЙРОННЫХ СЕТЕЙ"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"> Цель работы: изучение основных понятий теории искусственных нейронных сетей на примере простых задач распознавания логических функций («И», «ИЛИ», «исключающее ИЛИ»)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Импорт библиотек:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "bvIkPEqTXcpG"
},
"outputs": [],
"source": [
"import numpy as np\n",
"import torch\n",
"import matplotlib.pyplot as plt\n",
"from IPython.display import clear_output\n",
"\n",
"from torch import nn\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В заключительной части данной лабораторной работы мы применяем PyTorch — современный фреймворк для научных вычислений и глубокого обучения в Python.\n",
"\n",
"PyTorch во многом напоминает NumPy по принципам работы и синтаксису:\n",
"- оперирует многомерными массивами (в PyTorch они называются *тензорами*, или *Tensors*), которые являются прямым аналогом `ndarray` из NumPy;\n",
"- поддерживает похожий синтаксис для базовых операций: индексация, срезы, арифметические действия;\n",
"- реализует векторизованные вычисления и механизм broadcasting (широковещательное сложение);\n",
"- позволяет выполнять стандартные математические операции с интуитивно понятными методами (например, `tensor.mean()` в PyTorch аналогичен `array.mean()` в NumPy).\n",
"\n",
"\n",
"Некоторые основные компоненты PyTorch:\n",
"\n",
"1. Тензоры (Tensors) \n",
" - многомерные массивы с поддержкой вычислений на GPU;\n",
" - аналог `numpy.ndarray`, но с расширенными возможностями для машинного обучения.\n",
"\n",
"\n",
"2. Автоматическое дифференцирование (Autograd) \n",
" - механизм для автоматического вычисления градиентов;\n",
" - критически важен для обучения нейронных сетей (реализует алгоритм обратного распространения ошибки). \n",
" \n",
"\n",
"3. Модули (nn.Module) \n",
" - базовые строительные блоки для создания нейронных сетей;\n",
" - включают слои, функции активации, функции потерь и др.\n",
"\n",
"\n",
"4. Оптимизаторы (optim) \n",
" - реализации популярных алгоритмов оптимизации: SGD, Adam, RMSprop и др.;\n",
" - упрощают обновление параметров модели.\n",
"\n",
"\n",
"Ключевые возможности PyTorch:\n",
"\n",
"- Создание и обучение нейронных сетей любой сложности — от простых перцептронов до трансформеров.\n",
"- Вычисления на CPU и GPU с минимальным изменением кода (достаточно переместить тензоры на устройство `cuda`).\n",
"- Динамические вычислительные графы — в отличие от статических графов в некоторых других фреймворках, PyTorch строит граф операций «на лету», что упрощает отладку и эксперименты.\n",
"- Гибкость в проектировании архитектур — легко создавать кастомные слои и модели, переопределять методы обратного прохода.\n",
"\n",
"\n",
"Преимущества для исследований и разработки:\n",
"\n",
"- Интуитивный интерфейс, близкий к NumPy — низкий порог входа для тех, кто знаком с NumPy.\n",
"- Гибкая система наследования — возможность создавать собственные модули и слои.\n",
"- Обширное сообщество — множество туториалов, примеров, библиотек и форумов.\n",
"- Совместимость с другими библиотеками — лёгкая интеграция с NumPy, SciPy, Matplotlib и др.\n",
"- Производительность — ускорение вычислений на GPU (в 10–100 раз по сравнению с CPU для крупных задач).\n",
"\n",
"\n",
"Официальная документация: https://pytorch.org/docs/stable/index.html"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В качестве примера вышесказанного переписанная на PyTorch метрика accuracy: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "l4lzUxFY0ej5"
},
"outputs": [],
"source": [
"def accuracy(y_pred, y_true):\n",
" return torch.sum(y_pred == y_true) / len(y_true)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Содержание: \n",
"[1. Решение задачи логического «И»](#p_1) \n",
"[2. Решение задачи логического «ИЛИ»](#p_2) \n",
"[3. Решение задачи логического «исключающего ИЛИ»](#p_3)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 1. Решение задачи логического «И»"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Представим входные данные для решения задачи логического «И» в виде тензора `X_data`.\n",
"\n",
"Операции в нейронных сетях (умножение весов, активация, вычисление градиентов) выполняются только с вещественными числами, поэтому через `.float()` приводим тензор к вещественному типу данных — иначе далее возможна ошибка типа данных."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "Ej0DmW9uXlG0",
"outputId": "b3821094-83d4-40f1-faa6-7773535b9ea6"
},
"outputs": [],
"source": [
"X_data = torch.tensor([[0, 0], [0, 1], [1, 0], [1, 1]]).float()\n",
"print(X_data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Аналогичная операция с выходным вектором:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "khRrzE2fXlR4",
"outputId": "a1aa980e-fa15-4c7c-ba68-18f0f5588f7f"
},
"outputs": [],
"source": [
"y_and_data = torch.tensor([0, 0, 0, 1]).reshape(-1, 1).float()\n",
"print(y_and_data)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Создание нейронной сети в PyTorch: последовательная модель**\n",
"\n",
"Один из самых простых и наглядных способов создать нейронную сеть в PyTorch — использовать `nn.Sequential`. Это контейнер, который организует слои в последовательный пайплайн: данные проходят через каждый слой по порядку, от входа к выходу — выход предыдущего слоя автоматически становится входом следующего.\n",
"\n",
"Создадим данным способом нейронную сеть `model_seq` с одним слоем нейронов.\n",
"\n",
"Пояснения к выбранным слоям в её архитектуре:\n",
" 1. `nn.Linear(in_features=2, out_features=1)` — полностью соединённый (плотный, полносвязный) слой. \n",
" \n",
" Параметры:\n",
" - `in_features=2` — размерность входного вектора (2 признака, соответствующие входам логической операции);\n",
" - `out_features=1` — размерность выхода (1 нейрон для итогового результата).\n",
" \n",
" Математическая операция: \n",
" $$\n",
" y = W \\cdot X + b,\n",
" $$ \n",
"\n",
" 2. `nn.Sigmoid()` — функция активации (сигмоида).\n",
" \n",
"После создания экземпляр `model_seq` можно:\n",
"- вызывать как функцию: `model_seq(X_data)` — прямой проход через сеть;\n",
"- получать параметры: `model_seq.parameters()` — для оптимизации;\n",
"- выводить структуру: печать `model_seq` покажет последовательность слоёв."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "gqr4pECOoDpG",
"outputId": "145244ca-2ede-498b-8a01-9841f6df041e"
},
"outputs": [],
"source": [
"model_seq = nn.Sequential(\n",
" nn.Linear(in_features=2, out_features=1),\n",
" nn.Sigmoid()\n",
")\n",
"\n",
"model_seq"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Переберём все обучаемые параметры сети `model_seq` — результатом будет список тензоров, содержащих исходные веса и смещения сети:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "32TRT1kv9_Ln",
"outputId": "49e48ed3-3909-46d6-ac66-c0b59d1b9a5b"
},
"outputs": [],
"source": [
"[x for x in model_seq.parameters()]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обратите внимание в выводе на флаг `requires_grad=True`.\n",
"\n",
"Он указывает, что для этого тензора в процессе обратного распространения ошибки нужно будет вычислять градиенты (производные) всех математических операций, через которые далее в коде этот тензор проходит. Без этого флага параметры не будут обновляться при обучении. Флаг при задании тензора также можно переключать на `False`.\n",
"\n",
"Как это работает:\n",
"\n",
" 1. Во время прямого прохода (`forward`) PyTorch строит вычислительный граф, запоминая операции с тензорами, у которых `requires_grad=True`.\n",
" 2. При вызове `loss.backward()` автоматически вычисляются градиенты по всем параметрам с `requires_grad=True`, при этом значение каждое градиенты сохраняются в атрибуте `.grad` тензора.\n",
" 3. Оптимизатор (объект, реализующий алгоритм обновления параметров модели на основе вычисленных градиентов — например, SGD) использует эти градиенты для обновления параметров."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Рассмотрим всё на примере.\n",
"\n",
"Выберем в качестве оптимизатора параметров `model_seq` SGD (с достаточно большим шагом обучения `lr` для наглядности) и среднеквадратичную функцию потерь:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "DMJYrTlE-VqS"
},
"outputs": [],
"source": [
"optimizer = torch.optim.SGD(model_seq.parameters(), lr=1.5)\n",
"criterion = nn.MSELoss()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Пропустим входные данные `X_data` через `model_seq`:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "5xiqGW-opJNK",
"outputId": "44183227-fe44-45f7-fb95-3dff575d702e"
},
"outputs": [],
"source": [
"z = model_seq(X_data)\n",
"z"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Атрибут `grad_fn=` в выводе обозначает:\n",
"- Тензор `z` — результат работы сигмоиды в последнем слое сети;\n",
"- PyTorch «запомнил» эту операцию в своём вычислительном графе;\n",
"- При обратном распространении ошибки градиенты будут корректно рассчитаны по формуле производной сигмоиды и переданы дальше в сеть."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Рассчитаем значение функции потерь:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "kn_XCMP8-fVm",
"outputId": "f5813ee6-a1f3-4b34-acee-77978ecf7b8f"
},
"outputs": [],
"source": [
"loss = criterion(z, y_and_data)\n",
"loss"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В атрибуте `grad_fn=` аналогично видно, что в вычислительном графе к тензорам применена функция среднеквадратичной ошибки.\n",
"\n",
"Вычислим градиенты функции потерь по всем параметрам модели согласно вычислительному графу:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "kWc5ip2O-wKp"
},
"outputs": [],
"source": [
"loss.backward()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Обновим с помошью оптимизатора все параметры сети: "
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "dxh8RIJV-1Hy"
},
"outputs": [],
"source": [
"optimizer.step()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Посмотрим значения обновлённых параметров:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "AQt5IglN_BJx",
"outputId": "b916e29e-874d-4396-a447-3556d5b5757e"
},
"outputs": [],
"source": [
"[x for x in model_seq.parameters()]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Метод `optimizer.zero_grad()` вызывается обязательно перед каждым последующим обратным проходом (`loss.backward()`) в цикле обучения для **обнуления градиентов всех параметров** модели, управляемых этим оптимизатором.\n",
"\n",
"Почему это необходимо? \n",
"\n",
"В PyTorch градиенты по умолчанию накапливаются (суммируются) при каждом вызове `loss.backward()`. Если не обнулять градиенты:\n",
"- значения градиентов будут расти с каждой итерацией;\n",
"- веса модели начнут обновляться некорректно (с учётом «старых» градиентов);\n",
"- возможен эффект «взрывных градиентов» (gradients explode), когда значения становятся настолько большими, что превращаются в `NaN` (не число)."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "KRD01eVD_yjE"
},
"outputs": [],
"source": [
"optimizer.zero_grad()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сделайте несколько проходов (итераций) от [первого шага обратного распространения ошибки](#loop_and) до данной ячейки. Убедитесь, что ошибка сети `loss` понижается."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Рассмотрим ещё один способ создания сети в PyTorch.\n",
"\n",
"**Создание нейронной сети в PyTorch: через ООП**\n",
"\n",
"В PyTorch принято определять архитектуры нейронных сетей как классы, наследующие от `nn.Module`. Это позволяет:\n",
"- структурировать код в виде повторно используемых компонентов;\n",
"- чётко разделять инициализацию параметров (`__init__`) и прямой проход (`forward`);\n",
"- легко расширять и модифицировать модели;\n",
"- использовать встроенные механизмы PyTorch (оптимизаторы, сохранение/загрузка моделей).\n",
"\n",
"Пример сети с одним полносвязным слоем и сигмоидой в качестве функции активации:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "PF5yli7WXlVd"
},
"outputs": [],
"source": [
"class OneLayerNetwork(nn.Module):\n",
" def __init__(self, n_inputs=2, n_outputs=1):\n",
" super().__init__()\n",
" self.model = nn.Sequential(\n",
" nn.Linear(in_features=n_inputs, out_features=n_outputs),\n",
" nn.Sigmoid()\n",
" )\n",
"\n",
" def forward(self, X):\n",
" return self.model(X)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Сейчас все слои для удобства по-прежнему собраны в `nn.Sequential`. Чтобы повысить гибкость модели, в методе `__init__` можно по отдельности задать все необходимые слои, а в `forward` — определять порядок их применения. Такой способ даёт больше контроля над архитектурой (пример разберём в одной из следующих лабораторных работ).\n",
"\n",
"Сигмоиду здесь можно также заменить на `nn.ReLU` или другую функцию активации — но для отделения от экземплятор с исходной архитектурой создайте другой класс (например, `OneLayerReLUNetwork()`)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Создадим экземпляр однослойной сети этого класса для решения задачи логического «И»:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "kIuQLzUIwVwC",
"outputId": "91aa25b7-aae4-4655-e83b-4abac88531c8"
},
"outputs": [],
"source": [
"model_one_layer = OneLayerNetwork()\n",
"model_one_layer"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"По аналогии с прошлым ноутбуком зададим \n",
" - данные для обучения (входные и выходные);\n",
" - экземпляр нейронной сети (через последовательность `nn.Sequential()` или класс `OneLayerNetwork()`);\n",
" - количество эпох или итераций в процессе обучения (желательно больше 5);\n",
" - скорость обучение и коэффициент импульса;\n",
" - оптимизатор (попробуйте разные алгоритмы — `torch.optim.SGD()`, `torch.optim.Adam()` и другие) (значение `learning_rate` передаётся в `lr`) (учтите, что в `torch.optim.Adam()` нет импульса);\n",
" - функцию потерь (можно оставить `nn.MSELoss()`, однако поскольку решается задача бинарной классификации, можно выбрать бинарную кросс-энтропию `nn.BCELoss()`).\n",
" \n",
" \n",
"*Примечание*. Вы можете использовать для обучения сети либо код ниже, либо модифицированный на его основе — например, реализовать функцию обучения нейронной сети и проверки её работы."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "p09jzhOY3MyQ"
},
"outputs": [],
"source": [
"y_true = y_and_data\n",
"\n",
"# Перебор seed для инициализации параметров\n",
"torch.manual_seed(seed=42)\n",
"\n",
"model = # Ваш код здесь\n",
"\n",
"epochs = # Ваш код здесь\n",
"\n",
"learning_rate = # Ваш код здесь\n",
"momentum = # Ваш код здесь\n",
"\n",
"optimizer = # Ваш код здесь\n",
"criterion = # Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"**Обучение нейронной сети для решения задачи логического «И»:**"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/",
"height": 556
},
"id": "qKimvoStsZXv",
"outputId": "725ec1a2-2d68-4f24-91c6-3469a39efbc4"
},
"outputs": [],
"source": [
"loss_history = []\n",
"\n",
"for epoch in range(epochs):\n",
" \n",
" # Метод .train() переводит модель в режим обучения\n",
" model.train()\n",
"\n",
" optimizer.zero_grad()\n",
"\n",
" z = model(X_data)\n",
" model_answer_interpretation = (z >= 0.5).float()\n",
"\n",
" loss = criterion(z, y_true)\n",
" \n",
" # Метод .item() извлекает скалярное значение из тензора loss\n",
" loss_history.append(loss.item())\n",
"\n",
" loss.backward()\n",
"\n",
" optimizer.step()\n",
" \n",
" # Метод .eval() переводит модель в режим валидации/тестирования (об этом в следующей лабораторной)\n",
" model.eval()\n",
"\n",
" if (epoch + 1) % 5 == 0:\n",
"\n",
" clear_output(True)\n",
" plt.plot(range(1, epoch+2), loss_history, label='Loss')\n",
" plt.title(f'Epoch: {epoch + 1}, Loss: {loss:.6f}')\n",
" plt.grid(True, alpha=0.3)\n",
" plt.legend(loc='best')\n",
" plt.show()\n",
"\n",
" print('Test:')\n",
" for i in range(len(X_data)):\n",
" # Метод .detach() создаёт копию тензора, отсоединённую от вычислительного графа,\n",
" # чтобы избежать ненужного вычисления градиентов для исходного тензора\n",
" print(f'Input: {X_data.numpy()[i]}, Output: {torch.round(z[i].detach() * 100).numpy() / 100}, Prediction: {model_answer_interpretation[i].numpy()}, True: {y_true[i].numpy()}')\n",
"\n",
" print(f'Accuracy: {accuracy(model_answer_interpretation, y_true):.2f}')"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Проверим качество обучения сети:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"assert accuracy(model_answer_interpretation, y_and_data) == 1\n",
"assert np.mean(loss_history[:5]) > np.mean(loss_history[-5:])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Поэкспериметируйте с параметрами обучения — сделайте несколько вариантов с разными функциями потерь, оптимизаторами, значениями скорости обучения и коэффициента импульса. Выберите лучшие по качеству обучения и количеству эпох."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 2. Решение задачи логического «ИЛИ»"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"По аналогии с задачей логического «И» решите задачу логического «ИЛИ».\n",
"\n",
"Выходные данные:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "UGFSsTGh4Xyp",
"outputId": "40e554c0-51a0-4adb-ca8b-8e46c83c2e7d"
},
"outputs": [],
"source": [
"y_or_data = torch.tensor([0, 1, 1, 1]).reshape(-1, 1).float()\n",
"print(y_or_data)"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Проверьте качество обучения сети:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"assert accuracy(model_answer_interpretation, y_or_data) == 1\n",
"assert np.mean(loss_history[:5]) > np.mean(loss_history[-5:])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Поэкспериметируйте с параметрами обучения — сделайте несколько вариантов с разными функциями потерь, оптимизаторами, значениями скорости обучения и коэффициента импульса. Выберите лучшие по качеству обучения и количеству эпох."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## 3. Решение задачи логического «исключающего ИЛИ»"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Выходные данные:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "gNigOR9N5X3z",
"outputId": "297e81ad-0eb7-403a-8dbf-0df7706c934e"
},
"outputs": [],
"source": [
"y_xor_data = torch.tensor([0, 1, 1, 0]).reshape(-1, 1).float()\n",
"print(y_xor_data)"
]
},
{
"cell_type": "markdown",
"metadata": {
"id": "6hL-mvyF5T58"
},
"source": [
"Напомним, что однослойной сетью задачу «исключающего ИЛИ» решить нельзя. В нейронную сеть требуется добавить ещё один слой с как минимум двумя нейронами.\n",
"\n",
"Модифицируем для этого класс `OneLayerNetwork()` в класс `TwoLayersNetwork()` — в последовательсти в `self.model` добавим ещё один полносвязный слой с сигмоидой для активации. Добавлен также параметр `n_hiddens` — количество нейронов в скрытом слое. Обратите внимание на задание размерности в последовательности слоёв."
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"id": "TGcgUAFQtXn7"
},
"outputs": [],
"source": [
"class TwoLayersNetwork(nn.Module):\n",
" def __init__(self, n_inputs=2, n_hiddens=2, n_outputs=1):\n",
" super().__init__()\n",
" self.model = nn.Sequential(\n",
" nn.Linear(in_features=n_inputs, out_features=n_hiddens),\n",
" nn.Sigmoid(),\n",
" nn.Linear(in_features=n_hiddens, out_features=n_outputs),\n",
" nn.Sigmoid()\n",
" )\n",
"\n",
" def forward(self, X):\n",
" return self.model(X)"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Создадим экземпляр двухслойной сети этого класса для решения задачи «исключающего ИЛИ»:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {
"colab": {
"base_uri": "https://localhost:8080/"
},
"id": "afK0vsG1t2oL",
"outputId": "bab9683b-fefe-4734-f948-340a353b99c8"
},
"outputs": [],
"source": [
"model_two_layers = TwoLayersNetwork()\n",
"model_two_layers"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"По аналогии с задачами логического «И» и логического «ИЛИ» решите «задачу исключающего ИЛИ»:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"# Ваш код здесь\n",
"\n",
"# Вариант задания сети с разным количество нейронов в скрытом слое\n",
"n_hiddens = 2\n",
"model = TwoLayersNetwork(n_hiddens=n_hiddens)\n",
"\n",
"# Ваш код здесь"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Проверьте качество обучения сети:"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": [
"assert accuracy(model_answer_interpretation, y_xor_data) == 1\n",
"assert np.mean(loss_history[:5]) > np.mean(loss_history[-5:])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Поэкспериметируйте с параметрами обучения — сделайте несколько вариантов с разными функциями потерь, оптимизаторами, значениями скорости обучения и коэффициента импульса. Выберите лучшие по качеству обучения и количеству эпох."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Литература:\n",
"1. Бородкин А.А., Елисеев В.Л. Основы и применение искусственных нейронных сетей. Сборник лабораторных работ: методическое пособие. – М.: Издательский дом МЭИ, 2017.\n",
"2. MachineLearning.ru — профессиональный информационно-аналитический ресурс, посвященный машинному обучению, распознаванию образов и интеллектуальному анализу данных: http://www.machinelearning.ru\n",
"3. Modern State of Artificial Intelligence — Online Masters program at MIPT: https://girafe.ai/"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
" "
]
}
],
"metadata": {
"colab": {
"provenance": []
},
"kernelspec": {
"display_name": "Python 3",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.7.3"
}
},
"nbformat": 4,
"nbformat_minor": 1
}