Скидки до 60% и 3 курса в подарок 0 дней 00 :00 :00 Выбрать курс
Код
#статьи

Основы PyTorch для Python-разработчика

Изучаем фреймворк и создаём простого голосового помощника.

Иллюстрация: Катя Павловская для Skillbox Media

В этой статье мы рассмотрим фреймворк PyTorch для машинного обучения. Torch — это научная вычислительная среда с поддержкой алгоритмов машинного обучения, которая ориентирована на использование графических процессоров (GPU) для ускорения вычислений. Мы начнём с базовой теории, а затем перейдём к практике: создадим голосового ассистента, который сможет распознавать речь и предоставлять актуальную информацию о погоде.

Хотя мы не будем подробно разбирать все возможности PyTorch, материал рассчитан не на полных новичков. Для понимания статьи вам нужно знать базовый синтаксис Python, уметь устанавливать библиотеки и запускать код.

Содержание


Кому и для чего нужен PyTorch

PyTorch — это фреймворк с открытым исходным кодом для создания и обучения нейронных сетей на Python. Его часто используют исследователи, специалисты по данным и разработчики ML-систем. Например, команда OpenAI использует PyTorch для разработки новых архитектур нейросетей, а инженеры Uber и Netflix — для создания своих рекомендательных систем.

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

Например, вы можете использовать модуль torchvision для распознавания изображений или библиотеку transformers для обработки текста. Такой подход значительно сокращает время разработки и избавляет от необходимости писать код с нуля. То есть вы можете сосредоточиться на задаче и не отвлекаться на настройку базовой инфраструктуры модели.

Если вы новичок в машинном обучении, то PyTorch можно представить как конструктор LEGO для создания моделей. В нём есть базовые «кубики» и готовые модули, которые можно легко комбинировать по инструкции или создавать собственные архитектуры. Кроме того, PyTorch позволяет менять «схему сборки» прямо во время работы: если определённая часть сети работает неэффективно, её можно модифицировать без перестройки всей модели.

А если вы уже работали с библиотекой NumPy, то PyTorch покажется вам во многом знакомым: в нём тоже можно выполнять привычные операции с данными и использовать похожий синтаксис. Например, операция вычисления среднего значения tensor.mean() в PyTorch по синтаксису и функциональности полностью аналогична array.mean() в NumPy.

Главное отличие в том, что PyTorch выполняет вычисления не только на процессоре (CPU), как NumPy, но и на графическом ускорителе (GPU). А это означает, что по сравнению с вычислениями только на CPU вы можете ускорить работу в 10–50 раз, особенно если речь идёт о тяжёлых задачах — например, при обработке видео, работе с большими объёмами данных и обучении моделей.

Как устроен PyTorch

Фреймворк PyTorch основан на нескольких ключевых компонентах — тензорах, вычислительных графах и механизме автоматического дифференцирования. Эти компоненты работают в связке, и их можно представить как фабрику: тензоры — это сырьё (данные), вычислительный граф — чертёж и конвейер обработки, а автоматическое дифференцирование — система контроля качества, которая определяет, что нужно изменить для улучшения результата.

Тензоры — это многомерные массивы данных, которые оптимизированы для параллельных вычислений на GPU и могут иметь любое количество измерений. Например, одномерный тензор — это вектор [1, 2, 3], двухмерный — матрица [[1, 2], [3, 4]], а трёхмерный — «куб» данных [[[1, 2], [3, 4]], [[5, 6], [7, 8]]]. Для удобства представляйте тензор как таблицу чисел, которую можно расширять в длину, ширину и глубину.

Вычислительные графы — архитектурная схема, которая отображает последовательность и взаимосвязь операций над данными. В такой схеме узлы представляют различные математические операции, а рёбра — потоки данных-тензоров. Этот подход позволяет наглядно проследить, как данные трансформируются от входного слоя нейросети до финального результата.

Например, выражение c = a + b в PyTorch можно представить как небольшой граф: два входа с данными (a и b) подключаются к узлу операции «сложение», а результат (c) идёт на выход. Такая схема позволяет фреймворку отслеживать порядок и взаимосвязь всех операций. Поэтому, если вы измените входные данные или захотите пересчитать результат, PyTorch просто повторит те же шаги и выдаст обновлённый ответ.

