1+ #include " RuCLIP.h"
2+
3+ ResidualAttentionBlockImpl :: ResidualAttentionBlockImpl(const std::string &module_name, const int d_model, const int n_head, const torch::Tensor &attn_mask)
4+ : torch::nn::Module(module_name)
5+ {
6+ Attn = torch::nn::MultiheadAttention (d_model, n_head);
7+ Ln1 = RCLayerNorm (std::vector<int64_t >() = { (int64_t )d_model });
8+ Mlp = torch::nn::Sequential ({
9+ {" c_fc" , torch::nn::Linear (d_model, d_model * 4 )},
10+ {" gelu" , QuickGELU ()},
11+ {" c_proj" , torch::nn::Linear (d_model * 4 , d_model)}
12+ });
13+ Ln2 = RCLayerNorm (std::vector<int64_t >() = { (int64_t )d_model });
14+ AttnMask = attn_mask;
15+
16+ register_module (" attn" , Attn);
17+ register_module (" ln_1" , Ln1);
18+ register_module (" mlp" , Mlp);
19+ register_module (" ln_2" , Ln2);
20+ // register_buffer("attn_mask", AttnMask);
21+ }
22+
23+ torch::Tensor ResidualAttentionBlockImpl :: Attention(const torch::Tensor &x)
24+ {
25+ if (AttnMask.defined () && (AttnMask.numel () != 0 ))
26+ AttnMask = AttnMask.to (x.dtype ()).to (x.device ());
27+ /* return Attn(x, x, x, weights = False, attn_mask = self.attn_mask)[0];*/
28+ // std::tuple<Tensor, Tensor> forward(const Tensor & query, const Tensor & key, const Tensor & value, const Tensor & key_padding_mask = {}, bool need_weights = true, const Tensor & attn_mask = {}, bool average_attn_weights = true)
29+ return std::get<0 >(Attn->forward (x, x, x, {}, false , AttnMask));
30+ }
31+
32+ torch::Tensor ResidualAttentionBlockImpl :: forward(const torch::Tensor &x)
33+ {
34+ auto result = x + Attention (Ln1 (x));
35+ result = result + Mlp->forward (Ln2 (result));
36+ return result;
37+ }
38+
39+
40+
41+ TransformerImpl :: TransformerImpl(const std::string &module_name, const int width, const int layers, const int heads, const torch::Tensor &attn_mask /* = torch::Tensor()*/ )
42+ : torch::nn::Module(module_name), Width(width), Layers(layers), Heads(heads)/* , AttnMask(attn_mask)*/
43+ {
44+ for (int i = 0 ; i < layers; i++)
45+ Resblocks->push_back (ResidualAttentionBlock (module_name + " _" + std::to_string (i), width, heads, attn_mask));
46+
47+ register_module (" resblocks" , Resblocks); // ???
48+ // for (int i = 0; i < Resblocks->size(); i++)
49+ // register_module(module_name + "_res_attn_block_" + std::to_string(i), Resblocks[i]);
50+ }
51+
52+ torch::Tensor TransformerImpl :: forward(const torch::Tensor& x)
53+ {
54+ // !!!Сделать проверку и преобразование if (x.type() != )
55+ return Resblocks->forward (x);
56+ }
57+
58+ void TransformerImpl :: InitializeParameters()
59+ {
60+ float proj_std = powf (Width, -0 .5f ) * pow (2 * Layers, -0 .5f );
61+ float attn_std = powf (Width, -0 .5f );
62+ float fc_std = powf (2 * Width, -0 .5f );
63+
64+ for (int i = 0 ; i < Resblocks->size (); i++)
65+ {
66+ auto block = Resblocks[i]->as <ResidualAttentionBlock>();
67+ torch::nn::init::normal_ (block->GetAttn ()->in_proj_weight , 0 ., attn_std);
68+ torch::nn::init::normal_ (block->GetAttn ()->out_proj ->weight , 0 ., proj_std);
69+ auto mlp = block->GetMlp ();
70+ for (int j = 0 ; j < mlp->size (); j++)
71+ {
72+ if (mlp[j]->name () == " c_fc" )
73+ torch::nn::init::normal_ (mlp[j]->as <torch::nn::Linear>()->weight , 0 ., fc_std);
74+ if (mlp[j]->name () == " c_proj" )
75+ torch::nn::init::normal_ (mlp[j]->as <torch::nn::Linear>()->weight , 0 ., proj_std);
76+ }
77+ }
78+ }
79+
80+
81+
82+ VisionTransformerImpl :: VisionTransformerImpl(
83+ const std::string &module_name,
84+ const int input_resolution,
85+ const int patch_size,
86+ const int width,
87+ const int layers,
88+ const int heads,
89+ const int output_dim
90+ ) : torch::nn::Module(module_name), InputResolution(input_resolution), OutputDim(output_dim)
91+ {
92+ Conv1 = torch::nn::Conv2d (torch::nn::Conv2dOptions (3 , width, patch_size).stride (patch_size).bias (false ));
93+ float scale = powf (width, -0.5 );
94+ ClassEmbedding = scale * torch::randn (width);
95+ PositionalEmbedding = scale * torch::randn ({ (int )pow (input_resolution / patch_size/* деление нацело*/ , 2 ) + 1 , width });
96+ LnPre = RCLayerNorm (std::vector<int64_t >() = { (int64_t )width });
97+ VTTransformer = Transformer (" visual" , width, layers, heads);
98+ LnPost = RCLayerNorm (std::vector<int64_t >() = { (int64_t )width });
99+ Proj = scale * torch::randn ({ width, output_dim });
100+
101+ register_buffer (" class_embedding" , ClassEmbedding);
102+ register_buffer (" positional_embedding" , PositionalEmbedding);
103+ register_buffer (" proj" , Proj);
104+ register_module (" conv1" , Conv1);
105+ register_module (" ln_pre" , LnPre);
106+ register_module (" ln_post" , LnPost);
107+ register_module (" transformer" , VTTransformer);
108+ }
109+
110+ torch::Tensor VisionTransformerImpl :: forward(const torch::Tensor &x)
111+ {
112+ // !!!Сделать проверку и преобразование if (x.type() != )
113+ auto res = Conv1 (x); // shape = [*, width, grid, grid]
114+ res = res.reshape ({ res.sizes ()[0 ], res.sizes ()[1 ], -1 }); // shape = [*, width, grid **2]
115+ res = res.permute ({ 0 , 2 , 1 }); // shape = [*, grid **2, width]
116+ res = torch::cat ({
117+ ClassEmbedding.to (res.dtype ()) + torch::zeros ({res.sizes ()[0 ], 1 , res.sizes ().back ()}, res.dtype ()).to (x.device ()),
118+ res
119+ }, 1 ); // shape = [*, grid **2 + 1, width]
120+ res = res + PositionalEmbedding.to (res.dtype ());
121+ res = LnPre (res);
122+ res = res.permute ({ 1 , 0 , 2 }); // NLD->LND
123+ res = VTTransformer (res);
124+ res = res.permute ({ 1 , 0 , 2 }); // LND->NLD
125+ res = LnPost (res.index ({ torch::indexing::Slice (), 0 , torch::indexing::Slice () }));
126+ if (Proj.defined () && Proj.numel () != 0 )
127+ res = torch::mm (res, Proj);
128+ return res;
129+ }
130+
131+
132+
133+ CLIPImpl :: CLIPImpl(
134+ const std::string &module_name,
135+ const int embed_dim,
136+ const int image_resolution,
137+ const int vision_layers,
138+ const int vision_width,
139+ const int vision_patch_size,
140+ const int context_length,
141+ const int vocab_size,
142+ const int transformer_width,
143+ const int transformer_heads,
144+ const int transformer_layers,
145+ const int eos_id /* = 3*/
146+ ) : torch::nn::Module(module_name), EosId(eos_id), ContextLength(context_length), VocabSize(vocab_size), TransformerWidth(transformer_width), TransformerLayers(transformer_layers)
147+ {
148+ int vision_heads = vision_width / 64 ;
149+ Visual = VisionTransformer (" visual" , image_resolution, vision_patch_size, vision_width, vision_layers, vision_heads, embed_dim);
150+ NVTransformer = Transformer (" transformer" , transformer_width, transformer_layers, transformer_heads, BuildAttentionMask ());
151+
152+ TokenEmbedding = torch::nn::Embedding (vocab_size, transformer_width);
153+ PositionalEmbedding = torch::empty ({ context_length, transformer_width }); // !!!type, device
154+
155+ std::cout << " transformer_width: " << transformer_width<< std::endl;
156+
157+ LnFinal = RCLayerNorm (std::vector<int64_t >() = { (int64_t )transformer_width });
158+ TextProjection = torch::empty ({ transformer_width, embed_dim }); // !!!type, device
159+ LogitScale = torch::ones ({}) * logf (1 .f / 0 .07f );
160+
161+ register_module (" visual" , Visual);
162+ register_module (" transformer" , NVTransformer);
163+ register_module (" token_embedding" , TokenEmbedding);
164+ register_module (" ln_final" , LnFinal);
165+ register_buffer (" positional_embedding" , PositionalEmbedding);
166+ register_buffer (" text_projection" , TextProjection);
167+ register_buffer (" logit_scale" , LogitScale);
168+
169+ InitializeParameters ();
170+ }
171+
172+ void CLIPImpl :: InitializeParameters()
173+ {
174+ torch::nn::init::normal_ (TokenEmbedding->weight , 0 ., 0.02 );
175+ torch::nn::init::normal_ (PositionalEmbedding, 0 ., 0.01 );
176+ NVTransformer->InitializeParameters ();
177+ if (TextProjection.defined () && TextProjection.numel () != 0 )
178+ torch::nn::init::normal_ (TextProjection, 0 ., pow (TransformerWidth, -0.5 ));
179+ }
180+
181+ torch::Tensor CLIPImpl :: BuildAttentionMask()
182+ {
183+ auto mask = torch::empty ({ ContextLength, ContextLength });
184+ mask.fill_ (-std::numeric_limits<float >::infinity ());
185+ mask.triu_ (1 );
186+ return mask;
187+ }
188+
189+ // /pixel_values : torch::Tensor Processed images from RuCLIPProcessor class, out: image_latents : torch::Tensor Image embeddings
190+ torch::Tensor CLIPImpl :: EncodeImage(torch::Tensor pixel_values)
191+ {
192+ return Visual (pixel_values);
193+ }
194+
195+ // /input_ids : torch::Tensor Tokenized texts from RuCLIPProcessor class, out: text_latents : torch::Tensor Text embeddings
196+ torch::Tensor CLIPImpl :: EncodeText(torch::Tensor input_ids)
197+ {
198+ auto x = TokenEmbedding (input_ids); // .type(dtype()) // [batch_size, n_ctx, d_model]
199+ x = x + PositionalEmbedding; // .type(dtype())
200+ x = x.permute ({ 1 , 0 , 2 }); // NLD->LND
201+ x = NVTransformer (x);
202+ x = x.permute ({ 1 , 0 , 2 }); // LND->NLD
203+ x = LnFinal (x); // type(self.dtype) //x.shape = [batch_size, n_ctx, transformer.width]
204+ x = torch::mm (x.index ({ torch::arange (x.sizes ()[0 ]), torch::where (input_ids == EosId)[1 ] }), TextProjection);
205+ return x;
206+ }
207+
208+ torch::Tensor CLIPImpl :: forward(torch::Tensor input_ids, torch::Tensor pixel_values)
209+ {
210+ auto image_features = EncodeImage (pixel_values);
211+ auto text_features = EncodeText (input_ids);
212+
213+ // normalize features
214+ image_features = image_features / image_features.norm (2 /* L2*/ , -1 , true );
215+ text_features = text_features / text_features.norm (2 /* L2*/ , -1 , true );
216+
217+ // cosine similarity as logits
218+ auto scale = LogitScale.exp ();
219+ auto logits_per_image = scale * torch::mm (image_features, text_features.t ());
220+ auto logits_per_text = logits_per_image.t ();
221+
222+ return logits_per_image;
223+ }
0 commit comments