X commited on
Commit
24839a6
·
verified ·
1 Parent(s): 440027f

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +109 -388
app.py CHANGED
@@ -1,399 +1,120 @@
1
- import gradio as gr
2
- import torch
3
- import torch.nn as nn
4
- import torch.nn.functional as F
5
- import numpy as np
6
- from PIL import Image
7
- import imageio
8
  import os
9
- import tempfile
 
 
 
10
 
11
- # ============ ИСПРАВЛЕННАЯ ВЕРСИЯ ============
12
- class FullNeuralAnimator(nn.Module):
13
- def __init__(self):
14
- super().__init__()
15
-
16
- # Encoder
17
- self.enc1 = self._block(3, 32)
18
- self.enc2 = self._block(32, 64)
19
- self.enc3 = self._block(64, 128)
20
- self.enc4 = self._block(128, 256)
21
- self.pool = nn.MaxPool2d(2)
22
-
23
- # LSTM
24
- self.lstm = nn.LSTM(
25
- input_size=256 * 8 * 8,
26
- hidden_size=512,
27
- num_layers=2,
28
- batch_first=True,
29
- dropout=0.2
30
- )
31
-
32
- # Decoder
33
- self.dec4 = self._block(512, 256)
34
- self.dec3 = self._block(256, 128)
35
- self.dec2 = self._block(128, 64)
36
- self.dec1 = self._block(64, 32)
37
-
38
- self.up4 = nn.ConvTranspose2d(512, 256, 2, stride=2)
39
- self.up3 = nn.ConvTranspose2d(256, 128, 2, stride=2)
40
- self.up2 = nn.ConvTranspose2d(128, 64, 2, stride=2)
41
- self.up1 = nn.ConvTranspose2d(64, 32, 2, stride=2)
42
-
43
- self.frame_generator = nn.Sequential(
44
- nn.Conv2d(32, 16, 3, padding=1),
45
- nn.ReLU(),
46
- nn.Conv2d(16, 3, 3, padding=1),
47
- nn.Tanh()
48
- )
49
-
50
- def _block(self, in_ch, out_ch):
51
- return nn.Sequential(
52
- nn.Conv2d(in_ch, out_ch, 3, padding=1),
53
- nn.BatchNorm2d(out_ch),
54
- nn.ReLU(inplace=True),
55
- nn.Conv2d(out_ch, out_ch, 3, padding=1),
56
- nn.BatchNorm2d(out_ch),
57
- nn.ReLU(inplace=True)
58
- )
59
-
60
- def forward(self, x, num_frames=20):
61
- batch_size = x.size(0)
62
-
63
- # Encoder
64
- e1 = self.enc1(x)
65
- e2 = self.enc2(self.pool(e1))
66
- e3 = self.enc3(self.pool(e2))
67
- e4 = self.enc4(self.pool(e3))
68
-
69
- skips = [e1, e2, e3, e4]
70
-
71
- # Bottleneck
72
- bottleneck = e4.view(batch_size, -1)
73
-
74
- frames = []
75
- hidden = None
76
- lstm_input = bottleneck.unsqueeze(1)
77
-
78
- for t in range(num_frames):
79
- lstm_out, hidden = self.lstm(lstm_input, hidden)
80
-
81
- h = lstm_out.squeeze(1).view(batch_size, 256, 8, 8)
82
-
83
- # Decoder с проверкой размеров
84
- d4 = self.up4(h)
85
- # Проверяем размеры и при необходимости ресайзим
86
- if d4.size(2) != skips[3].size(2) or d4.size(3) != skips[3].size(3):
87
- skips[3] = F.interpolate(skips[3], size=(d4.size(2), d4.size(3)), mode='bilinear')
88
- d4 = torch.cat([d4, skips[3]], dim=1)
89
- d4 = self.dec4(d4)
90
-
91
- d3 = self.up3(d4)
92
- if d3.size(2) != skips[2].size(2) or d3.size(3) != skips[2].size(3):
93
- skips[2] = F.interpolate(skips[2], size=(d3.size(2), d3.size(3)), mode='bilinear')
94
- d3 = torch.cat([d3, skips[2]], dim=1)
95
- d3 = self.dec3(d3)
96
-
97
- d2 = self.up2(d3)
98
- if d2.size(2) != skips[1].size(2) or d2.size(3) != skips[1].size(3):
99
- skips[1] = F.interpolate(skips[1], size=(d2.size(2), d2.size(3)), mode='bilinear')
100
- d2 = torch.cat([d2, skips[1]], dim=1)
101
- d2 = self.dec2(d2)
102
-
103
- d1 = self.up1(d2)
104
- if d1.size(2) != skips[0].size(2) or d1.size(3) != skips[0].size(3):
105
- skips[0] = F.interpolate(skips[0], size=(d1.size(2), d1.size(3)), mode='bilinear')
106
- d1 = torch.cat([d1, skips[0]], dim=1)
107
- d1 = self.dec1(d1)
108
-
109
- frame = self.frame_generator(d1)
110
- frames.append(frame)
111
-
112
- # Обновляем вход для LSTM
113
- next_features = self.enc4(self.pool(self.enc3(self.pool(self.enc2(self.pool(self.enc1(frame)))))))
114
- next_features = next_features.view(batch_size, -1)
115
- lstm_input = next_features.unsqueeze(1)
116
-
117
- return torch.stack(frames, dim=1)
118
 
