[Документация Yandex Cloud](../../index.md) > [Yandex Cloud Functions](../index.md) > [Практические руководства](index.md) > Рабочие процессы и автоматизация на Serverless > Запуск вычислений в DataSphere с помощью API

# Запуск вычислений в Yandex DataSphere с помощью API


{% note warning %}

Часть ресурсов, необходимых для прохождения практического руководства, доступны только в [регионе Россия](../../overview/concepts/region.md).

{% endnote %}


В [Yandex DataSphere](https://datasphere.yandex.cloud) с помощью API можно запускать исполнение кода, не заходя в проект. Это может быть полезно, если нужно автоматизировать рутинные операции, дообучить нейросеть или развернуть сервис, который не требует быстрого ответа по API.

В практическом руководстве на примере простой сверточной нейронной сети [CNN](https://ru.wikipedia.org/wiki/Свёрточная_нейронная_сеть) показано, как организовать эксплуатацию модели, обученной в DataSphere, с помощью [Yandex Cloud Functions](../index.md). Результат работы модели будет записываться в хранилище проекта DataSphere.

Если вы хотите развернуть сервис, который будет возвращать результаты по API, обратитесь к руководству [Развертывание сервиса на основе Docker-образа с FastAPI](../../datasphere/tutorials/node-from-docker-fast-api.md).

1. [Подготовьте инфраструктуру](#infra).
1. [Подготовьте ноутбуки](#set-notebooks).
1. [Обучите нейросеть](#ai-training).
1. [Загрузите архитектуру модели и веса](#load-data).
1. [Создайте Cloud Functions](#create-function).

Если созданные ресурсы вам больше не нужны, [удалите их](#clear-out).

## Перед началом работы {#before-you-begin}

Перед началом работы нужно зарегистрироваться в Yandex Cloud, настроить [сообщество](../../datasphere/concepts/community.md) и привязать к нему [платежный аккаунт](../../billing/concepts/billing-account.md):
1. [На главной странице DataSphere](https://datasphere.yandex.cloud) нажмите **Попробовать бесплатно** и выберите аккаунт для входа — Яндекс ID или рабочий аккаунт в федерации (SSO).
1. Выберите [организацию Yandex Identity Hub](../../organization/index.md), в которой вы будете работать в Yandex Cloud.
1. [Создайте сообщество](../../datasphere/operations/community/create.md).
1. [Привяжите платежный аккаунт](../../datasphere/operations/community/link-ba.md) к сообществу DataSphere, в котором вы будете работать. Убедитесь, что у вас подключен платежный аккаунт, и он находится в [статусе](../../billing/concepts/billing-account-statuses.md) `ACTIVE` или `TRIAL_ACTIVE`. Если платежного аккаунта нет, создайте его в интерфейсе DataSphere.

### Необходимые платные ресурсы {#paid-resources}

В стоимость реализации регулярных запусков входят:

* плата за использование [вычислительных ресурсов DataSphere](../../datasphere/pricing.md);
* плата за количество вызовов функции [Cloud Functions](../pricing.md).

## Подготовьте инфраструктуру {#infra}

Войдите в [консоль управления](https://console.yandex.cloud) Yandex Cloud и выберите организацию, в которой вы работаете с DataSphere. На странице [**Yandex Cloud Billing**](https://center.yandex.cloud/billing/accounts) убедитесь, что у вас подключен платежный аккаунт.

Если у вас есть активный платежный аккаунт, на [странице облака](https://console.yandex.cloud/cloud) вы можете создать или выбрать каталог, в котором будет работать ваша инфраструктура.

{% note info %}

Если вы работаете с Yandex Cloud через [федерацию удостоверений](../../organization/concepts/add-federation.md), вам может быть недоступна платежная информация. В этом случае обратитесь к администратору вашей организации в Yandex Cloud.

{% endnote %}

### Создайте каталог {#create-folder}

{% list tabs group=instructions %}

- Консоль управления {#console}

   1. В [консоли управления](https://console.yandex.cloud) выберите облако и нажмите кнопку ![create](../../_assets/console-icons/plus.svg) **Создать каталог**.
   1. Введите имя каталога, например, `data-folder`.
   1. Нажмите кнопку **Создать**.

{% endlist %}

### Создайте сервисный аккаунт для проекта DataSphere {#create-sa}

Для доступа к проекту DataSphere из функции Cloud Functions вам понадобится [сервисный аккаунт](../../iam/concepts/users/service-accounts.md) с ролью `datasphere.community-projects.editor`.

{% list tabs group=instructions %}

- Консоль управления {#console}

   1. В [консоли управления](https://console.yandex.cloud) перейдите в каталог `data-folder`.
   1. [Перейдите]( ../../console/operations/select-service.md#select-service) в сервис **Identity and Access Management**.
   1. Нажмите кнопку **Создать сервисный аккаунт**.
   1. Введите имя сервисного аккаунта, например, `datasphere-sa`.
   1. Нажмите **Добавить роль** и назначьте сервисному аккаунту роль `datasphere.community-projects.editor`.
   1. Нажмите кнопку **Создать**.

{% endlist %}

### Добавьте сервисный аккаунт в проект {#sa-to-project}

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

1. Выберите нужный проект в своем сообществе или на [главной странице](https://datasphere.yandex.cloud) DataSphere во вкладке **Недавние проекты**.
1. На вкладке **Участники** нажмите **Добавить участника**.
1. Выберите аккаунт `datasphere-sa` и нажмите **Добавить**.

## Подготовьте ноутбуки и архитектуру нейросети {#set-notebooks}

Склонируйте Git-репозиторий, в котором находятся ноутбуки с примерами обучения и тестирования [модели машинного обучения](../../glossary/ml-models.md):
   1. В верхнем меню нажмите **Git** и выберите **Clone**.
   1. В открывшемся окне введите URI репозитория `https://github.com/yandex-cloud-examples/yc-datasphere-batch-execution.git` и нажмите кнопку **Clone**.
   
   Дождитесь окончания клонирования, это может занять некоторое время. Папка cклонированного репозитория появится в разделе ![folder](../../_assets/datasphere/jupyterlab/folder.svg) **File Browser**.

В репозитории содержатся два ноутбука и архитектура нейросети:

* `train_classifier.ipynb` — для скачивания обучающей выборки датасета `CIFAR10` и обучения простой нейронной сети;
* `test_classifier.ipynb` — для тестирования модели;
* `my_nn_model.py` — архитектура нейросети. Для классификации на вход нейросети подаются трехканальные изображения. Она содержит два сверточных слоя с `maxpool` слоем между ними и три линейных слоя:

    ```python
    import torch.nn as nn
    import torch.nn.functional as F
    import torch

    class Net(nn.Module):
        def __init__(self):
            super().__init__()
            self.conv1 = nn.Conv2d(3, 6, 5)
            self.pool = nn.MaxPool2d(2, 2)
            self.conv2 = nn.Conv2d(6, 16, 5)
            self.fc1 = nn.Linear(16 * 5 * 5, 120)
            self.fc2 = nn.Linear(120, 84)
            self.fc3 = nn.Linear(84, 10)

        def forward(self, x):
            x = self.pool(F.relu(self.conv1(x)))
            x = self.pool(F.relu(self.conv2(x)))
            x = torch.flatten(x, 1) # flatten all dimensions except batch
            x = F.relu(self.fc1(x))
            x = F.relu(self.fc2(x))
            x = self.fc3(x)
            return x
    ```

## Обучите нейросеть {#ai-training}

В ноутбуке `train_classifier.ipynb` вы скачаете обучающую выборку датасета `CIFAR10` и обучите простую нейронную сеть. Веса обученной модели сохраняются в хранилище проекта под названием `cifar_net.pth`.

1. Откройте проект DataSphere:
   
   1. Выберите нужный проект в своем сообществе или на [главной странице](https://datasphere.yandex.cloud) DataSphere во вкладке **Недавние проекты**.
   1. Нажмите кнопку **Открыть проект в JupyterLab** и дождитесь окончания загрузки.
   1. Откройте вкладку с ноутбуком.

1. Импортируйте библиотеки, необходимые для обучения модели:

    ```python
    import torch
    import torchvision
    import torchvision.transforms as transforms
    import torch.optim as optim
    from my_nn_model import Net
    ```

1. Загрузите датасет `CIFAR10` для обучения модели. Изображения в датасете относятся к 10 категориям:

    ```python
    transform = transforms.Compose(
        [transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    batch_size = 4

    trainset = torchvision.datasets.CIFAR10(root='./data', train=True,
                                            download=True, transform=transform)
    trainloader = torch.utils.data.DataLoader(trainset, batch_size=batch_size,
                                            shuffle=True, num_workers=2)

    classes = ('plane', 'car', 'bird', 'cat',
            'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    ```

1. Выведите на экран примеры изображений, которые содержатся в датасете:

    ```python
    import matplotlib.pyplot as plt
    import numpy as np

    def imshow(img):
        img = img / 2 + 0.5     # unnormalize
        npimg = img.numpy()
        plt.imshow(np.transpose(npimg, (1, 2, 0)))
        plt.show()

    dataiter = iter(trainloader)
    images, labels = next(dataiter)
    imshow(torchvision.utils.make_grid(images))
    print(' '.join(f'{classes[labels[j]]:5s}' for j in range(batch_size)))
    ```

1. Создайте функцию потерь и оптимизатор, необходимые для обучения нейросети:

    ```python
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    net = Net()
    net.to(device)

    criterion = nn.CrossEntropyLoss()
    optimizer = optim.SGD(net.parameters(), lr=0.001, momentum=0.9)
    ```

1. Запустите процесс обучения на 5 эпохах: 

    ```python
    for epoch in range(5): 
        running_loss = 0.0
        for i, data in enumerate(trainloader, 0):
            inputs, labels = data[0].to(device), data[1].to(device)

            optimizer.zero_grad()

            outputs = net(inputs)
            loss = criterion(outputs, labels)
            loss.backward()
            optimizer.step()

            running_loss += loss.item()
            if i % 2000 == 1999:
                print(f'[{epoch + 1}, {i + 1:5d}] loss: {running_loss / 2000:.3f}')
                running_loss = 0.0

    print('Finished Training')
    ```

1. Сохраните полученную модель на проектный диск:

    ```python
    torch.save(net.state_dict(), './cifar_net.pth')
    ```

## Загрузите архитектуру модели и веса {#load-data}

В ноутбуке `test_classifier.ipynb` вы загрузите архитектуру модели и веса, созданные во время работы файла [`train_classifier.ipynb`](#ai-training). Загруженная модель используется для прогнозов на тестовой выборке. Результаты прогноза сохраняются в файле `test_predictions.csv`.

1. Откройте проект DataSphere:
   
   1. Выберите нужный проект в своем сообществе или на [главной странице](https://datasphere.yandex.cloud) DataSphere во вкладке **Недавние проекты**.
   1. Нажмите кнопку **Открыть проект в JupyterLab** и дождитесь окончания загрузки.
   1. Откройте вкладку с ноутбуком.

1. Импортируйте библиотеки, необходимые для работы с моделью и создания прогнозов:

    ```python
    import torch
    import torchvision
    import torchvision.transforms as transforms
    from my_nn_model import Net
    import pandas as pd
    ```

1. Подготовьте объекты, которые позволят обращаться к тестовой выборке:

    ```python
    transform = transforms.Compose(
        [transforms.ToTensor(),
        transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5))])

    batch_size = 4

    testset = torchvision.datasets.CIFAR10(root='./data', train=False,
                                        download=True, transform=transform)
    testloader = torch.utils.data.DataLoader(testset, batch_size=batch_size,
                                            shuffle=False, num_workers=2)

    classes = ('plane', 'car', 'bird', 'cat',
            'deer', 'dog', 'frog', 'horse', 'ship', 'truck')
    ```

1. Определите конфигурацию ресурсов, на которой будет выполняться модель — СPU или GPU:

    ```python
    device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
    ```

1. Загрузите веса обученной модели и сделайте прогнозы на тестовой выборке:

    ```python
    net = Net()
    net.to(device)
    net.load_state_dict(torch.load('./cifar_net.pth'))

    predictions = []
    predicted_labels = []
    with torch.no_grad():
        for data in testloader:
            images, labels = data[0].to(device), data[1].to(device)
            outputs = net(images)
            _, predicted = torch.max(outputs.data, 1)
            predictions.append(predicted.tolist())
            predicted_labels.append([classes[predicted[j]] for j in range(batch_size)])
    ```

1. Сохраните прогнозы в формате `pandas.DataFrame`:

    ```python
    final_pred = pd.DataFrame({'class_idx': [item for sublist in predictions for item in sublist],
                               'class': [item for sublist in predicted_labels for item in sublist]})
    ```

1. Сохраните прогнозы модели в файл:

    ```python
    final_pred.to_csv('/home/jupyter/datasphere/project/test_predictions.csv')
    ```

## Создайте Cloud Functions {#create-function}

Чтобы запускать исполнение ячеек, не открывая JupyterLab, вам понадобится Cloud Functions, которая будет инициировать запуск вычислений в ноутбуке по API.

{% list tabs group=instructions %}

- Консоль управления {#console}

    1. В [консоли управления](https://console.yandex.cloud) перейдите в каталог, в котором хотите создать функцию.
    1. [Перейдите]( ../../console/operations/select-service.md#select-service) в сервис **Cloud Functions**.
    1. Нажмите кнопку **Создать функцию**.
    1. Введите имя функции, например, `ai-function`.
    1. Нажмите кнопку **Создать функцию**.

{% endlist %}

### Создайте версию Cloud Functions {#create-function-ver}

[Версия](../concepts/function.md#version) содержит код функции, параметры запуска и все необходимые зависимости.

{% list tabs group=instructions %}

- Консоль управления {#console}

    1. В [консоли управления](https://console.yandex.cloud) перейдите в каталог, в котором находится функция.
    1. [Перейдите]( ../../console/operations/select-service.md#select-service) в сервис **Cloud Functions**.
    1. Выберите функцию, версию которой хотите создать.
    1. В разделе **Последняя версия** нажмите кнопку **Создать в редакторе**.
    1. Выберите среду выполнения **Python**. Не выбирайте опцию **Добавить файлы с примерами кода**.
    1. Выберите способ **Редактор кода**.
    1. Нажмите **Создать файл** и введите имя файла, например `index`.
    1. Введите код функции, подставив идентификатор вашего проекта и абсолютный путь к ноутбуку в проекте:
    
        ```python
        import requests
    
        def handler(event, context):

            url = 'https://datasphere.api.cloud.yandex.net/datasphere/v2/projects/<идентификатор_проекта>:execute'
            body = {"notebookId": "/home/jupyter/datasphere/project/test_classifier.ipynb"}
            headers = {"Content-Type" : "application/json",
                       "Authorization": "Bearer {}".format(context.token['access_token'])}
            resp = requests.post(url, json = body, headers=headers)

            return {
            'body': resp.json(),
            }
        ```

       Где:
       * `<идентификатор_проекта>` — идентификатор проекта DataSphere, который расположен на странице проекта под названием.
       * `notebookId` — абсолютный путь к ноутбуку в проекте.

    1. В блоке **Параметры** задайте параметры версии:
       * **Точка входа**: `index.handler`.
       * **Сервисный аккаунт**: `datasphere-sa`.
    1. В правом верхнем углу нажмите **Сохранить изменения**.

{% endlist %}

## Как удалить созданные ресурсы {#clear-out}

Чтобы перестать платить за созданные ресурсы:
* [Удалите](../operations/function/function-delete.md) функцию.
* [Удалите](../../datasphere/operations/projects/delete.md) проект.