Механизм автоматического дифференцирования — это встроенная в PyTorch система, которая автоматически вычисляет, как меняются выходные значения модели при изменении её параметров. Эти изменения называют градиентами. Благодаря этому механизму нейросеть сама определяет, какие параметры и как нужно скорректировать для улучшения результата — программисту при этом не нужно вручную считать сложные производные.

К примеру, если нейросеть для распознавания изображений перепутала кошку с собакой, этот механизм рассчитает веса нейронов и то, насколько нужно их изменить, чтобы в следующий раз повысить точность распознавания.

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

  • Преобразование звука в данные — аудиосигнал конвертируется в спектрограммы и последовательности численных значений (тензоров), которые отражают частотные и временные характеристики речи.
  • Обработка в вычислительном графе — тензоры проходят через цепочку операций: сначала из них извлекаются звуковые признаки, затем происходит распознавание слов, а в конце формируется ответ.
  • Анализ ошибки — если модель распознала речь неправильно, PyTorch вычисляет, какие параметры (веса) необходимо скорректировать.
  • Обновление модели — PyTorch корректирует параметры модели, чтобы повысить точность распознавания при следующих попытках.

Благодаря такому взаимодействию компонентов модель может постепенно обучаться и точнее распознавать речь. Переходим к сборке нашего ассистента.

Создаём голосового помощника на Python и PyTorch

В этом разделе мы поработаем с API, подключим внешние библиотеки и напишем несколько функций для запуска голосового ассистента. Это будет простая программа, но вы можете доработать её и добавить функции, которые сочтёте полезными. Например, в нашей версии ассистент не умеет включать музыку, однако вы можете это исправить или реализовать другую команду.

Подготовка

Перед написанием кода перейдите на сайт openweathermap.org, где собраны данные о погоде по всему миру. Мы будем использовать его API, чтобы голосовой помощник мог отвечать на вопрос «Какая сейчас погода?» в заданном городе. При желании вы можете выбрать другой похожий ресурс.

После регистрации на сайте зайдите в личный кабинет, найдите раздел «My API Keys» и скопируйте сгенерированный ключ — это строка из букв и цифр:

Пример API-ключа в личном кабинете сервиса OpenWeatherMap. Обратите внимание: после регистрации активация вашего API-ключа может занять несколько часов
Скриншот: OpenWeatherMap / Skillbox Media

Полученный API-ключ необходимо сохранить в переменной окружения WEATHER_API_KEY. Переменную окружения можно создать временно для текущей сессии терминала или постоянно. Для учебного проекта достаточно временного варианта, поэтому введите в Windows PowerShell две команды:

# Устанавливаем переменную окружения только для текущей сессии
$env:WEATHER_API_KEY="ВАШ_КЛЮЧ"

# Проверяем, что ключ установлен  
echo $env:WEATHER_API_KEY

# Если ключ успешно сохранён, в ответ отобразится введённое значение — ваш API-ключ

По-хорошему, на подготовительном этапе нам следовало бы обучить модель с нуля, чтобы она адаптировалась именно под наши задачи. Однако этот процесс требует времени, значительных вычислительных ресурсов и крупных наборов размеченных аудиозаписей. Чтобы упростить задачу, мы используем готовую модель распознавания речи Wav2Vec 2.0 в русской версии — jonatasgrosman/wav2vec2-large-xlsr-53-russian с платформы Hugging Face.

Устанавливаем зависимости и формируем проект

Для работы нам понадобится несколько внешних библиотек, которые можно установить одной командой:

pip install torch torchaudio transformers pyaudio pyttsx3 requests numpy

Кратко разбираемся, что и для чего нужно:

  • PyTorch — для запуска и обработки нейросети,
  • Torchaudio — для работы со звуковыми файлами (ресемплинга),
  • Transformers — для загрузки предобученной модели Wav2Vec 2.0,
  • PyAudio — для записи звука с микрофона,
  • pyttsx3 — для синтеза речи (озвучивания),
  • Requests — для выполнения HTTP-запросов к погодному API,
  • NumPy — для работы с аудиоданными при чтении WAV.