119
- # ============ СТИЛЕВАЯ НЕЙРОСЕТЬ ============
120
- class StyleTransferAnimator(nn.Module):
121
- def __init__(self):
122
- super().__init__()
123
-
124
- self.style_embeddings = nn.ParameterDict({
125
- 'wave': nn.Parameter(torch.randn(64)),
126
- 'pulse': nn.Parameter(torch.randn(64)),
127
- 'glitch': nn.Parameter(torch.randn(64)),
128
- 'melt': nn.Parameter(torch.randn(64)),
129
- 'twist': nn.Parameter(torch.randn(64)),
130
- })
131
-
132
- self.encoder = nn.Sequential(
133
- nn.Conv2d(3, 32, 4, stride=2, padding=1),
134
- nn.ReLU(),
135
- nn.Conv2d(32, 64, 4, stride=2, padding=1),
136
- nn.ReLU(),
137
- nn.Conv2d(64, 128, 4, stride=2, padding=1),
138
- nn.ReLU(),
139
- nn.Conv2d(128, 256, 4, stride=2, padding=1),
140
- nn.ReLU(),
141
- )
142
-
143
- self.lstm = nn.LSTM(
144
- input_size=256 * 8 * 8,
145
- hidden_size=512,
146
- num_layers=2,
147
- batch_first=True,
148
- dropout=0.2
149
- )
150
-
151
- self.decoder = nn.Sequential(
152
- nn.ConvTranspose2d(512 + 64, 256, 4, stride=2, padding=1),
153
- nn.ReLU(),
154
- nn.ConvTranspose2d(256, 128, 4, stride=2, padding=1),
155
- nn.ReLU(),
156
- nn.ConvTranspose2d(128, 64, 4, stride=2, padding=1),
157
- nn.ReLU(),
158
- nn.ConvTranspose2d(64, 3, 4, stride=2, padding=1),
159
- nn.Tanh()
160
- )
161
-
162
- def forward(self, x, style='wave', num_frames=20):
163
- batch_size = x.size(0)
164
-
165
- features = self.encoder(x)
166
- features_flat = features.view(batch_size, -1)
167
-
168
- style_vector = self.style_embeddings[style]
169
- style_vector = style_vector.unsqueeze(0).repeat(batch_size, 1)
170
-
171
- frames = []
172
- hidden = None
173
- lstm_input = features_flat.unsqueeze(1)
174
-
175
- for t in range(num_frames):
176
- lstm_out, hidden = self.lstm(lstm_input, hidden)
177
-
178
- h = lstm_out.squeeze(1).view(batch_size, 256, 8, 8)
179
- style_expanded = style_vector.view(batch_size, 64, 1, 1).repeat(1, 1, 8, 8)
180
- decoder_input = torch.cat([h, style_expanded], dim=1)
181
-
182
- frame = self.decoder(decoder_input)
183
- frames.append(frame)
184
-
185
- next_features = self.encoder(frame)
186
- next_features = next_features.view(batch_size, -1)
187
- lstm_input = next_features.unsqueeze(1)
188
-
189
- return torch.stack(frames, dim=1)
190
 
