На прошлой неделе меня дважды спрашивали, как восстановить текст предложения из его LaBSE эмбеддинга. Я дважды отвечал, что никак. Но на самом деле, конечно, можно обучить декодер генерировать текст по его эмбеддингу. Зачем? Например, чтобы:
переводить со 100 разных языков на русский;
суммаризовать много похожих предложений одним;
реалистично заменять фразы в составе предложений;
менять смысл или стиль предложений.
Модель для восстановления предложений из эмбеддингов опубликована как cointegrated/rut5-base-labse-decoder, а подробности – под катом.
LaBSE и другие энкодеры предложений
Энкодер предложений (sentence encoder) – это модель (обычно нейросеть), которая получает на вход текст предложения, а на выходе отдаёт многомерный вектор (например, 768-мерный), примерно описывающий смысл этого предложения. То есть такой, что у предложений, похожих друг на друга по смыслу, векторы похожи друг на друга геометрически. Энкодеры предложений можно использовать для классификации текстов и массы других полезных задач; подробнее читайте в моих постах про маленький BERT и про рейтинг энкодеров предложений.
LaBSE (language-agnostic BERT sentence embeddings) – это модель, предложенная в статье 2020 года от исследователей из Google. По архитектуре это BERT, а обучался он на выборке текстов на 100+ языков в многозадачном режиме. Основная задача – сближать друг с другом эмбеддинги предложений с одинаковым смыслом на разных языках, и с этой задачей модель справляется очень хорошо. Благодаря этой способности можно, например, обучать модель классифицировать английские тексты, а потом применять на русских, или находить в большом корпусе пары предложений на разных языках, являющиеся переводами друг друга.
А вот чего LaBSE не умеет делать совсем, так это генерировать тексты. Единожды превратив текст в вектор, мы уже не сможем получить из него обратно текст. Для этого нужна отдельная модель. И то не факт, что она с этим справится: как говаривал профессор Raymond J. Mooney, You can’t cram the meaning of a single $&!#* sentence into a single $!#&* vector! Но мы всё-таки попробуем.
Обучение декодера
Декодер в NLP – это как раз модель, которая из векторов генерирует тексты, т.е. решает задачу, обратную задаче энкодера. Для русского языка есть несколько декодеров, из которых я выбрал некогда обученную мною модель T5, т.к. это требовало минимальных изменений в коде. Как альтернатива, я мог бы попробовать дообучить русскую GPT; если попробуете – расскажите, пожалуйста!
Кодирование текстов в векторы происходит абсолютно стандартно: извлекаем эмбеддинг CLS-токена из LaBSE и нормализуем его.
bert_name = 'sentence-transformers/LaBSE'
enc_tokenizer = AutoTokenizer.from_pretrained(bert_name)
encoder = AutoModel.from_pretrained(bert_name)
def encode(texts, do_norm=True):
encoded_input = enc_tokenizer(texts, padding=True, truncation=True, max_length=512, return_tensors='pt')
with torch.no_grad():
model_output = encoder(**encoded_input.to(encoder.device))
embeddings = model_output.pooler_output
if do_norm:
embeddings = torch.nn.functional.normalize(embeddings)
return embeddings
Декодирование выглядит так же просто. Это стандартная генерация текстов с помощью T5 (или любого другого seq2seq трансформера), только на вход мы подаём эмбеддинги из LaBSE, которые "прикидываются" эмбеддингами от энкодера T5 (благо размерность и у тех, и у других оказалась 768, так что мне даже не пришлось модифицировать слои cross-attention в T5).
t5_name = 'cointegrated/rut5-base-labse-decoder'
dec_tokenizer = AutoTokenizer.from_pretrained(t5_name)
decoder = AutoModelForSeq2SeqLM.from_pretrained(t5_name)
def decode(embeddings, max_length=256, repetition_penalty=3.0, num_beams=3, **kwargs):
out = decoder.generate(
encoder_outputs=BaseModelOutput(last_hidden_state=embeddings.unsqueeze(1)),
max_length=max_length,
num_beams=num_beams,
repetition_penalty=repetition_penalty,
)
return [dec_tokenizer.decode(tokens, skip_special_tokens=True) for tokens in out]
Естественно, без файнтюнинга T5 предложения, сгенерированные таким образом, будут бессмысленными, ведь T5 обучался смотреть на эмбеддинги из другого пространства, причём не на один, а на целую последовательность эмбеддингов (для каждого токена).
Для дообучения я взял 2 миллиона коротких текстов: opus100, Leipzig collection, и комментарии из Одноклассников. В качестве аугментации добавил ещё 400К отдельно взятых слов. И на всём этом стандартным образом (teacher-forced cross-entropy) обучил T5 генерировать из эмбеддинга исходный текст. Обучал с батчом 8 в течение примерно миллиона шагов; это заняло 2.5 дня на Google Colab. Блокнот – туть.
После дообучения T5 справляется с новой задачей вполне сносно. Можно, например, закодировать такие тексты:
embeddings = encode([
"4 декабря 2000 года",
"Давно такого не читала, очень хорошо пишешь!",
"Я тогда не понимала, что происходит, не понимаю и сейчас.",
"London is the capital of Great Britain.",
])
print(embeddings.shape)
# torch.Size([4, 768])
После декодирования тексты меняются, но смысл их модель примерно воспроизводит:
for text in decode(embeddings):
print(text)
# После 4 декабря 2000 года
# Не так давно, это многое читала!
# Я не понимала того, что происходит сейчас, тогда же.
# Британская столица Англии.
Примеры применения
Окей, нейросеть обучена, и что теперь? В общем-то ничего, ведь этот эксперимент я проделал в первую очередь просто для развлечения. Но если хочется развлекаться дальше, в этом блокноте собрано несколько примеров применения такого декодера. Самый очевидный – это перефразирование, но возможны и более креативные применения.
Перевод
LaBSE умеет "переводить" тексты с разных языков в общее векторное пространство, а наш декодер умеет переводить из этого пространства на русский. Значит, вместе эта парочка моделей можем переводить на русский с любого из 109 языков, известных LaBSE!
Ниже пример десятка языков. Модель не совсем понимает разницу между словами "господа" и "господи", а в остальном вполне справляется с задачей.
Исходный текст |
Перевод |
Господа, я не ел 6 дней! |
Господи, я не ел 6 дней! |
Панове, я не їв 6 днів! |
Господи, я не ел 6 дней! |
Gentlemen, I haven't eaten for 6 days! |
Господи, я 6 дней не кормила! |
Messieurs, je n'ai pas mangé depuis 6 jours! |
Господи, я не съела 6 дней! |
Meine Herren, ich habe seit sechs Tagen nichts gegessen! |
Господи, у меня шесть дней не ели ничего! |
Худовандо, ман 6 рӯз боз чизе нахӯрдаам! |
Боже, у меня еще 6 дней не было! |
Tanrım, 6 gündür yemek yemedim! |
Господи, я не ел 6 дней! |
אלוהים, לא אכלתי 6 ימים |
Боже, у меня не было 6 дней! |
主啊,我已经6天没吃东西了 |
Господи, я уже 6 дней не ела. |
हे प्रभु, मैंने 6 दिनों से कुछ नहीं खाया है! |
Господи, я не съела ничего из этого дня! |
Суммаризация
Иногда бывает нужно по множеству предложений понять, в чём их основная общая идея. Например, не читать 50 отзывов на товар, а прочитать один "усреднённый отзыв". Наша модель вообще-то совсем не предназначалась для суммаризации – но вдруг у неё получится?
Для примера я взял данные отзывов на товары из хакатона М.Видео. Собираю в один текст все отзывы на товар, разбиваю предложения, вычисляю эмбеддинг каждого предложения, усредняю их все в один вектор, нормирую его, и декодирую этот вектор своей моделью. Вот примеры того, что получилось:
# соковыжималка Braun J500
# примеры отдельных предложений
Дизайн строгий, но это понятно - фирма-то немецая.
Из 5 кг яблок выходит меньше литра сока, а пены больше чем сам сок!!!
Жмых сухой, сеточка мелкая и не пропускает куски.
...
# декодированное усреднённое предложение
Устройство очень хорошее, потому что выбрасывать яблоки неплохо.
# Планшет Lenovo Tab 3 Plus
# примеры отдельных предложений
Минусов никаких не заметно пока что.
Экран, Lte, gps, ГЛОНАСС, 2 сим, быстрый, шустрый, размер, тонкий, сборка.
Замечательный планшет!
...
# декодированное усреднённое предложение
Всё очень красиво, у нас на экране есть сенсорная картинка.
# Планшет Prestigio MultiPad
# примеры отдельных предложений
Не очень понравилось что динамик только 1, стерео нет(
На расстоянии пары сантиметров видны пиксели, батарейка заряжается конечно долго.
Зарядное устройство стандартвое без изъян.
...
# декодированное усреднённое предложение
Встроенный экран очень хороший, даже несмотря на то, что у меня есть сенсорная камера.
Как видим, усреднённые предложения не очень информативные, но в целом неплохо отражают настроение отзывов и некоторые аспекты описываемых товаров.
Сложение и вычитание предложений
Мы помним и любим word2vec за поддержку прикольных алгебраических операций над векторами слов, в духе "king + woman - man = queen". Оказывается, LaBSE так тоже умеет!
embeddings = encode(['король', 'женщина', 'мужчина'])
print(decode(embeddings[[0]] + embeddings[[1]] - embeddings[[2]]))
# ['королева']
embeddings = encode(['Лондон', 'Франция', 'Англия'])
print(decode(embeddings[[0]] + embeddings[[1]] - embeddings[[2]]))
# ['Париж']
Более того, LaBSE может складывать и вычитать не только слова, но и небольшие фразы. С длинными текстами у него получается хуже, но зато декодер иногда прикольно додумывает детали:
embeddings = encode([
'Это произошло во время правления Петра Первого.',
'Иван Грозный',
'Пётр Первый',
])
print(decode(embeddings[[0]] + embeddings[[1]] - embeddings[[2]]))
# ['Это произошло в режиме правления Ивана Грозного.']
embeddings = encode([
'Кошка обучает своих котят охотиться за мышами.',
'белый медведь',
'кот',
])
print(decode(embeddings[[0]] + embeddings[[1]] - embeddings[[2]]))
# ['Белый Медведь обучает медведям следить за охотой на оленей.']
embeddings = encode([
'Я не хочу делать прививку, потому что не доверяю врачам.',
'Я верю в народную медицину.',
'Я не доверяю никаким врачам.',
])
print(decode(embeddings[[0]] + embeddings[[1]] - embeddings[[2]]))
# ['Я верю в вакцинацию, потому что я хочу лечиться.']
Перенос стиля текстов
Как мы видели в примере с отзывами, векторы LaBSE сохраняют информацию о стиле и настрое текстов. Получается, если мы возьмём несколько пар текстов с похожим смыслом, но в разном стиле, то средняя разница между их векторами может отражать разницу между стилями. Может быть, её можно использовать для изменения смысла других текстов, как в статьях про TextSETTR или DIFFUR?
Для примера возьмём отсюда примеры сдержанных и эмоциональных текстов. Примеры на английском, но LaBSE на это плевать.
texts_reserved = [
"That is a very pretty painting.",
"I’m excited to see the show.",
"I’m surprised they rescheduled the meeting.",
"This specimen is an example of the baroque style.",
"After the performance, we ate a meal.",
]
texts_emotive = [
"OMG, that’s such a beautiful painting!",
"I’m sooo excited to see the show, it’s going to be stellar!!",
"I absolutely can not believe that they rescheduled the meeting!",
"This wonderful specimen is a truly spectacular example of the baroque style.",
"After the superb performance, we ate a delicious meal.",
]
delta = encode(texts_emotive).mean(0) - encode(texts_reserved).mean(0)
print(decode(encode('Этот фильм произвёл на меня хорошее впечатление.') + delta * 1))
# ['Этот фильм мне очень понравился хорошим впечатлением!']
print(decode(encode('Внешний долг США достиг рекордной величины.') + delta * 1.5))
# ['Увеличенная США долговая задолженность в целом достигла рекордных размеров!']
Видим, что перефразированные тексты действительно стали более эмоциональными и экспрессивными.
Другой пример – превращение формальных текстов в неформальные:
texts_formal = [
"This was a remarkably thought-provoking read.",
"It is certainly amongst my favorites.",
"We humbly request your presence at our gala on the 12th.",
]
texts_informal = [
"reading this rly makes u think",
"Its def one of my favs",
"come swing by our bbq next week if ya can make it",
]
delta = encode(texts_formal).mean(0) - encode(texts_informal).mean(0)
print(decode(encode('Убедительно просим вас покинуть помещение учреждения.') - delta * 0.5))
# ['пожалуйста, уходите из помещения']
print(decode(encode('Был рад нашей с Вами встрече!') - delta * 0.5))
# ['Хорошо встретился с тобой!']
Как видим, оно тоже приблизительно работает.
Ещё я пробовал применить этот подход для детоксификации текстов, но оказалось, что LaBSE понимает смысл грубых текстов на русском языке не очень хорошо – видимо, в его обучающей выборке таких было немного.
Заключение
Энкодерами предложений в последнее время занимаются довольно много, и генераторами текста (такими, как GPT) – тоже. Но к таким декодерам, которые бы инвертировали работу энкодера, интерес в последнее время угас (хотя когда-то автоэнкодеры были модной штучкой). Возможно, зря: как видим, для инвертированного энкодера в 2022 вполне можно найти любопытные применения.
Мой декодер (cointegrated/rut5-base-labse-decoder) выложен на HF; вы можете использовать его в паре с облегчённым русско-английским энкодером cointegrated/LaBSE-en-ru или с полноценной моделью на 100+ языков sentence-transformers/LaBSE. В любом случае, лайкайте понравившиеся вам модели, и пишите в комментарии об интересных кейсах их применения. Подписывайтесь на мой канал, пользуйтесь солнцезащитным кремом и боритесь за мир!
Комментарии (22)
slonoten
19.07.2022 13:26Отличная работа, то что такие модельки можно дообучать за 1.5 дня коллаба - прекрасно.
inkoziev
20.07.2022 10:11Круто! Вот я давно ждал такой модели. Была у меня задумка взять (ну то есть сначала кхм сделать) такой генератор "вектор в текст", повесить на него RL и пусть этот франкенштейн учится выдавать диалоги. Думал начать с чего-то совсем простого, типа Deep Deterministic Policy Gradient, который умеет в continuous actions, и пусть он рулит компонентами эмбеддинга. 768 это конечно многовато, но надо попробовать. А уж reward'ы мы накрутим, начиная с хоть с https://huggingface.co/tinkoff-ai/response-quality-classifier-base. Ну или даже брать перплексию на гэпэтэхе, натрененной на куче диалогов (детских, смешных и т.д.). Спасибо, моя мечта стала ближе :)
cointegrated Автор
20.07.2022 11:05А зачем для диалогов генератор "вектор в текст" вообще? Кажется, RL можно повесить на ту же самую GPT, предобученную на диалоговом корпусе?
inkoziev
20.07.2022 13:03>А зачем для диалогов генератор "вектор в текст" вообще?
В качестве примера - допустим, я хочу, чтобы чатбот умел динамически адаптировать свою речь под текущего собеседника, максимизируя понимаемость и минимизируя длину своих ответов. Или чтобы собеседник чаще ставил смайлики на его ответах. Люди ведь так делают, меняют "речевой регистр", говорят более простыми словами или простыми предложениями, если видят, что собеседник их не понимает. Или чаще шутят, если общаются с условным любителем юмора. Чтобы управлять генерацией в диалоговой gpt, я (в силу кривизны рук и скудоумия) использую всякие костыли в затравке, переключаемые ручными правилами. А так бы этим занималась rl-моделька и декодер "вектор-текст".
>Кажется, RL можно повесить на ту же самую GPT, предобученную на диалоговом корпусе?
Я пока не нашел хорошего способа управлять генерацией в GPT с помощью RL/whatever. Он наверняка есть, но я пока не наткнулся на такой :(Что у нас есть. Некая моделька, которая на вход получает текст и выдает вектор длиной 50,527 чисел - вероятности следующего токена. Как я могу систематически изменить выдачу этой модели, чтобы например получить реплику чатбота с повышенной восторженностью?
1) манипулировать с входным текстом, например добавлять туда спецтокены эмоций, предварительно отфайнтюнив модель на корпусе, который размечен чем-то типа cointegrated/rubert-tiny2-cedr-emotion-detection.
2) лезть руками в вектор на выходе модели, гася вероятности ненужных токенов и повышая вероятности нужных. Тут все сложно, так как русский текст часто при bpe-токенизации разваливается на малобуквенные кусочки, и надо филигранно рулить вероятностями служебных частей речи типа предлогов, окончаниями и т.д.:У Лу ком ор ья дуб зелё ный , З ла тая цепь на ду бе том : И днём и ночью кот учёный Всё ходит по цепи кругом
Первый способ понятно как сформулировать в терминах rl: эмоции это action'ы, мы будем учиться динамически переключать эмоциональную окраску каждой новой реплики для оптимизации цели диалога. Второй способ уложить в RL я не знаю как, 50k action'ов это слишком.cointegrated Автор
20.07.2022 16:12Вообще не вижу проблемы в том, чтобы уложить в RL 50K action'ов. Если у нас модель и так уже предобучена выдавать связные и разнообразные тексты (а у GPT с этим всё в порядке), то нам не надо все 50К действий генерировать и награждать. Достаточно, например, насэмплить несколько наиболее вероятных текстов из распределения ответов модели, а потом сделать такой градиентный шаг, который бы увеличивал вероятности для хороших текстов и уменьшал – для плохих. А ещё можно разделить сгенерированные тексты на группы и обусловить модель генерировать самую лучшую группу, как в статье про Quark.
В общем, мне кажется, что с RL для текстов серьёзная проблема другая: сложно придумать такой reward, максимизация которого действительно приводила бы к генерации текстов с нужными свойствами, а не заставляла бы модель-генератор переобучаться под модель-критика.
snakers4
20.07.2022 15:00Занятно, что можно соединять две разные модели и indictive bias про энкодер-декодер прямо работает.
Одновременно с этим вышла статья про No Language Left Behind (NLLB) и расширение LASER до 100+ языков, интересно, что вы думаете на эту тему. Я вот с инженерной точки зрения ими восхищаюсь, а с полит-экономической, очень грущу, потому что понятно зачем это делается.
А так очень прикольно, что по бичу можно делать такие вещи.cointegrated Автор
20.07.2022 16:02-1Я считаю, что и инженерно, и по-человечески проект NLLB – это здорово. И более того, через пару недель я и сам к нему присоединяюсь.
А что касается полит-экономической части, мне кажется, для сообществ малоресурсных языков лучше иметь переводчик от Меты (тем более, что там всё сделано относительно прозрачно), чем не иметь никакого.
А вас что беспокоит? Что Мета, раз сделала перевод для Википедии, начнёт подминать её под себя?
snakers4
20.07.2022 16:16-1Очевидно, что они начнут диктовать какие статьи и какое наполнение там должно быть.
В статье или блог посте они открытым текстом пишут, что это делается для перевода английской Википедии на новые языки, в первую очередь африканские (ну или будут переводить нужные статьи).
И при обновлении оригинальных статей вряд ли кто-то будет обновлять дочерние. Остальная логическая цепочка строится легко.
И более того, через пару недель я и сам к нему присоединяюсь.
Жалко, что мы и Хабр потеряли ещё одного специалиста. На всякий случай, вы же знаете за что Facebook был признан экстремистской организацией в РФ? У вас это не вызывает у вас в голове противоречия при трудоустройстве?
cointegrated Автор
20.07.2022 16:21Жалко, что мы и Хабр потеряли ещё одного специалиста.
Не знаю, кто такие "мы" (или "вы"), но с Хабром я не вижу проблем совсем. Я писал сюда, работая и в Яндексе, и в Сколтехе, и просто на фрилансе, и не вижу причин покидать русскоязычное NLP-сообщество, работая в Мете.
На всякий случай, вы же знаете за что Facebook был признан экстремистской организацией в РФ? У вас это не вызывает у вас в голове противоречия при трудоустройстве?
У меня противоречия в голове вызывает масса разной х**ни, которая происходит с нами уже давно, а с момента полномасштабного вторжения в Украину эскалировалась. Но с трудоустройством проблем нет, ведь кто сказал, что я в России буду работать?
snakers4
20.07.2022 16:27-3Не вижу причин покидать русскоязычное NLP-сообщество, работая в Мету.
Напишите хотя бы личку, не изменится ли ваше мнение, когда вы прочтете их юр. документы.
кто такие "мы" (или "вы")
Но с трудоустройством проблем нет, ведь кто сказал, что я в России буду работать?
В принципе я и не ожидал иного ответа. Как говорится, кому война, что подтверждает мой тезис про "некоторые животные более равны чем другие".
Для людей, не следящих за новостями, Facebook был признан экстремистской организацией за призывы убивать всех русских, что двулично даже по меркам запада и их политик)
cointegrated Автор
20.07.2022 16:34+2Напишите хотя бы личку, не изменится ли ваше мнение, когда вы прочтете их юр. документы.
При желании могу и сюда написать) Все документы, которые читал пока что, были не страшными.
Для людей, не следящих за новостями, Facebook был признан экстремистской организацией за призывы убивать всех русских, что двулично даже по меркам запада и их политик)
Если мне не изменяет память, Facebook никого ни к чему не призывал. А то, что они не забанили юзеров, призывающих бороться с российскими оккупантами в Украине, не является, на мой взгляд, достаточным поводом считать организацию экстремистской.
cointegrated Автор
20.07.2022 16:27-1Очевидно, что они начнут диктовать какие статьи и какое наполнение там должно быть.
Мне не очевидно, если честно.
Во-первых, конкретно коллегам из FAIR этим заниматься тупо ни к чему, они заняты обучением очередного трансформера и публикацией очередной статьи. Ну а остальные организации в составе Меты ни организационно, ни технически не имеют доступа к переводилке, так что если им зачем-то вдруг нужно влиять на контент в Википедии, у них не больше рычагов влияния на это, чем было прежде.
Во-вторых, сама Мета никаким образом не оказывает влияния на контент публикуемых статей или решение о публикации, она просто предоставляет инструмент для перевода. Так что я могу представить, что с приходом этого инструмента упадёт среднее качество статей на редких языках (потому что активисты будут штамповать их в больших количествах, не тратя очень много времени на ручной пост-процессинг переведённых текстов, или потому, что с ростом числа статей их будет сложнее вовремя обновлять), но не ожидаю, что контент этих статей как-то систематически поменяется (потому что решение о публикации статьи остаётся за редактором Википедии).
Или я в вашей логической цепочке что-то упустил?snakers4
20.07.2022 16:34-1потому что решение о публикации статьи остаётся за редактором Википедии)
Вы так наивны.
В этой же логике, не надо публиковать призывы сасамостоятельно, это прошлый век, если публично объявляется о партнёрке - это значит бабло.
Бабло значит, что редактора можно посадить нужного. А дальше дали инструмент и любые призывы появляются где нужно в нужном количестве. И все белые и пушистые.
Но вот на повороте резком спалились.
cointegrated Автор
20.07.2022 18:26Мне не кажется правдоподобным, что Мета (или, например, Яндекс, где я прежде работал) занимаются такими вещами.
Но если вас эта проблема беспокоит, можно попробовать сделать свою систему перевода, альтернативную фейсбучной и контролируемую сообществом, чтобы Википедия меньше зависела от Меты. Я сам готов в таком поучаствовать в волонтёрском порядке (если, конечно, сотрудники экстремистской организации могут быть для вас рукопожатными).
snakers4
20.07.2022 18:47-1Понятно, что имея готовые инструменты и датасеты путь пройти в 10 раз проще, чем с нуля.
Но что-то мне подсказывает, что это скорее тема для отдельного бизнеса, а не разового хобби проекта. Я прошел какой-то такой путь один раз, на второй можно кончиться.
Также интересно какое будет правоприменение закона об иноагентах.
А к Яндексу вопросов в 10 раз больше,чем к Фейсбуку.
Я хотя бы могу рационально понять, почему они призывают, вместе со всей Западной пропагандой (давайте сэкономим время на полемику) убить всех русских / разделить / деколонозировать / разделить итд ИТП
Но позиция Яндекса мне совсем не ясна.
AigizK
20.07.2022 21:58Я хз как повлияет их политика, но то что для 15 языков народов РФ и СНГ они создали оффлайн переводчик, причем очень высокого качества, заслуживает уважения.
Это сейчас тому же башкирскому языку дает возможность использовать кучу моделей, натренированных для английского и русского языка.
snakers4
21.07.2022 05:03Как говорится ждём массового появления контента на этих языках нужной направленности.
Другой вопрос конечно состоит в том, что Сбер взявший на себя некоторую пальму "первенства" ничего такого не сделал и играется с какой-то хренью.
Хотя опять же, если бы цель стояла просто вложить бабло в корпуса даже просто руками и их выложить (что фейсбук по сути и сделали, но как бы за счёт контента из интернета), то это имело бы в 10 раз больше эффекта.
А по факту получаем ситуацию в которой очередные "индейцы" получают бусы от господина, а сам господин уже строит планы на Манхеттен.
snakers4
20.07.2022 15:05боритесь за мир!
Вы забыли добавить за мир во всем мире.
А то в голову сразу приходит вот такая вот цитата:
Все животные равны, но некоторые животные более равны чем другие.
cointegrated Автор
20.07.2022 16:30А в чём принципиальная разница, можете разъяснить?
snakers4
20.07.2022 16:38Принципиально иной базис ценностей.
Грубо говоря ценна каждая жизнь, весь мир это весь мир а не одна шестая или восьмая, итд итп
cointegrated Автор
20.07.2022 18:01Понимаю и разделяю позицию о ценности каждой жизни!
Но разве мой призыв ей противоречит? Я же вроде не призываю бороться за мир в отдельном регионе и развязывать войны в остальных)
slonoten
Отличная работа, то что такие модельки можно дообучать за 1.5 дня коллаба - прекрасно.