Для работы будем использовать редактор VS Code, но вы можете выбрать любой другой. Создайте папку для проекта и как-то её назовите — например, voice_assistant. Внутри этой папки создайте файл с расширением .py — у нас это будет assistant.py. Дополнительно вы можете создать виртуальное окружение, чтобы изолировать зависимости проекта.

Если что-то не работает, убедитесь, что у вас на компьютере установлена актуальная версия Python (3.8 или выше). Проверить это можно командой:

python --version

Пишем код и запускаем голосового помощника

Сначала мы импортируем библиотеки для работы со звуком, нейросетью и выполнения интернет-запросов. После этого загрузим модель Wav2Vec 2.0, которая сможет преобразовать записанное с микрофона аудио в текст.

Дальше мы создадим несколько функций: одна будет записывать звук, вторая — преобразовывать его в текст, третья — получать прогноз погоды, а четвёртая — озвучивать ответ. Также у нас будет отдельная функция для обработки команд: она анализирует распознанный текст и определяет, что сделать — ответить приветствием, сообщить погоду или сообщить, что запрос не понят.

Вся логика работает в бесконечном цикле: после запуска ассистент ждёт, когда вы нажмёте Enter, затем записывает произнесённую фразу, преобразует её в текст, анализирует команду, озвучивает ответ и прописывает его текстом.

import os
import wave
import requests
import numpy as np
import torch
import torchaudio
import pyaudio
import pyttsx3
from transformers import Wav2Vec2ForCTC, Wav2Vec2Processor

# Название нашей модели и настройки
MODEL_NAME = "jonatasgrosman/wav2vec2-large-xlsr-53-russian"
current_location = "Москва"  # Город по умолчанию
DEVICE = torch.device("cuda" if torch.cuda.is_available() else "cpu")

# Загружаем процессор и модель распознавания речи
processor = Wav2Vec2Processor.from_pretrained(MODEL_NAME)
model = Wav2Vec2ForCTC.from_pretrained(MODEL_NAME).to(DEVICE)
model.eval()

# Добавляем запись аудио с микрофона в файл
def record_audio(filename: str, duration: int = 5, sample_rate: int = 16000) -> None:
    p = pyaudio.PyAudio()
    stream = p.open(format=pyaudio.paInt16, channels=1, rate=sample_rate, input=True, frames_per_buffer=1024)
    print("Запись началась...")
    frames = [stream.read(1024) for _ in range(int(sample_rate / 1024 * duration))]
    print("Запись завершена.")
    stream.stop_stream()
    stream.close()
    p.terminate()

    # Сохраняем аудиоданные в WAV
    with wave.open(filename, "wb") as wf:
        wf.setnchannels(1)
        wf.setsampwidth(p.get_sample_size(pyaudio.paInt16))
        wf.setframerate(sample_rate)
        wf.writeframes(b"".join(frames))

# Настраиваем распознавание речи из WAV-файла
def transcribe_audio(filename: str) -> str:
    try:
        with wave.open(filename, "rb") as wf:
            n_channels = wf.getnchannels()
            sampwidth = wf.getsampwidth()
            sr = wf.getframerate()
            n_frames = wf.getnframes()
            raw = wf.readframes(n_frames)
    except (wave.Error, FileNotFoundError):
        return ""

    if n_channels != 1 or sampwidth != 2:
        return ""

    # Преобразуем в float32 [-1, 1]
    audio = np.frombuffer(raw, dtype=np.int16).astype(np.float32) / 32768.0

    # Проводим ресемплинг до 16 кГц, если нужно
    if sr != 16000:
        tensor = torch.from_numpy(audio).unsqueeze(0)
        tensor = torchaudio.functional.resample(tensor, orig_freq=sr, new_freq=16000)
        audio = tensor.squeeze(0).numpy()
        sr = 16000

    # Запускаем модель для получения текста
    inputs = processor(audio, sampling_rate=sr, return_tensors="pt", padding=True)
    input_values = inputs.input_values.to(DEVICE)
    attention_mask = inputs.attention_mask.to(DEVICE) if "attention_mask" in inputs else None
    with torch.no_grad():
        logits = model(input_values, attention_mask=attention_mask).logits
    ids = torch.argmax(logits, dim=-1)
    return processor.batch_decode(ids)[0].strip()

