Здравствуйте, коллеги.
Надеемся еще до конца августа приступить к переводу небольшой, но поистине базовой книги о реализации возможностей ИИ на языке Python.
Господин Гифт, пожалуй, в дополнительной рекламе не нуждается (для любопытствующих — профиль мэтра на GitHub):
В предлагаемой сегодня статье будет коротко рассказано о библиотеке Ray, разработанной в Калифорнийском университете (Беркли) и упомянутой в книге Гифта мелким петитом. Надеемся, что в качестве раннего тизера — то, что надо. Добро пожаловать под кат
По мере развития алгоритмов и приемов машинного обучения, все больше и больше приложений для машинного обучения требуется запускать сразу на множестве машин, и они не могут обойтись без параллелизма. Однако инфраструктура для выполнения машинного обучения на кластерах по-прежнему формируется ситуативно. Сейчас уже существуют хорошие решения (например, серверы параметров или поиск гиперпараметров) и высококачественные распределенные системы (например, Spark или Hadoop), исходно создававшиеся не для работы с ИИ, но практикующие специалисты часто создают инфраструктуру для собственных распределенных систем с нуля. На это тратится масса лишних усилий.
В качестве примера рассмотрим концептуально простой алгоритм, скажем, Эволюционные стратегии для обучения с подкреплением. На псевдокоде этот алгоритм укладывается примерно в дюжину строк, и его реализация на Python немногим больше. Однако, для эффективного использования этого алгоритма на более крупной машине или кластере требуется значительно более сложная программная инженерия. В реализации этого алгоритма от авторов данной статьи – тысячи строк кода, здесь необходимо определять протоколы связи, стратегии сериализации и десериализации сообщений, а также различные способы обработки данных.
Одна из целей Ray — помочь специалисту-практику превратить алгоритм-прототип, запускаемый на ноутбуке, в высокопроизводительное распределенное приложение, эффективно работающее на кластере (или на отдельно взятой многоядерной машине), добавив относительно немногочисленные строки кода. Такой фреймворк должен по части производительности обладать всеми преимуществами системы, оптимизированной вручную, и не требовать, чтобы пользователь сам задумывался о планировании, передаче данных и машинных сбоях.
Свободный фреймворк для ИИ
Связь с другими фреймворками глубокого обучения: Ray полностью совместим с такими фреймворками глубокого обучения как TensorFlow, PyTorch и MXNet, поэтому во многих приложениях совершенно естественно использовать вместе с Ray один или более других фреймворков глубокого обучения (например, в наших библиотеках для обучения с подкреплением активно применяются TensorFlow и PyTorch).
Связь с другими распределенными системами: Сегодня используется много популярных распределенных систем, однако, большинство из них проектировалось без учета задач, связанных с ИИ, поэтому не обладают требуемой производительностью для поддержки ИИ и не имеют API для выражения прикладных аспектов ИИ. В современных распределенных системах отсутствуют (те или иные, в зависимости от системы) такие нужные возможности:
# Определяем две удаленные функции. При вызове этих функций создаются задачи,
# выполняемые удаленно.
@ray.remote
def multiply(x, y):
return np.dot(x, y)
@ray.remote
def zeros(size):
return np.zeros(size)
# Параллельно запускаем две задачи. Они сразу же возвращают футуры,
# и эти задачи выполняются в фоновом режиме.
x_id = zeros.remote((100, 100))
y_id = zeros.remote((100, 100))
# Запускаем третью задачу. Она не будет назначена, пока первые две задачи
# не завершатся.
z_id = multiply.remote(x_id, y_id)
# Получаем результат. Он останется заблокирован до тех пор, пока не завершится третья задача.
z = ray.get(z_id)
import gym
@ray.remote
class Simulator(object):
def __init__(self):
self.env = gym.make("Pong-v0")
self.env.reset()
def step(self, action):
return self.env.step(action)
# Создаем симулятор, он запускает удаленный процесс, который, в свою очередь,
# запустит все методы этого актора
simulator = Simulator.remote()
observations = []
for _ in range(4):
# Совершаем в симулятор действие 0. Этот вызов не приводит к блокировке
# и возвращает футуру
observations.append(simulator.step.remote(0))
@ray.remote
class ParameterServer(object):
def __init__(self, keys, values):
# Эти значения будут изменяться, поэтому необходимо создать локальную копию.
values = [value.copy() for value in values]
self.parameters = dict(zip(keys, values))
def get(self, keys):
return [self.parameters[key] for key in keys]
def update(self, keys, values):
# Эта функция обновления выполняет сложение с имеющимися значениями, но
# функцию обновления можно определять произвольно
for key, value in zip(keys, values):
self.parameters[key] += value
parameter_server = ParameterServer.remote(initial_keys, initial_values)
@ray.remote
def worker_task(parameter_server):
while True:
keys = ['key1', 'key2', 'key3']
# Получаем наиболее актуальные параметры
values = ray.get(parameter_server.get.remote(keys))
# Вычисляем некоторые обновления параметров
updates = …
# Обновляем параметры
parameter_server.update.remote(keys, updates)
# Запускаем 4 долгосрочные задачи
for _ in range(4):
worker_task.remote(parameter_server)
from ray.tune import register_trainable, grid_search, run_experiments
# Функция для оптимизации. Гиперпараметры находятся в аргументе config
def my_func(config, reporter):
import time, numpy as np
i = 0
while True:
reporter(timesteps_total=i, mean_accuracy=(i ** config['alpha']))
i += config['beta']
time.sleep(0.01)
register_trainable('my_func', my_func)
run_experiments({
'my_experiment': {
'run': 'my_func',
'resources': {'cpu': 1, 'gpu': 0},
'stop': {'mean_accuracy': 100},
'config': {
'alpha': grid_search([0.2, 0.4, 0.6]),
'beta': grid_search([1, 2]),
},
}
})
К сожалению, не доступен сервер mySQL