Spaces:
Build error
Build error
File size: 5,839 Bytes
3462329 15012bd 3462329 15012bd bbb5cc7 ecffe29 3462329 00ef496 ecffe29 bbb5cc7 3462329 50f33da 15012bd 50f33da 3462329 66525d8 69c39e7 15012bd 3462329 15012bd 3462329 15012bd 3462329 15012bd 3462329 15012bd ecffe29 3462329 69c39e7 15012bd 3462329 d0f981b c25c4e9 d0f981b c25c4e9 d0f981b f27384b cb4f957 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 | import torch
import torch.nn.functional as F
import gradio as gr
from PIL import Image
import pickle
import json
from huggingface_hub import hf_hub_download
from model import image_captioning_model
from tokenizer import CaptionTokenizer # Важно!
# Загрузка файлов
repo_id = "Pumponchik/ImageCaption"
repo_type = "space"
model_path = hf_hub_download(repo_id=repo_id, filename="pytorch_model.bin", repo_type=repo_type)
config_path = hf_hub_download(repo_id=repo_id, filename="config.json", repo_type=repo_type)
tokenizer_path = hf_hub_download(repo_id=repo_id, filename="tokenizer.pkl", repo_type=repo_type)
transform_path = hf_hub_download(repo_id=repo_id, filename="image_transforms.pkl", repo_type=repo_type)
# Загрузка конфигурации
with open(config_path, "r") as f:
full_config = json.load(f)
# Фильтрация параметров для модели
model_params = {
"vocab_size": full_config["vocab_size"],
"embedding_dim": full_config["embedding_dim"],
"hidden_size": full_config["hidden_size"],
"num_layers": full_config["num_layers"]
}
# Инициализация модели
model = image_captioning_model(**model_params)
# Загрузка весов модели
model.load_state_dict(torch.load(model_path, map_location="cpu"), strict=False)
device = "cuda" if torch.cuda.is_available() else "cpu"
model.to(device)
model.eval()
tokenizer = CaptionTokenizer.load(tokenizer_path)
# Загрузка трансформаций
with open(transform_path, "rb") as f:
transform = pickle.load(f)
def wrap_text(text, max_width):
words = text.split(" ")
result = [[words[0]]]
for word in words[1:]:
if len(" ".join(result[-1])) + len(word) + 1 > max_width:
result[-1] = " ".join(result[-1])
result.append([])
result[-1].append(word)
result[-1] = " ".join(result[-1])
return "\n".join(result)
def generate(model, image, tokenizer, max_seq_len=20, top_p=None, top_k=1):
assert top_p is None or top_k is None, "Не используйте одновременно top_p и top_k"
model.eval()
device = next(model.parameters()).device
image = transform(image).to(device).unsqueeze(0)
batch_size = image.size(0)
with torch.no_grad():
img_emb = model.img_fe(image)
h_0 = model.img_to_hidden(img_emb).unsqueeze(0).repeat(model.text_fe.num_layers, 1, 1)
c_0 = h_0.clone()
input_token = torch.full((batch_size,), tokenizer.tok_to_ind['<BOS>'], dtype=torch.long, device=device)
result_tokens = [[] for _ in range(batch_size)]
mask = torch.ones(batch_size, dtype=torch.bool, device=device)
for _ in range(max_seq_len):
input_emb = model.text_fe.embedding(input_token).unsqueeze(1)
output, (h_0, c_0) = model.text_fe.rnn(input_emb, (h_0, c_0))
logits = model.fc_out(output.squeeze(1))
probs = F.softmax(logits, dim=-1)
next_tokens = torch.zeros(batch_size, dtype=torch.long, device=device)
for i in range(batch_size):
if not mask[i]:
continue
prob = probs[i]
if top_k is not None:
sorted_probs, sorted_indices = torch.sort(prob, descending=True)
sorted_probs = sorted_probs[:top_k]
sorted_indices = sorted_indices[:top_k]
sorted_probs = sorted_probs / sorted_probs.sum()
next_token_idx = torch.multinomial(sorted_probs, 1)
next_tokens[i] = sorted_indices[next_token_idx]
elif top_p is not None:
sorted_probs, sorted_indices = torch.sort(prob, descending=True)
cumulative_probs = torch.cumsum(sorted_probs, dim=0)
mask_p = cumulative_probs <= top_p
sorted_probs = sorted_probs[mask_p]
sorted_indices = sorted_indices[mask_p]
sorted_probs = sorted_probs / sorted_probs.sum()
next_token_idx = torch.multinomial(sorted_probs, 1)
next_tokens[i] = sorted_indices[next_token_idx]
else:
next_tokens[i] = torch.multinomial(prob, 1)
token_id = next_tokens[i].item()
result_tokens[i].append(token_id)
if token_id == tokenizer.tok_to_ind['<EOS>']:
mask[i] = False
input_token = next_tokens
if not mask.any():
break
result_text = []
for tokens in result_tokens:
caption = " ".join([tokenizer.ind_to_tok.get(t, "<UNK>") for t in tokens
if t not in [tokenizer.tok_to_ind.get("<BOS>", -1),
tokenizer.tok_to_ind.get("<EOS>", -1),
tokenizer.tok_to_ind.get("<PAD>", -1)]])
result_text.append(caption)
return result_text[0] if batch_size == 1 else result_text
def generate_caption(image):
image = image.convert("RGB")
max_seq_len = full_config.get("max_len", 20)
caption = generate(model, image, tokenizer, max_seq_len=max_seq_len, top_k=5)
caption = wrap_text(caption, 43)
return caption
iface = gr.Interface(
fn=generate_caption,
inputs=gr.Image(type="pil", label="Загрузите изображение"),
outputs=gr.Textbox(label="Сгенерированное описание"),
title="Генерация описаний изображений",
description="Загрузите изображение, и модель создаст текстовое описание."
)
iface.launch(
server_name="0.0.0.0",
server_port=7860,
)
|