# Получаем прогноз погоды по API
def get_weather_text(city: str) -> str:
    api_key = os.environ.get("WEATHER_API_KEY")
    if not api_key:
        return "API-ключ не найден. Установите переменную окружения WEATHER_API_KEY."
    url = "https://api.openweathermap.org/data/2.5/weather"
    params = {"q": city, "appid": api_key, "lang": "ru", "units": "metric"}
    try:
        r = requests.get(url, params=params, timeout=10)
        data = r.json()
        if data.get("cod") == 200:
            desc = data["weather"][0]["description"]
            temp = data["main"]["temp"]
            return f"Сейчас в {city} {desc}, температура {temp}°C."
        msg = data.get("message") or "Не удалось получить данные."
        return f"Не удалось найти погоду для {city}. {msg}"
    except requests.RequestException:
        return "Не удалось получить данные о погоде."

# Добавляем синтез речи (озвучку)
def speak(text: str) -> None:
    engine = pyttsx3.init()
    engine.say(text)
    engine.runAndWait()

# Настраиваем обработку пользовательских команд
def process_command(command: str) -> str:
    global current_location
    cmd = command.lower().strip()

    if not cmd:
        return "Не расслышал команду. Повторите, пожалуйста."

    if "установить местоположение" in cmd:
        city = cmd.split("установить местоположение", 1)[-1].strip().title()
        if city:
            current_location = city
            return f"Местоположение установлено на {city}."
        return "Не понял город. Скажите: 'установить местоположение <город>'."

    if "какая погода" in cmd or "погода" in cmd:
        return get_weather_text(current_location)

    if "привет" in cmd:
        return "Привет!"

    if "включи музыку" in cmd:
        return "Включаю музыку. (Демо.)"

    return "Извините, я не понял команду."

# Формируем основной цикл работы ассистента
def main():
    speak(f"Голосовой помощник запущен. Текущее местоположение: {current_location}.")
    print("Нажмите Enter, чтобы начать запись...")
    while True:
        input()  # ждём нажатия Enter
        record_audio("command.wav")  # записываем речь
        text = transcribe_audio("command.wav")  # распознаём
        print("Вы сказали:", text if text else "(пусто)")
        answer = process_command(text)  # получаем ответ
        print("Ответ:", answer)
        speak(answer)  # озвучиваем ответ

if __name__ == "__main__":
    main()

Чтобы запустить голосового помощника, откройте терминал внутри редактора и выполните команду с указанием имени файла:

python assistant.py

Подождите около 20 секунд, пока ассистент загрузит модель и поприветствует вас. После этого нажмите Enter и попробуйте с ним пообщаться. Иногда при запросе погоды ассистент может не обнаружить API-ключ. В таком случае убедитесь, что терминал открыт и сессия всё ещё активна. Попробуйте перезапустить редактор. Если это не поможет, введите ключ прямо в терминале редактора и затем снова запустите голосового ассистента.

Пример работы голосового ассистента на Python. На команду «Привет!» помощник отвечает «Привет!», на «Включи музыку» — «Включаю музыку», но не включает её, так как это лишь демонстрация. На запрос «Какая погода?» он сообщает погоду в Москве
Скриншот: Visual Studio Code / Skillbox Media

Больше интересного про код — в нашем телеграм-канале. Подписывайтесь!



Нейросети. Практический курс

20 инструментов для видео, графики, текста и аудио в одном курсе. Получите бесплатный доступ и начните осваивать топовые нейросети.

Начать бесплатно →

Учитесь бесплатно: «Нейросети. Практический курс» Получить доступ
Понравилась статья?
Да

Пользуясь нашим сайтом, вы соглашаетесь с тем, что мы используем cookies 🍪

Ссылка скопирована