191
- # ============ НЕЙРОСЕТЕВОЙ АНИМАТОР ============
192
- class NeuralAnimator:
193
- def __init__(self):
194
- self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
195
- print(f"🔥 Устройство: {self.device}")
196
-
197
- self.animator = FullNeuralAnimator().to(self.device)
198
- self.styler = StyleTransferAnimator().to(self.device)
199
-
200
- self.load_models()
201
-
202
- self.animator.eval()
203
- self.styler.eval()
204
-
205
- def load_models(self):
206
- models_dir = 'neural_models'
207
- os.makedirs(models_dir, exist_ok=True)
208
-
209
- if os.path.exists(f'{models_dir}/animator.pth'):
210
- self.animator.load_state_dict(torch.load(f'{models_dir}/animator.pth', map_location=self.device))
211
- print("✅ Аниматор загружен")
212
- else:
213
- print("⚠️ Модель не найдена, используем случайную")
214
-
215
- if os.path.exists(f'{models_dir}/styler.pth'):
216
- self.styler.load_state_dict(torch.load(f'{models_dir}/styler.pth', map_location=self.device))
217
- print("✅ Стилизатор загружен")
218
-
219
- def generate_animation(self, image, style='wave', num_frames=20, size=128):
220
- if image is None:
221
- return None
222
-
223
- if isinstance(image, np.ndarray):
224
- img = Image.fromarray(image)
225
- else:
226
- img = image
227
-
228
- img = img.resize((size, size))
229
- img_tensor = torch.from_numpy(np.array(img)).float() / 127.5 - 1
230
- img_tensor = img_tensor.permute(2, 0, 1).unsqueeze(0).to(self.device)
231
-
232
- with torch.no_grad():
233
- if style in ['wave', 'pulse', 'glitch', 'melt', 'twist']:
234
- frames_tensor = self.styler(img_tensor, style=style, num_frames=num_frames)
235
- else:
236
- frames_tensor = self.animator(img_tensor, num_frames=num_frames)
237
-
238
- frames = []
239
- for t in range(num_frames):
240
- frame = frames_tensor[0, t].cpu().numpy().transpose(1, 2, 0)
241
- frame = np.clip((frame + 1) / 2, 0, 1)
242
- frames.append((frame * 255).astype(np.uint8))
243
-
244
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix='.gif')
245
- imageio.mimsave(temp_file.name, frames, duration=0.05, loop=0)
246
-
247
- return temp_file.name
248
 
