Самообновляющиеся нейростикеры
Ссылка на телеграмовский стикерпак.
Когда я увидел, что сделали в process.studio, я сразу понял, что невозможно из этого не сделать стикерпак для телеграма. Вопрос лишь в том, кто успеет первым. А тут ещё в студии Лебедева вышел самообновляющийся генеративный стикерпак Стикератор.
Стикеры получились не очень детализированные, пиксельные, но душевные.
Злые:
Приунывшие:
В шоке:
Счастливые, насколько это возможно:
Опыта с нейросетями у меня никакого не было, поэтому мне помогал Саша Мохов, за что ему большое спасибо. Он помог выбрать инструмент и помогал советом в тупиковых ситуациях.
Картинки для обучения сети скачал с Эмоджипедии:
import lxml.html
from lxml.cssselect import CSSSelector as css
import requests
from urllib.request import urlretrieve
response = requests.get('https://emojipedia.org/people/')
tree = lxml.html.fromstring(response.content)
links = css('.emoji-list>li>a')(tree)
for l in links:
url = l.get('href')[1:]
if url == 'serious-face-with-symbols-covering-mouth/':
# stops downloading on specific emoji
break
print(url)
response = requests.get('https://emojipedia.org/people/'+url)
tree2 = lxml.html.fromstring(response.content)
imgs = css('.vendor-image>img')(tree2)
index = 0
for i in imgs:
index += 1
img_url = i.get('src')
filename = img_url.split('/')[-1].split('.')
filename[0] += '_'+str(index)
filename = '.'.join(filename)
print(' - '+img_url)
urlretrieve(img_url, '/Users/z/Downloads/Neuroji_images/'+filename)
Сеть обучил на бесплатном Google colab. Это офигенный сервис, можно запускать тяжёлые вычисления на серверах гугла и не греть свой ноутбук. Да и быстрее выходит. Результат обучения сохранил как два файла: структура нейросети и веса её связей.
model_17500.h5
model_17500.json
Модель делается долго, но её нужно сделать всего один раз, после этого для получения смайликов нужно совсем немножко ресурсов.
Смайлики генерятся другим питоновским скриптом. Он при запуске загружает модель нейросети, потом по таймеру создаёт стикеры и заливает их в пак с помощью либы python-telegram-bot:
%matplotlib inline
import telegram
from telegram.ext import Updater, CommandHandler
from PIL import Image, ImageDraw
from random import randrange
from io import BytesIO
import matplotlib.pyplot as plt
import numpy as np
from keras.layers import Dense, Flatten, Reshape
from keras.layers.advanced_activations import LeakyReLU
from keras.models import Sequential
from keras.optimizers import Adam
from keras.models import model_from_json
import time
import sys
def sample_images(number=1):
global bot
global model
print("Hello, World!")
z = np.random.normal(0, 1, (number, z_dim))
gen_imgs = model.predict(z)
print('Generated {} images'.format(number))
gen_imgs = 0.5 * gen_imgs + 0.5
clear()
for i in range(number):
im_ar = (gen_imgs[i, :, :, :]) * 256.
pil_im = Image.fromarray(im_ar.astype('uint8'), 'RGBA')
pil_im = pil_im.resize((512,512), Image.NEAREST)
bio = BytesIO()
bio.name = 'image.png'
pil_im.save(bio, 'PNG')
bio.seek(0)
bot.add_sticker_to_set(user_id = 115178271,
name = 'neuroji_by_neuroji_bot',
png_sticker = bio,
emojis = '😶')
bot.send_message(chat_id='@zbottesting', text='{} neurojis added!'.format(number))
def clear():
global bot
stickers = bot.get_sticker_set('neuroji_by_neuroji_bot').stickers
for s in stickers:
bot.delete_sticker_from_set(s.file_id)
z_dim = 100 # Size of the noise vector, used as input to the Generator
number = 80
# load json and create model
json_file = open('model_17500.json', 'r')
model_json = json_file.read()
json_file.close()
model = model_from_json(model_json)
model.load_weights("model_17500.h5")
print("Loaded model from disk")
bot = telegram.Bot('851927713:Aa0hGqlACKcGD-deGbTX5BPYdfv3biNywRE') #FIXME paste your token here
updater = Updater(bot = bot, use_context=True)
j = updater.job_queue
updater.dispatcher.add_handler(CommandHandler('clear', clear))
def recurring_job():
try:
sample_images(number)
except: # catch *all* exceptions
e = sys.exc_info()[0]
bot.send_message(chat_id='@zbottesting', text='{}'.format(e))
time.sleep(60*5)
recurring_job()
recurring_job()
Рядом должны лежать файлы обученной модели:
model_17500.h5
model_17500.json
Этот код крутится на самом дешёвом сервере DigitalOcean. Причём я смешно запускаю: не просто питоновский файл, а целый jupyter notebook, на котором уже питоновский скрипт работает. Не уверен, что кроме меня так кто-то делает, но мне удобно, я к юпитеру привык.
Запускаю код так. Сперва подключаюсь к серверу по SSH:
ssh -L 8080:localhost:8080 root@64.225.28.54
Запускаю на удалённом сервере Jupyter notebook. Чтобы он продолжал работать после закрытия терминала, надо запускать его хитро:
nohup jupyter nonohup jupyter notebook --allow-root --port 8080 &
После чего ноутбук волшебным образом отрывается на localhost:8080
, можно запускать в нём код на выполнение, закрывать вкладку браузера и терминал, и заниматься другими делами.
Ссылка на телеграмовский стикерпак.
Клёво было бы сделать естественный отбор, чтобы самые популярные выживали. Но, кажется, АПИ телеграма не отдаёт статистику об отдельных стикерах.
UPD: Время от времени вылезали ошибки и приходилось перезапускать скрипт в юпитере. Поэтому переделал по-нормальному: теперь слегка переделанный скрипт запускается по крону. Для этого открыл редактор crontab -e
и добавил строчку
*/5 * * * * /usr/bin/python3 /root/cron-neuroji.py
Выбрать нужный интервал запуска можно на crontab.guru