Привет, Хаброжители! Мы недавно сдали в типографию книгу Эндрю Траска (Andrew W. Trask), закладывающую фундамент для дальнейшего овладения технологией глубокого обучения. Она начинается с описания основ нейронных сетей и затем подробно рассматривает дополнительные уровни и архитектуры.
Предлагаем на обзорно ознакомится с отрывком «Федеративное обучение»
Идея федеративного обучения зародилась из того, что многие данные, содержащие полезную информацию для решения задач (например, для диагностики онкологических заболеваний с использованием МРТ), трудно получить в количествах, достаточных для обучения мощной модели глубокого обучения. Кроме полезной информации, необходимой для обучения модели, наборы данных содержат также другие сведения, не имеющие отношения к решаемой задаче, но их раскрытие кому-либо потенциально может нанести вред.
Федеративное обучение — это методика заключения модели в защищенную среду и ее обучение без перемещения данных куда-либо. Рассмотрим пример.
Допустим, нам нужно обучить модель определять спам по электронным письмам людей
В данном случае мы говорим о классификации электронной почты. Нашу первую модель мы обучим на общедоступном наборе данных с названием Enron. Это огромный корпус электронных писем, опубликованных в ходе слушаний по делу компании Enron (теперь это стандартный аналитический корпус электронной почты). Интересный факт: я был знаком с людьми, которым по роду своей деятельности приходилось читать/комментировать этот набор данных, и они отмечают, что люди посылали друг другу в этих письмах самую разную информацию (часто очень личную). Но так как этот корпус был обнародован в ходе судебных разбирательств, в настоящее время его можно использовать без ограничений.
Код в предыдущем и в этом разделе реализует только подготовительные операции. Файлы с входными данными (ham.txt и spam.txt) доступны на веб-странице книги: www.manning.com/books/grokking-deep-learning и в репозитории GitHub: github.com/iamtrask/Grokking-Deep-Learning. Мы должны предварительно обработать его, чтобы подготовить его для передачи в класс Embedding из главы 13, где мы создали свой фреймворк глубокого обучения. Как и прежде, все слова в этом корпусе преобразуются в списки индексов. Кроме того, мы приводим все письма к одинаковой длине в 500 слов, либо обрезая их, либо дополняя лексемами . Благодаря этому мы получаем набор данных прямоугольной формы.
Определив вспомогательные функции train() и test(), мы можем инициализировать нейронную сеть и обучить ее, написав всего несколько строк кода. Уже после трех итераций сеть оказывается в состоянии классифицировать контрольный набор данных с точностью 99.45 % (контрольный набор данных хорошо сбалансирован, поэтому этот результат можно считать превосходным):
Выше было выполнено самое обычное глубокое обучение. Теперь добавим конфиденциальности
В предыдущем разделе мы реализовали пример анализа электронной почты. Теперь поместим все электронные письма в одно место. Это старый добрый метод работы (который все еще широко используется во всем мире). Для начала сымитируем окружение федеративного обучения, в котором имеется несколько разных коллекций писем:
Пока ничего сложного. Теперь мы можем выполнить ту же процедуру обучения, что и прежде, но уже на трех отдельных наборах данных. После каждой итерации мы будем усреднять значения в моделях Боба (Bob), Алисы (Alice) и Сью (Sue) и оценивать результаты. Обратите внимание, что некоторые методы федеративного обучения предусматривают объединение после каждого пакета (или коллекции пакетов); я же решил сохранить код максимально простым:
Ниже дан фрагмент с результатами. Эта модель достигла практически того же уровня точности, что и предыдущая, и теоретически у нас отсутствовал доступ к обучающим данным — или нет? Как бы там ни было, но каждый человек изменяет модель в процессе обучения, верно? Неужели мы действительно не сможем ничего выудить из их наборов данных?
Рассмотрим простой пример, как извлечь информацию из обучающего набора данных
Федеративное обучение страдает двумя большими проблемами, особенно трудноразрешимыми, когда у каждого человека имеется лишь маленькая горстка обучающих примеров, — скорость и конфиденциальность. Как оказывается, если у кого-то имеется лишь несколько обучающих примеров (или модель, присланная вам, была обучена лишь на нескольких примерах: обучающем пакете), вы все еще можете довольно много узнать об исходных данных. Если представить, что у вас есть 10 000 человек (и у каждого имеется очень небольшой объем данных), большую часть времени вы потратите на пересылку модели туда и обратно и не так много — на обучение (особенно если модель очень большая).
Но не будем забегать вперед. Давайте посмотрим, что можно узнать после того, как пользователь выполнит обновление весов на одном пакете:
Боб создает и обучает модель на электронных письмах в своем почтовом ящике. Но так случилось, что он сохранил свой пароль, послав самому себе письмо с текстом: «My computer password is pizza». Наивный Боб! Посмотрев, какие весовые коэффициенты изменились, мы можем выяснить словарь (и понять смысл) письма Боба:
Таким несложным способом мы узнали сверхсекретный пароль Боба (и, возможно, его кулинарные предпочтения). И что же делать? Как доверять федеративному обучению, если так легко узнать, какие обучающие данные вызвали изменение весов?
» Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок
Для Хаброжителей скидка 30% на предзаказ книги по купону — Grokking Deep Learning
Предлагаем на обзорно ознакомится с отрывком «Федеративное обучение»
Идея федеративного обучения зародилась из того, что многие данные, содержащие полезную информацию для решения задач (например, для диагностики онкологических заболеваний с использованием МРТ), трудно получить в количествах, достаточных для обучения мощной модели глубокого обучения. Кроме полезной информации, необходимой для обучения модели, наборы данных содержат также другие сведения, не имеющие отношения к решаемой задаче, но их раскрытие кому-либо потенциально может нанести вред.
Федеративное обучение — это методика заключения модели в защищенную среду и ее обучение без перемещения данных куда-либо. Рассмотрим пример.
import numpy as np
from collections import Counter
import random
import sys
import codecsnp.random.seed(12345)
with codecs.open('spam.txt',"r",encoding='utf-8',errors='ignore') as f: ← Данные можно получить здесь http://www2.aueb.gr/users/ion/data/enron-spam/
raw = f.readlines()
vocab, spam, ham = (set(["<unk>"]), list(), list())
for row in raw:
spam.append(set(row[:-2].split(" ")))
for word in spam[-1]:
vocab.add(word)
with codecs.open('ham.txt',"r",encoding='utf-8',errors='ignore') as f:
raw = f.readlines()
for row in raw:
ham.append(set(row[:-2].split(" ")))
for word in ham[-1]:
vocab.add(word)
vocab, w2i = (list(vocab), {})
for i,w in enumerate(vocab):
w2i[w] = i
def to_indices(input, l=500):
indices = list()
for line in input:
if(len(line) < l):
line = list(line) + ["<unk>"] * (l - len(line))
idxs = list()
for word in line:
idxs.append(w2i[word])
indices.append(idxs)
return indices
Обучаем выявлять спам
Допустим, нам нужно обучить модель определять спам по электронным письмам людей
В данном случае мы говорим о классификации электронной почты. Нашу первую модель мы обучим на общедоступном наборе данных с названием Enron. Это огромный корпус электронных писем, опубликованных в ходе слушаний по делу компании Enron (теперь это стандартный аналитический корпус электронной почты). Интересный факт: я был знаком с людьми, которым по роду своей деятельности приходилось читать/комментировать этот набор данных, и они отмечают, что люди посылали друг другу в этих письмах самую разную информацию (часто очень личную). Но так как этот корпус был обнародован в ходе судебных разбирательств, в настоящее время его можно использовать без ограничений.
Код в предыдущем и в этом разделе реализует только подготовительные операции. Файлы с входными данными (ham.txt и spam.txt) доступны на веб-странице книги: www.manning.com/books/grokking-deep-learning и в репозитории GitHub: github.com/iamtrask/Grokking-Deep-Learning. Мы должны предварительно обработать его, чтобы подготовить его для передачи в класс Embedding из главы 13, где мы создали свой фреймворк глубокого обучения. Как и прежде, все слова в этом корпусе преобразуются в списки индексов. Кроме того, мы приводим все письма к одинаковой длине в 500 слов, либо обрезая их, либо дополняя лексемами . Благодаря этому мы получаем набор данных прямоугольной формы.
spam_idx = to_indices(spam)
ham_idx = to_indices(ham)
train_spam_idx = spam_idx[0:-1000]
train_ham_idx = ham_idx[0:-1000]
test_spam_idx = spam_idx[-1000:]
test_ham_idx = ham_idx[-1000:]
train_data = list()
train_target = list()
test_data = list()
test_target = list()
for i in range(max(len(train_spam_idx),len(train_ham_idx))):
train_data.append(train_spam_idx[i%len(train_spam_idx)])
train_target.append([1])
train_data.append(train_ham_idx[i%len(train_ham_idx)])
train_target.append([0])
for i in range(max(len(test_spam_idx),len(test_ham_idx))):
test_data.append(test_spam_idx[i%len(test_spam_idx)])
test_target.append([1])
test_data.append(test_ham_idx[i%len(test_ham_idx)])
test_target.append([0])
def train(model, input_data, target_data, batch_size=500, iterations=5):
n_batches = int(len(input_data) / batch_size)
for iter in range(iterations):
iter_loss = 0
for b_i in range(n_batches):
# дополняющая лексема не должна оказывать влияния на прогноз
model.weight.data[w2i['<unk>']] *= 0
input = Tensor(input_data[b_i*bs:(b_i+1)*bs], autograd=True)
target = Tensor(target_data[b_i*bs:(b_i+1)*bs], autograd=True)
pred = model.forward(input).sum(1).sigmoid()
loss = criterion.forward(pred,target)
loss.backward()
optim.step()
iter_loss += loss.data[0] / bs
sys.stdout.write("\r\tLoss:" + str(iter_loss / (b_i+1)))
print()
return model
def test(model, test_input, test_output):
model.weight.data[w2i['<unk>']] *= 0
input = Tensor(test_input, autograd=True)
target = Tensor(test_output, autograd=True)
pred = model.forward(input).sum(1).sigmoid()
return ((pred.data > 0.5) == target.data).mean()
Определив вспомогательные функции train() и test(), мы можем инициализировать нейронную сеть и обучить ее, написав всего несколько строк кода. Уже после трех итераций сеть оказывается в состоянии классифицировать контрольный набор данных с точностью 99.45 % (контрольный набор данных хорошо сбалансирован, поэтому этот результат можно считать превосходным):
model = Embedding(vocab_size=len(vocab), dim=1)
model.weight.data *= 0
criterion = MSELoss()
optim = SGD(parameters=model.get_parameters(), alpha=0.01)
for i in range(3):
model = train(model, train_data, train_target, iterations=1)
print("% Correct on Test Set: " + \
str(test(model, test_data, test_target)*100))
______________________________________________________________________________
Loss:0.037140416860871446
% Correct on Test Set: 98.65
Loss:0.011258669226059114
% Correct on Test Set: 99.15
Loss:0.008068268387986223
% Correct on Test Set: 99.45
Сделаем модель федеративной
Выше было выполнено самое обычное глубокое обучение. Теперь добавим конфиденциальности
В предыдущем разделе мы реализовали пример анализа электронной почты. Теперь поместим все электронные письма в одно место. Это старый добрый метод работы (который все еще широко используется во всем мире). Для начала сымитируем окружение федеративного обучения, в котором имеется несколько разных коллекций писем:
bob = (train_data[0:1000], train_target[0:1000])
alice = (train_data[1000:2000], train_target[1000:2000])
sue = (train_data[2000:], train_target[2000:])
Пока ничего сложного. Теперь мы можем выполнить ту же процедуру обучения, что и прежде, но уже на трех отдельных наборах данных. После каждой итерации мы будем усреднять значения в моделях Боба (Bob), Алисы (Alice) и Сью (Sue) и оценивать результаты. Обратите внимание, что некоторые методы федеративного обучения предусматривают объединение после каждого пакета (или коллекции пакетов); я же решил сохранить код максимально простым:
for i in range(3):
print("Starting Training Round...")
print("\tStep 1: send the model to Bob")
bob_model = train(copy.deepcopy(model), bob[0], bob[1], iterations=1)
print("\n\tStep 2: send the model to Alice")
alice_model = train(copy.deepcopy(model),
alice[0], alice[1], iterations=1)
print("\n\tStep 3: Send the model to Sue")
sue_model = train(copy.deepcopy(model), sue[0], sue[1], iterations=1)
print("\n\tAverage Everyone's New Models")
model.weight.data = (bob_model.weight.data + \
alice_model.weight.data + \
sue_model.weight.data)/3
print("\t% Correct on Test Set: " + \
str(test(model, test_data, test_target)*100))
print("\nRepeat!!\n")
Ниже дан фрагмент с результатами. Эта модель достигла практически того же уровня точности, что и предыдущая, и теоретически у нас отсутствовал доступ к обучающим данным — или нет? Как бы там ни было, но каждый человек изменяет модель в процессе обучения, верно? Неужели мы действительно не сможем ничего выудить из их наборов данных?
Starting Training Round...
Step 1: send the model to Bob
Loss:0.21908166249699718
......
Step 3: Send the model to Sue
Loss:0.015368461608470256
Average Everyone's New Models
% Correct on Test Set: 98.8
Взламываем федеративную модель
Рассмотрим простой пример, как извлечь информацию из обучающего набора данных
Федеративное обучение страдает двумя большими проблемами, особенно трудноразрешимыми, когда у каждого человека имеется лишь маленькая горстка обучающих примеров, — скорость и конфиденциальность. Как оказывается, если у кого-то имеется лишь несколько обучающих примеров (или модель, присланная вам, была обучена лишь на нескольких примерах: обучающем пакете), вы все еще можете довольно много узнать об исходных данных. Если представить, что у вас есть 10 000 человек (и у каждого имеется очень небольшой объем данных), большую часть времени вы потратите на пересылку модели туда и обратно и не так много — на обучение (особенно если модель очень большая).
Но не будем забегать вперед. Давайте посмотрим, что можно узнать после того, как пользователь выполнит обновление весов на одном пакете:
import copy
bobs_email = ["my", "computer", "password", "is", "pizza"]
bob_input = np.array([[w2i[x] for x in bobs_email]])
bob_target = np.array([[0]])
model = Embedding(vocab_size=len(vocab), dim=1)
model.weight.data *= 0
bobs_model = train(copy.deepcopy(model),
bob_input, bob_target, iterations=1, batch_size=1)
Боб создает и обучает модель на электронных письмах в своем почтовом ящике. Но так случилось, что он сохранил свой пароль, послав самому себе письмо с текстом: «My computer password is pizza». Наивный Боб! Посмотрев, какие весовые коэффициенты изменились, мы можем выяснить словарь (и понять смысл) письма Боба:
for i, v in enumerate(bobs_model.weight.data - model.weight.data):
if(v != 0):
print(vocab[i])
Таким несложным способом мы узнали сверхсекретный пароль Боба (и, возможно, его кулинарные предпочтения). И что же делать? Как доверять федеративному обучению, если так легко узнать, какие обучающие данные вызвали изменение весов?
is
pizza
computer
password
my
» Более подробно с книгой можно ознакомиться на сайте издательства
» Оглавление
» Отрывок
Для Хаброжителей скидка 30% на предзаказ книги по купону — Grokking Deep Learning