249
- # ============ ОБУЧЕНИЕ ============
250
- def train_neural_animator():
251
- print("🧠 Обучаем нейросеть...")
252
-
253
- device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
254
-
255
- animator = FullNeuralAnimator().to(device)
256
- styler = StyleTransferAnimator().to(device)
257
-
258
- opt_anim = torch.optim.Adam(animator.parameters(), lr=0.0001)
259
- opt_style = torch.optim.Adam(styler.parameters(), lr=0.0001)
260
-
261
- mse = nn.MSELoss()
262
-
263
- print("🚀 Начинаем обучение...")
264
-
265
- for epoch in range(5): # 5 эпох для быстрого теста
266
- batch_size = 2
267
- fake_images = torch.randn(batch_size, 3, 128, 128, device=device)
268
-
269
- # Обучаем аниматор
270
- frames = animator(fake_images, num_frames=10)
271
- loss_smooth = mse(frames[:, 1:], frames[:, :-1])
272
- loss_consistency = mse(frames.mean(dim=1), fake_images)
273
- loss_anim = loss_smooth + 0.5 * loss_consistency
274
-
275
- opt_anim.zero_grad()
276
- loss_anim.backward()
277
- opt_anim.step()
278
-
279
- # Обучаем стилизатор
280
- style_frames = styler(fake_images, style='wave', num_frames=10)
281
- loss_style_smooth = mse(style_frames[:, 1:], style_frames[:, :-1])
282
- loss_style_consistency = mse(style_frames.mean(dim=1), fake_images)
283
- loss_style = loss_style_smooth + 0.5 * loss_style_consistency
284
-
285
- opt_style.zero_grad()
286
- loss_style.backward()
287
- opt_style.step()
288
-
289
- print(f"Epoch {epoch+1}/5 | Loss: {loss_anim.item():.4f} | Style: {loss_style.item():.4f}")
290
-
291
- os.makedirs('neural_models', exist_ok=True)
292
- torch.save(animator.state_dict(), 'neural_models/animator.pth')
293
- torch.save(styler.state_dict(), 'neural_models/styler.pth')
294
-
295
- print("✅ Обучение завершено!")
296
- return "✅ Модель обучена!"
297
 
298
- # ============ GRADIO ИНТЕРФЕЙС ============
299
- animator = NeuralAnimator()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
300
 
301
- def generate_wrapper(image, style, frames, size):
302
- if image is None:
303
- return None
304
- try:
305
- return animator.generate_animation(image, style, int(frames), int(size))
306
- except Exception as e:
307
- print(f"Ошибка: {e}")
308
- return None
 
 
309
 
310
- # Создаём интерфейс
311
- with gr.Blocks(title="🧠 Нейросетевая анимация") as demo:
312
- gr.Markdown("""
313
- # 🧠 ПОЛНОСТЬЮ НЕЙРОСЕТЕВАЯ АНИМАЦИЯ
314
-
315
- Нейросеть делает ВСЁ: анализ, предсказание движения, генерацию кадров!
316
- """)
317
-
318
- with gr.Row():
319
- with gr.Column(scale=1):
320
- input_image = gr.Image(
321
- label="📸 Загрузи фото",
322
- type="numpy",
323
- height=300
324
- )
325
-
326
- style = gr.Dropdown(
327
- choices=[
328
- ("Волна 🌊", "wave"),
329
- ("Пульс 💓", "pulse"),
330
- ("Глитч 📺", "glitch"),
331
- ("Плавление 🕯️", "melt"),
332
- ("Скручивание 🌀", "twist"),
333
- ("Нейросетевой 🧠", "neural")
334
- ],
335
- label="🎨 Стиль анимации",
336
- value="wave"
337
- )
338
-
339
- frames = gr.Slider(
340
- minimum=10,
341
- maximum=30,
342
- value=20,
343
- step=5,
344
- label="Количество кадров"
345
- )
346
-
347
- size = gr.Slider(
348
- minimum=64,
349
- maximum=256,
350
- value=128,
351
- step=64,
352
- label="Размер (чем меньше, тем быстрее)"
353
- )
354
-
355
- with gr.Row():
356
- generate_btn = gr.Button("🧠 Запустить!", variant="primary")
357
- train_btn = gr.Button("🎓 Обучить", variant="secondary")
358
-
359
- status = gr.Textbox(label="Статус", value="Готов к работе")
360
-
361
- with gr.Column(scale=1):
362
- output_gif = gr.Image(
363
- label="🎬 Результат",
364
- type="filepath",
365
- height=400
366
- )
367
-
368
- download_btn = gr.DownloadButton(
369
- label="📥 Скачать GIF",
370
- variant="primary"
371
- )
372
 
