recoilme commited on
Commit
77bf99c
·
1 Parent(s): 09f8d51
dataset-Copy1.py ADDED
@@ -0,0 +1,402 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # pip install flash-attn --no-build-isolation
2
+ import torch
3
+ import os
4
+ import gc
5
+ import numpy as np
6
+ import random
7
+ import json
8
+ import shutil
9
+ import time
10
+
11
+ from datasets import Dataset, load_from_disk, concatenate_datasets
12
+ from diffusers import AutoencoderKL,AutoencoderKLWan
13
+ from torchvision.transforms import Resize, ToTensor, Normalize, Compose, InterpolationMode, Lambda
14
+ from transformers import AutoModel, AutoImageProcessor, AutoTokenizer, AutoModelForCausalLM
15
+ from typing import Dict, List, Tuple, Optional, Any
16
+ from PIL import Image
17
+ from tqdm import tqdm
18
+ from datetime import timedelta
19
+
20
+ # ---------------- 1️⃣ Настройки ----------------
21
+ dtype = torch.float16
22
+ device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
23
+ batch_size = 5
24
+ min_size = 320 #192 #256 #192
25
+ max_size = 640 #384 #256 #384
26
+ step = 64 #64
27
+ empty_share = 0.05
28
+ limit = 0
29
+ # Основная процедура обработки
30
+ folder_path = "/workspace/d23" #alchemist"
31
+ save_path = "/workspace/d23_640" #"alchemist"
32
+ os.makedirs(save_path, exist_ok=True)
33
+
34
+ # Функция для очистки CUDA памяти
35
+ def clear_cuda_memory():
36
+ if torch.cuda.is_available():
37
+ used_gb = torch.cuda.max_memory_allocated() / 1024**3
38
+ print(f"used_gb: {used_gb:.2f} GB")
39
+ torch.cuda.empty_cache()
40
+ gc.collect()
41
+
42
+ # ---------------- 2️⃣ Загрузка моделей ----------------
43
+ def load_models():
44
+ print("Загрузка моделей...")
45
+ vae = AutoencoderKL.from_pretrained("AiArtLab/sdxs3d",subfolder="vae",torch_dtype=dtype).to(device).eval()
46
+
47
+ model_name = "Qwen/Qwen3-0.6B"
48
+ tokenizer = AutoTokenizer.from_pretrained(model_name)
49
+ model = AutoModelForCausalLM.from_pretrained(
50
+ model_name,
51
+ torch_dtype=dtype,
52
+ device_map=device
53
+ ).eval()
54
+ #tokenizer = AutoTokenizer.from_pretrained('Qwen/Qwen3-Embedding-0.6B', padding_side='left')
55
+ #model = AutoModel.from_pretrained('Qwen/Qwen3-Embedding-0.6B').to("cuda")
56
+ return vae, model, tokenizer
57
+
58
+ vae, model, tokenizer = load_models()
59
+
60
+ shift_factor = getattr(vae.config, "shift_factor", 0.0)
61
+ if shift_factor is None:
62
+ shift_factor = 0.0
63
+
64
+ scaling_factor = getattr(vae.config, "scaling_factor", 1.0)
65
+ if scaling_factor is None:
66
+ scaling_factor = 1.0
67
+
68
+ latents_mean = getattr(vae.config, "latents_mean", None)
69
+ latents_std = getattr(vae.config, "latents_std", None)
70
+
71
+ # ---------------- 3️⃣ Трансформации ----------------
72
+ def get_image_transform(min_size=256, max_size=512, step=64):
73
+ def transform(img, dry_run=False):
74
+ # Сохраняем исходные размеры изображения
75
+ original_width, original_height = img.size
76
+
77
+ # 0. Ресайз: масштабируем изображение, чтобы максимальная сторона была равна max_size
78
+ if original_width >= original_height:
79
+ new_width = max_size
80
+ new_height = int(max_size * original_height / original_width)
81
+ else:
82
+ new_height = max_size
83
+ new_width = int(max_size * original_width / original_height)
84
+
85
+ if new_height < min_size or new_width < min_size:
86
+ # 1. Ресайз: масштабируем изображение, чтобы минимальная сторона была равна min_size
87
+ if original_width <= original_height:
88
+ new_width = min_size
89
+ new_height = int(min_size * original_height / original_width)
90
+ else:
91
+ new_height = min_size
92
+ new_width = int(min_size * original_width / original_height)
93
+
94
+ # 2. Проверка: если одна из сторон превышает max_size, готовимся к обрезке
95
+ crop_width = min(max_size, (new_width // step) * step)
96
+ crop_height = min(max_size, (new_height // step) * step)
97
+
98
+ # Убеждаемся, что размеры обрезки не меньше min_size
99
+ crop_width = max(min_size, crop_width)
100
+ crop_height = max(min_size, crop_height)
101
+
102
+ # Если запрошен только предварительный расчёт размеров
103
+ if dry_run:
104
+ return crop_width, crop_height
105
+
106
+ # Конвертация в RGB и ресайз
107
+ img_resized = img.convert("RGB").resize((new_width, new_height), Image.LANCZOS)
108
+
109
+ # Определение координат обрезки (обрезаем с учетом вотермарок - треть сверху)
110
+ top = (new_height - crop_height) // 3
111
+ left = 0
112
+
113
+ # Обрезка изображения
114
+ img_cropped = img_resized.crop((left, top, left + crop_width, top + crop_height))
115
+
116
+ # Сохраняем итоговые размеры после всех преобразований
117
+ final_width, final_height = img_cropped.size
118
+
119
+ # тензор
120
+ img_tensor = ToTensor()(img_cropped)
121
+ img_tensor = Normalize(mean=[0.5, 0.5, 0.5], std=[0.5, 0.5, 0.5])(img_tensor)
122
+ return img_tensor, img_cropped, final_width, final_height
123
+
124
+ return transform
125
+
126
+ # ---------------- 4️⃣ Функции обработки ----------------
127
+ def last_token_pool(last_hidden_states: torch.Tensor,
128
+ attention_mask: torch.Tensor) -> torch.Tensor:
129
+ # Определяем, есть ли left padding
130
+ left_padding = (attention_mask[:, -1].sum() == attention_mask.shape[0])
131
+ if left_padding:
132
+ return last_hidden_states[:, -1]
133
+ else:
134
+ sequence_lengths = attention_mask.sum(dim=1) - 1
135
+ batch_size = last_hidden_states.shape[0]
136
+ return last_hidden_states[torch.arange(batch_size, device=last_hidden_states.device), sequence_lengths]
137
+
138
+ def encode_texts_batch(texts, tokenizer, model, device="cuda", max_length=150, normalize=False):
139
+ with torch.inference_mode():
140
+ # Токенизация
141
+ batch = tokenizer(
142
+ texts,
143
+ return_tensors="pt",
144
+ padding="max_length",
145
+ truncation=True,
146
+ max_length=max_length
147
+ ).to(device)
148
+
149
+ # Прогон через модель
150
+ #outputs = model(**batch)
151
+
152
+ # Пулинг по last token
153
+ #embeddings = last_token_pool(outputs.last_hidden_state, batch["attention_mask"])
154
+
155
+ # L2-нормализация (опционально, обычно нужна для семантического поиска)
156
+ #if normalize:
157
+ # embeddings = F.normalize(embeddings, p=2, dim=1)
158
+
159
+ # Прогон через базовую модель (внутри CausalLM)
160
+ outputs = model.model(**batch, output_hidden_states=True)
161
+
162
+ # Берем последний слой (эмбеддинги всех токенов)
163
+ hidden_states = outputs.hidden_states[-1] # [B, L, D]
164
+
165
+ # Можно применить нормализацию по каждому токену (как в CLIP)
166
+ if normalize:
167
+ hidden_states = F.normalize(hidden_states, p=2, dim=-1)
168
+
169
+ return hidden_states.cpu().numpy() # embeddings.unsqueeze(1).cpu().numpy()
170
+
171
+ def clean_label(label):
172
+ label = label.replace("Image 1", "").replace("Image 2", "").replace("Image 3", "").replace("Image 4", "")
173
+ return label
174
+
175
+ def process_labels_for_guidance(original_labels, prob_to_make_empty=0.01):
176
+ """
177
+ Обрабатывает список меток для classifier-free guidance.
178
+
179
+ С вероятностью prob_to_make_empty:
180
+ - Метка в первом списке заменяется на пустую строку.
181
+ - К метке во втором списке добавляется префикс "zero:".
182
+
183
+ В противном случае метки в обоих списках остаются оригинальными.
184
+
185
+ """
186
+ labels_for_model = []
187
+ labels_for_logging = []
188
+
189
+ for label in original_labels:
190
+ if random.random() < prob_to_make_empty:
191
+ labels_for_model.append("") # Заменяем на пустую строку для модели
192
+ labels_for_logging.append(f"zero: {label}") # Добавляем префикс для логгирования
193
+ else:
194
+ labels_for_model.append(label) # Оставляем оригинальную метку для модели
195
+ labels_for_logging.append(label) # Оставляем оригинальную метку для логгирования
196
+
197
+ return labels_for_model, labels_for_logging
198
+
199
+ def encode_to_latents(images, texts):
200
+ transform = get_image_transform(min_size, max_size, step)
201
+
202
+ try:
203
+ # Обработка изображений (все одинакового размера)
204
+ transformed_tensors = []
205
+ pil_images = []
206
+ widths, heights = [], []
207
+
208
+ # Применяем трансформацию ко всем изображениям
209
+ for img in images:
210
+ try:
211
+ t_img, pil_img, w, h = transform(img)
212
+ transformed_tensors.append(t_img)
213
+ pil_images.append(pil_img)
214
+ widths.append(w)
215
+ heights.append(h)
216
+ except Exception as e:
217
+ print(f"Ошибка трансформации: {e}")
218
+ continue
219
+
220
+ if not transformed_tensors:
221
+ return None
222
+
223
+ # Создаём батч
224
+ batch_tensor = torch.stack(transformed_tensors).to(device, dtype)
225
+ if batch_tensor.ndim==5:
226
+ batch_tensor = batch_tensor.unsqueeze(2) # [B, C, 1, H, W]
227
+
228
+ # Кодируем батч
229
+ with torch.no_grad():
230
+ posteriors = vae.encode(batch_tensor).latent_dist.mode()
231
+ latents = (posteriors - shift_factor) / scaling_factor
232
+
233
+ latents_np = latents.to(dtype).cpu().numpy()
234
+
235
+ # Обрабатываем тексты
236
+ text_labels = [clean_label(text) for text in texts]
237
+
238
+ model_prompts, text_labels = process_labels_for_guidance(text_labels, empty_share)
239
+ embeddings = encode_texts_batch(model_prompts, tokenizer, model)
240
+
241
+ return {
242
+ "vae": latents_np,
243
+ "embeddings": embeddings,
244
+ "text": text_labels,
245
+ "width": widths,
246
+ "height": heights
247
+ }
248
+
249
+ except Exception as e:
250
+ print(f"Критическая ошибка в encode_to_latents: {e}")
251
+ raise
252
+
253
+
254
+ # ---------------- 5️⃣ Обработка папки с изображениями и текстами ----------------
255
+ def process_folder(folder_path, limit=None):
256
+ """
257
+ Рекурсивно обходит указанную директорию и все вложенные директории,
258
+ собирая пути к изображениям и соответствующим текстовым файлам.
259
+ """
260
+ image_paths = []
261
+ text_paths = []
262
+ width = []
263
+ height = []
264
+ transform = get_image_transform(min_size, max_size, step)
265
+
266
+ # Используем os.walk для рекурсивного обхода директорий
267
+ for root, dirs, files in os.walk(folder_path):
268
+ for filename in files:
269
+ # Проверяем, является ли файл изображением
270
+ if filename.lower().endswith((".jpg", ".jpeg", ".png")):
271
+ image_path = os.path.join(root, filename)
272
+ try:
273
+ img = Image.open(image_path)
274
+ except Exception as e:
275
+ print(f"Ошибка при открытии {image_path}: {e}")
276
+ os.remove(image_path)
277
+ text_path = os.path.splitext(image_path)[0] + ".txt"
278
+ if os.path.exists(text_path):
279
+ os.remove(text_path)
280
+ continue
281
+ # Применяем трансформацию только для получения размеров
282
+ w, h = transform(img, dry_run=True)
283
+ # Формируем путь к текстовому файлу
284
+ text_path = os.path.splitext(image_path)[0] + ".txt"
285
+
286
+ # Добавляем пути, если текстовый файл существует
287
+ if os.path.exists(text_path) and min(w, h)>0:
288
+ image_paths.append(image_path)
289
+ text_paths.append(text_path)
290
+ width.append(w) # Добавляем в список
291
+ height.append(h) # Добавляем в список
292
+
293
+ # Проверяем ограничение на количество
294
+ if limit and limit>0 and len(image_paths) >= limit:
295
+ print(f"Достигнут лимит в {limit} изображений")
296
+ return image_paths, text_paths, width, height
297
+
298
+ print(f"Найдено {len(image_paths)} изображений с текстовыми описаниями")
299
+ return image_paths, text_paths, width, height
300
+
301
+ def process_in_chunks(image_paths, text_paths, width, height, chunk_size=10000, batch_size=1):
302
+ total_files = len(image_paths)
303
+ start_time = time.time()
304
+ chunks = range(0, total_files, chunk_size)
305
+
306
+ for chunk_idx, start in enumerate(chunks, 1):
307
+ end = min(start + chunk_size, total_files)
308
+ chunk_image_paths = image_paths[start:end]
309
+ chunk_text_paths = text_paths[start:end]
310
+ chunk_widths = width[start:end] if isinstance(width, list) else [width] * len(chunk_image_paths)
311
+ chunk_heights = height[start:end] if isinstance(height, list) else [height] * len(chunk_image_paths)
312
+
313
+ # Чтение текстов
314
+ chunk_texts = []
315
+ for text_path in chunk_text_paths:
316
+ try:
317
+ with open(text_path, 'r', encoding='utf-8') as f:
318
+ text = f.read().strip()
319
+ chunk_texts.append(text)
320
+ except Exception as e:
321
+ print(f"Ошибка чтения {text_path}: {e}")
322
+ chunk_texts.append("")
323
+
324
+ # Группируем изображения по размерам
325
+ size_groups = {}
326
+ for i in range(len(chunk_image_paths)):
327
+ size_key = (chunk_widths[i], chunk_heights[i])
328
+ if size_key not in size_groups:
329
+ size_groups[size_key] = {"image_paths": [], "texts": []}
330
+ size_groups[size_key]["image_paths"].append(chunk_image_paths[i])
331
+ size_groups[size_key]["texts"].append(chunk_texts[i])
332
+
333
+ # Обрабатываем каждую группу размеров отдельно
334
+ for size_key, group_data in size_groups.items():
335
+ print(f"Обработка группы с размером {size_key[0]}x{size_key[1]} - {len(group_data['image_paths'])} изображений")
336
+
337
+ group_dataset = Dataset.from_dict({
338
+ "image_path": group_data["image_paths"],
339
+ "text": group_data["texts"]
340
+ })
341
+
342
+ # Теперь можно использовать указанный batch_size, т.к. все изображения одного размера
343
+ processed_group = group_dataset.map(
344
+ lambda examples: encode_to_latents(
345
+ [Image.open(path) for path in examples["image_path"]],
346
+ examples["text"]
347
+ ),
348
+ batched=True,
349
+ batch_size=batch_size,
350
+ #remove_columns=["image_path"],
351
+ desc=f"Обработка группы размера {size_key[0]}x{size_key[1]}"
352
+ )
353
+
354
+ # Сохраняем результаты группы
355
+ group_save_path = f"{save_path}_temp/chunk_{chunk_idx}_size_{size_key[0]}x{size_key[1]}"
356
+ processed_group.save_to_disk(group_save_path)
357
+ clear_cuda_memory()
358
+ elapsed = time.time() - start_time
359
+ processed = (chunk_idx - 1) * chunk_size + sum([len(sg["image_paths"]) for sg in list(size_groups.values())[:list(size_groups.values()).index(group_data) + 1]])
360
+ if processed > 0:
361
+ remaining = (elapsed / processed) * (total_files - processed)
362
+ elapsed_str = str(timedelta(seconds=int(elapsed)))
363
+ remaining_str = str(timedelta(seconds=int(remaining)))
364
+ print(f"ETA: Прошло {elapsed_str}, Осталось {remaining_str}, Прогресс {processed}/{total_files} ({processed/total_files:.1%})")
365
+
366
+ # ---------------- 7️⃣ Объединение чанков ----------------
367
+ def combine_chunks(temp_path, final_path):
368
+ """Объединение обработанных чанков в финальный датасет"""
369
+ chunks = sorted([
370
+ os.path.join(temp_path, d)
371
+ for d in os.listdir(temp_path)
372
+ if d.startswith("chunk_")
373
+ ])
374
+
375
+ datasets = [load_from_disk(chunk) for chunk in chunks]
376
+ combined = concatenate_datasets(datasets)
377
+ combined.save_to_disk(final_path)
378
+
379
+ print(f"✅ Датасет успешно сохранен в: {final_path}")
380
+
381
+
382
+
383
+ # Создаем временную папку для чанков
384
+ temp_path = f"{save_path}_temp"
385
+ os.makedirs(temp_path, exist_ok=True)
386
+
387
+ # Получаем список файлов
388
+ image_paths, text_paths, width, height = process_folder(folder_path,limit)
389
+ print(f"Всего найдено {len(image_paths)} изображений")
390
+
391
+ # Обработка с чанкованием
392
+ process_in_chunks(image_paths, text_paths, width, height, chunk_size=10000, batch_size=batch_size)
393
+
394
+ # Объединение чанков в финальный датасет
395
+ combine_chunks(temp_path, save_path)
396
+
397
+ # Удаление временной папки
398
+ try:
399
+ shutil.rmtree(temp_path)
400
+ print(f"✅ Временная папка {temp_path} успешно удалена")
401
+ except Exception as e:
402
+ print(f"⚠️ Ошибка при удалении временной папки: {e}")
dataset.py CHANGED
@@ -16,6 +16,8 @@ from typing import Dict, List, Tuple, Optional, Any
16
  from PIL import Image
17
  from tqdm import tqdm
18
  from datetime import timedelta
 
 
19
 
20
  # ---------------- 1️⃣ Настройки ----------------
21
  dtype = torch.float16
@@ -27,8 +29,9 @@ step = 64 #64
27
  empty_share = 0.05
28
  limit = 0
29
  # Основная процедура обработки
30
- folder_path = "/workspace/d23" #alchemist"
31
- save_path = "/workspace/d23_640" #"alchemist"
 
32
  os.makedirs(save_path, exist_ok=True)
33
 
34
  # Функция для очистки CUDA памяти
@@ -51,8 +54,6 @@ def load_models():
51
  torch_dtype=dtype,
52
  device_map=device
53
  ).eval()
54
- #tokenizer = AutoTokenizer.from_pretrained('Qwen/Qwen3-Embedding-0.6B', padding_side='left')
55
- #model = AutoModel.from_pretrained('Qwen/Qwen3-Embedding-0.6B').to("cuda")
56
  return vae, model, tokenizer
57
 
58
  vae, model, tokenizer = load_models()
@@ -135,7 +136,7 @@ def last_token_pool(last_hidden_states: torch.Tensor,
135
  batch_size = last_hidden_states.shape[0]
136
  return last_hidden_states[torch.arange(batch_size, device=last_hidden_states.device), sequence_lengths]
137
 
138
- def encode_texts_batch(texts, tokenizer, model, device="cuda", max_length=150, normalize=False):
139
  with torch.inference_mode():
140
  # Токенизация
141
  batch = tokenizer(
@@ -146,25 +147,11 @@ def encode_texts_batch(texts, tokenizer, model, device="cuda", max_length=150, n
146
  max_length=max_length
147
  ).to(device)
148
 
149
- # Прогон через модель
150
- #outputs = model(**batch)
151
-
152
- # Пулинг по last token
153
- #embeddings = last_token_pool(outputs.last_hidden_state, batch["attention_mask"])
154
-
155
- # L2-нормализация (опционально, обычно нужна для семантического поиска)
156
- #if normalize:
157
- # embeddings = F.normalize(embeddings, p=2, dim=1)
158
-
159
  # Прогон через базовую модель (внутри CausalLM)
160
  outputs = model.model(**batch, output_hidden_states=True)
161
 
162
  # Берем последний слой (эмбеддинги всех токенов)
163
- hidden_states = outputs.hidden_states[-1] # [B, L, D]
164
-
165
- # Можно применить нормализацию по каждому токену (как в CLIP)
166
- if normalize:
167
- hidden_states = F.normalize(hidden_states, p=2, dim=-1)
168
 
169
  return hidden_states.cpu().numpy() # embeddings.unsqueeze(1).cpu().numpy()
170
 
@@ -354,6 +341,10 @@ def process_in_chunks(image_paths, text_paths, width, height, chunk_size=10000,
354
  # Сохраняем результаты группы
355
  group_save_path = f"{save_path}_temp/chunk_{chunk_idx}_size_{size_key[0]}x{size_key[1]}"
356
  processed_group.save_to_disk(group_save_path)
 
 
 
 
357
  clear_cuda_memory()
358
  elapsed = time.time() - start_time
359
  processed = (chunk_idx - 1) * chunk_size + sum([len(sg["image_paths"]) for sg in list(size_groups.values())[:list(size_groups.values()).index(group_data) + 1]])
@@ -363,22 +354,21 @@ def process_in_chunks(image_paths, text_paths, width, height, chunk_size=10000,
363
  remaining_str = str(timedelta(seconds=int(remaining)))
364
  print(f"ETA: Прошло {elapsed_str}, Осталось {remaining_str}, Прогресс {processed}/{total_files} ({processed/total_files:.1%})")
365
 
366
- # ---------------- 7️⃣ Объединение чанков ----------------
367
  def combine_chunks(temp_path, final_path):
368
- """Объединение обработанных чанков в финальный датасет"""
369
- chunks = sorted([
370
- os.path.join(temp_path, d)
371
- for d in os.listdir(temp_path)
372
- if d.startswith("chunk_")
373
- ])
374
-
375
- datasets = [load_from_disk(chunk) for chunk in chunks]
 
 
376
  combined = concatenate_datasets(datasets)
377
  combined.save_to_disk(final_path)
378
-
379
- print(f"✅ Датасет успешно сохранен в: {final_path}")
380
-
381
-
382
 
383
  # Создаем временную папку для чанков
384
  temp_path = f"{save_path}_temp"
 
16
  from PIL import Image
17
  from tqdm import tqdm
18
  from datetime import timedelta
19
+ import subprocess
20
+ import tempfile
21
 
22
  # ---------------- 1️⃣ Настройки ----------------
23
  dtype = torch.float16
 
29
  empty_share = 0.05
30
  limit = 0
31
  # Основная процедура обработки
32
+ folder_path = "/workspace/1" #alchemist"
33
+ save_path = "/workspace/1_640" #"alchemist"
34
+ dir_tmp = "/workspace/tmp"
35
  os.makedirs(save_path, exist_ok=True)
36
 
37
  # Функция для очистки CUDA памяти
 
54
  torch_dtype=dtype,
55
  device_map=device
56
  ).eval()
 
 
57
  return vae, model, tokenizer
58
 
59
  vae, model, tokenizer = load_models()
 
136
  batch_size = last_hidden_states.shape[0]
137
  return last_hidden_states[torch.arange(batch_size, device=last_hidden_states.device), sequence_lengths]
138
 
139
+ def encode_texts_batch(texts, tokenizer, model, device="cuda", max_length=150):
140
  with torch.inference_mode():
141
  # Токенизация
142
  batch = tokenizer(
 
147
  max_length=max_length
148
  ).to(device)
149
 
 
 
 
 
 
 
 
 
 
 
150
  # Прогон через базовую модель (внутри CausalLM)
151
  outputs = model.model(**batch, output_hidden_states=True)
152
 
153
  # Берем последний слой (эмбеддинги всех токенов)
154
+ hidden_states = outputs.last_hidden_state
 
 
 
 
155
 
156
  return hidden_states.cpu().numpy() # embeddings.unsqueeze(1).cpu().numpy()
157
 
 
341
  # Сохраняем результаты группы
342
  group_save_path = f"{save_path}_temp/chunk_{chunk_idx}_size_{size_key[0]}x{size_key[1]}"
343
  processed_group.save_to_disk(group_save_path)
344
+
345
+ subprocess.run(["tar", "-I", "zstd", "-cf", f"{group_save_path}.tar.zst", "-C", group_save_path, "."], check=True)
346
+ shutil.rmtree(group_save_path)
347
+
348
  clear_cuda_memory()
349
  elapsed = time.time() - start_time
350
  processed = (chunk_idx - 1) * chunk_size + sum([len(sg["image_paths"]) for sg in list(size_groups.values())[:list(size_groups.values()).index(group_data) + 1]])
 
354
  remaining_str = str(timedelta(seconds=int(remaining)))
355
  print(f"ETA: Прошло {elapsed_str}, Осталось {remaining_str}, Прогресс {processed}/{total_files} ({processed/total_files:.1%})")
356
 
357
+ # ---------------- 7️⃣ Объединение ----------------
358
  def combine_chunks(temp_path, final_path):
359
+ archives = sorted([os.path.join(temp_path, f) for f in os.listdir(temp_path) if f.endswith(".tar.zst")])
360
+ datasets = []
361
+ for arc in archives:
362
+ #tmp = tempfile.mkdtemp()
363
+ tmp = tempfile.mkdtemp(dir=dir_tmp)
364
+ os.makedirs(tmp, exist_ok=True)
365
+ subprocess.run(["tar", "-I", "zstd", "-xf", arc, "-C", tmp], check=True)
366
+ ds = load_from_disk(tmp)
367
+ datasets.append(ds)
368
+ shutil.rmtree(tmp)
369
  combined = concatenate_datasets(datasets)
370
  combined.save_to_disk(final_path)
371
+ print(f"✅ Датасе�� сохранён: {final_path}")
 
 
 
372
 
373
  # Создаем временную папку для чанков
374
  temp_path = f"{save_path}_temp"
media/result_grid.jpg CHANGED

Git LFS Details

  • SHA256: 506996b6102645a13400234155a76eaf4da0b85ab1fef1ba7d5688ad3eec641c
  • Pointer size: 132 Bytes
  • Size of remote file: 5.59 MB

Git LFS Details

  • SHA256: a2ee482962498d0f81a3b78c309a06266c43c7268d01e960d799c499c069abcd
  • Pointer size: 132 Bytes
  • Size of remote file: 5.76 MB
samples/unet_320x640_0.jpg CHANGED

Git LFS Details

  • SHA256: 9591be1fd28d616667f989a4c60ea5104d03c96e52ffd0cf99173a9b920f46c5
  • Pointer size: 130 Bytes
  • Size of remote file: 68.2 kB

Git LFS Details

  • SHA256: ab008cee205e49d2170f46cc3b876f1cb8729e87b509674ce79c26fc7e62b18d
  • Pointer size: 130 Bytes
  • Size of remote file: 74.2 kB
samples/unet_384x640_0.jpg CHANGED

Git LFS Details

  • SHA256: 7f1de414ecfedcfacadae3507280a2156c011d477b287c5d6fda6061826d74f6
  • Pointer size: 131 Bytes
  • Size of remote file: 152 kB

Git LFS Details

  • SHA256: 7e9fafc22986d367652dc17010b23830c6feb36e03598398ec4686b14e6ef58e
  • Pointer size: 131 Bytes
  • Size of remote file: 158 kB
samples/unet_448x640_0.jpg CHANGED

Git LFS Details

  • SHA256: fb29de4c4334a554c9da6fe48b8204d7b227eec226766fe5e2a9307eb883c212
  • Pointer size: 131 Bytes
  • Size of remote file: 132 kB

Git LFS Details

  • SHA256: c8c65679d9429f12f21bc9078f517503cc6cc310e060a3ee9b1cabd51573f9cd
  • Pointer size: 131 Bytes
  • Size of remote file: 180 kB
samples/unet_512x640_0.jpg CHANGED

Git LFS Details

  • SHA256: 9f68757a89dc32abf05ccec0fe4f37bf53884c4230807bb6fd79acd8844ee025
  • Pointer size: 131 Bytes
  • Size of remote file: 117 kB

Git LFS Details

  • SHA256: a7dcecd07eb9068be244ed7d783c34b103e9b58da7b73e0a2bde9e3555b32863
  • Pointer size: 131 Bytes
  • Size of remote file: 128 kB
samples/unet_576x640_0.jpg CHANGED

Git LFS Details

  • SHA256: 0d86fae40785eb6a11b1d0efdea68bc2008019f7f59b004645d55a88995e7f3c
  • Pointer size: 131 Bytes
  • Size of remote file: 163 kB

Git LFS Details

  • SHA256: ecafadfbbe5963a23020384cbc98b27caa44b845206d14e655c88ce30014136a
  • Pointer size: 131 Bytes
  • Size of remote file: 135 kB
samples/unet_640x320_0.jpg CHANGED

Git LFS Details

  • SHA256: 45bbd3e12e4fe63d86cb69640b0cb379cbc66e5aaccfb9ed70f36636638565cf
  • Pointer size: 131 Bytes
  • Size of remote file: 106 kB

Git LFS Details

  • SHA256: ac7aa161c43809d257908ccee3c9c04697c529f7df1cec33a956369ea347c479
  • Pointer size: 131 Bytes
  • Size of remote file: 107 kB
samples/unet_640x384_0.jpg CHANGED

Git LFS Details

  • SHA256: 3b2b9edf190545cbbed6abd185789045bf7bf8680342c76f397568a3fd3822aa
  • Pointer size: 130 Bytes
  • Size of remote file: 72.7 kB

Git LFS Details

  • SHA256: 9b8204f3cc82ff6c8b64f880e8e4ff40ec8eb3aa777ee8aa5d3399607d934c1b
  • Pointer size: 130 Bytes
  • Size of remote file: 88.8 kB
samples/unet_640x448_0.jpg CHANGED

Git LFS Details

  • SHA256: 5226c63f65fd8ed8365c963b7f930e42a6ce7918b0c408579fbc219d2f41511b
  • Pointer size: 130 Bytes
  • Size of remote file: 94.7 kB

Git LFS Details

  • SHA256: ea72a4c944bc91021bfaddbd700a7896600aa87898e3f793f223dfd16eba78af
  • Pointer size: 130 Bytes
  • Size of remote file: 92.6 kB
samples/unet_640x512_0.jpg CHANGED

Git LFS Details

  • SHA256: 2d5522818407acf4affaec6152e6e8a910cc79f4aa3d5a1219e34e227180da1b
  • Pointer size: 131 Bytes
  • Size of remote file: 132 kB

Git LFS Details

  • SHA256: c88c104df743809fab86cc2cccc174d334d6631107cd9fe68eb9bd76dd9b6e7a
  • Pointer size: 131 Bytes
  • Size of remote file: 108 kB
samples/unet_640x576_0.jpg CHANGED

Git LFS Details

  • SHA256: 3eb2e3ecabd6fabf5dd67fa952e8a86ca0fc7b995266aa3ca7152aa81f9f7e35
  • Pointer size: 131 Bytes
  • Size of remote file: 112 kB

Git LFS Details

  • SHA256: 597ebf66fc0a9f1accf1a0c7a33bc6126c71059ed3c1476a687047ac752c8810
  • Pointer size: 131 Bytes
  • Size of remote file: 181 kB
samples/unet_640x640_0.jpg CHANGED

Git LFS Details

  • SHA256: f35a56f5cca850218375002a5aa03600824fde9edd8948480a965adb2b5661a0
  • Pointer size: 131 Bytes
  • Size of remote file: 192 kB

Git LFS Details

  • SHA256: 98b20852ac0456b975aeff0777c73f10817edf27c09d99933c709eeba0964aaf
  • Pointer size: 131 Bytes
  • Size of remote file: 223 kB
test.ipynb CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:e0f7ceb281d9d78b8ed0085e763df363b106df049ee6830bc40d84e6a1c25b34
3
- size 8326857
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:520b651761ec5d543aaf4698b5b4dcf3168539db48e98fb14df32156bbd89132
3
+ size 6331075
unet/diffusion_pytorch_model.safetensors CHANGED
@@ -1,3 +1,3 @@
1
  version https://git-lfs.github.com/spec/v1
2
- oid sha256:2e9df474bc92756db3f86d5534a6539773126ff1f61bc622ff0af7cff04d08c9
3
  size 6184944280
 
1
  version https://git-lfs.github.com/spec/v1
2
+ oid sha256:16f6b17f2610858bc513b0f61501f61959ce08f46df214d6e3a12d4b2319ddd1
3
  size 6184944280