373
- generate_btn.click(
374
- fn=generate_wrapper,
375
- inputs=[input_image, style, frames, size],
376
- outputs=[output_gif]
377
- ).then(
378
- fn=lambda gif: gif if gif else None,
379
- inputs=[output_gif],
380
- outputs=[download_btn]
381
- )
382
 
383
- train_btn.click(
384
- fn=train_neural_animator,
385
- inputs=[],
386
- outputs=[status]
387
- )
388
 
389
- if __name__ == "__main__":
390
- print("""
391
- 🧠 ЗАПУСКАЕМ НЕЙРОСЕТЕВУЮ АНИМАЦИЮ!
392
- 📱 Открой браузер: http://localhost:7860
393
- """)
394
-
395
- demo.launch(
396
- server_name="0.0.0.0",
397
- server_port=7860,
398
- share=True
399
- )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import os
2
+ import random
3
+ import json
4
+ from datasets import Dataset
5
+ from huggingface_hub import HfApi
6
 
7
+ # === ТОКЕН ИЗ СЕКРЕТОВ SPACE ===
8
+ HF_TOKEN = os.getenv("HF_TOKEN")
9
+ USERNAME = "root39058" # Ваш username
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
+ if not HF_TOKEN:
12
+ raise ValueError("HF_TOKEN не найден! Добавьте секрет в Space")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
 
14
+ print("🚀 Начинаем генерацию датасета...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
15
 
16
+ # === СЛОВАРИ ===
17
+ words = {
18
+ 'nouns': [
19
+ 'дом', 'лес', 'вода', 'огонь', 'земля', 'небо', 'ветер', 'дождь', 'снег', 'солнце',
20
+ 'ночь', 'день', 'утро', 'вечер', 'зима', 'весна', 'лето', 'осень', 'город', 'деревня',
21
+ 'машина', 'дорога', 'река', 'гора', 'море', 'океан', 'звезда', 'луна', 'птица', 'рыба',
22
+ 'кот', 'пёс', 'волк', 'лиса', 'медведь', 'заяц', 'слон', 'тигр', 'лев', 'конь',
23
+ 'стол', 'стул', 'кровать', 'окно', 'дверь', 'стена', 'пол', 'потолок', 'лампа', 'книга',
24
+ 'компьютер', 'ноутбук', 'телефон', 'планшет', 'экран', 'клавиатура', 'мышь', 'монитор', 'память', 'процессор'
25
+ ],
26
+ 'verbs': [
27
+ 'бежит', 'идёт', 'летит', 'плывёт', 'сидит', 'стоит', 'лежит', 'ходит', 'едет', 'смотрит',
28
+ 'видит', 'слышит', 'говорит', 'молчит', 'думает', 'знает', 'спит', 'ест', 'пьёт', 'играет',
29
+ 'работает', 'учится', 'читает', 'пишет', 'рисует', 'поёт', 'танцует', 'гуляет', 'плавает', 'ныряет',
30
+ 'прыгает', 'ползает', 'строит', 'ломает', 'чинит', 'моет', 'убирает', 'готовит', 'варит', 'жарит'
31
+ ],
32
+ 'adjs': [
33
+ 'большой', 'маленький', 'красивый', 'страшный', 'добрый', 'злой', 'умный', 'глупый',
34
+ 'быстрый', 'медленный', 'высокий', 'низкий', 'широкий', 'узкий', 'длинный', 'короткий',
35
+ 'глубокий', 'мелкий', 'толстый', 'тонкий', 'лёгкий', 'тяжёлый', 'горячий', 'холодный',
36
+ 'тёплый', 'прохладный', 'мокрый', 'сухой', 'чистый', 'грязный', 'светлый', 'тёмный',
37
+ 'яркий', 'тусклый', 'громкий', 'тихий', 'мягкий', 'жёсткий', 'вкусный', 'противный'
38
+ ],
39
+ 'advs': [
40
+ 'очень', 'сильно', 'немного', 'слегка', 'едва', 'почти', 'вполне', 'совершенно',
41
+ 'абсолютно', 'чрезвычайно', 'крайне', 'слишком', 'чересчур', 'вдруг', 'внезапно',
42
+ 'постепенно', 'медленно', 'быстро', 'тихо', 'громко', 'весело', 'грустно', 'красиво'
43
+ ],
44
+ 'conj': [
45
+ 'и', 'а', 'но', 'да', 'или', 'либо', 'же', 'вот', 'ещё', 'только',
46
+ 'также', 'зато', 'однако', 'поэтому', 'потому что', 'так как', 'если',
47
+ 'хотя', 'когда', 'пока', 'после', 'перед', 'через', 'около', 'рядом'
48
+ ]
49
+ }
 
 
 
 
 
 
 
 
 
 
 
 
 
 
50
 
51
+ # === ГЕНЕРАТОРЫ ===
52
+ def generate_text():
53
+ noun = random.choice(words['nouns'])
54
+ adj = random.choice(words['adjs'])
55
+ verb = random.choice(words['verbs'])
56
+ adv = random.choice(words['advs']) if random.random() > 0.5 else ''
57
+
58
+ if random.random() > 0.6:
59
+ conj = random.choice(words['conj'])
60
+ noun2 = random.choice(words['nouns'])
61
+ verb2 = random.choice(words['verbs'])
62
+ text = f"{adj} {noun} {adv} {verb} {conj} {noun2} {verb2}"
63
+ else:
64
+ text = f"{adj} {noun} {adv} {verb}"
65
+
66
+ return text.capitalize() + "."
67
 
68
+ def generate_code():
69
+ codes = [
70
+ 'def hello():\n print("Привет, мир!")',
71
+ 'function greet(name) {\n console.log(`Привет, ${name}`);\n}',
72
+ '<h1>Заголовок</h1>\n<p>Текст</p>',
73
+ '.class {\n color: blue;\n font-size: 16px;\n}',
74
+ 'SELECT * FROM users WHERE id = 1;',
75
+ '{"key": "value", "array": [1, 2, 3]}'
76
+ ]
77
+ return random.choice(codes)
78
 
79
+ # === ГЕНЕРАЦИЯ ДАТАСЕТА ===
80
+ print("📊 Генерация...")
81
+
82
+ data = []
83
+ target_size = 100 * 1024 * 1024 # 100 МБ
84
+ current_size = 0
85
+
86
+ while current_size < target_size:
87
+ if random.random() > 0.2:
88
+ text = generate_text()
89
+ else:
90
+ text = generate_code()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
91
 
92
+ data.append({"text": text})
93
+ current_size = len(json.dumps(data, ensure_ascii=False).encode('utf-8'))
 
 
 
 
 
 
 
94
 
95
+ if len(data) % 1000 == 0:
96
+ print(f"Готово {len(data)} записей, {current_size // 1024 // 1024} МБ")
 
 
 
97
 
98
+ print(f"✅ Сгенерировано {len(data)} записей, {current_size // 1024 // 1024} МБ")
99
+
100
+ # === СОЗДАНИЕ DATASET ===
101
+ dataset = Dataset.from_list(data)
102
+
103
+ # === СОХРАНЕНИЕ ЛОКАЛЬНО ===
104
+ os.makedirs("/data", exist_ok=True)
105
+ dataset.save_to_disk("/data/my_russian_dataset")
106
+ print("✅ Сохранено в /data")
107
+
108
+ # === ПУШ НА HF ===
109
+ print("☁️ Загрузка на Hugging Face...")
110
+
111
+ try:
112
+ dataset.push_to_hub(
113
+ f"{USERNAME}/Miniset",
114
+ token=HF_TOKEN,
115
+ private=False,
116
+ commit_message="Датасет сгенерирован через Space"
117
+ )
118
+ print(f"\n✅ ГОТОВО! https://huggingface.co/datasets/{USERNAME}/russian-dataset-100mb")
119
+ except Exception as e:
120
+ print(f"❌ Ошибка: {e}")