මෙය PyTorch ක්රියාත්මක කිරීම කඩදාසි ප්රතිපෝෂණ මතකය සමඟ අනුක්රමික ට්රාන්ස්ෆෝමර්වල ඉහළ මට්ටමේ නිරූපණයන් වෙත ප්රවේශ වීම .
සාමාන්යට්රාන්ස්ෆෝමර් සමාන්තරව ටෝකන සකසනවා. සෑම ට්රාන්ස්ෆෝමර් ස්ථරයක්ම පෙර ස්ථරයේ ප්රතිදානයන් කෙරෙහි අවධානය යොමු කරයි. ප්රතිපෝෂණ ට්රාන්ස්ෆෝමරය පෙර පියවරයන්හි සියලුම ස්ථරවල ප්රතිදානය කෙරෙහි අවධානය යොමු කරයි. එබැවින් මෙය පුනරාවර්තනය එකතු කරන අතර, අපි ටෝකන්-විසින්-ටෝකන් සැකසිය යුතුය. මෙය පුහුණුව සැලකිය යුතු ලෙස මන්දගාමී වේ (අනුක්රමයේ දිග අනුව 5X - 10X පමණ). කෙසේ වෙතත්, ප්රතිපෝෂණ ට්රාන්ස්ෆෝමර් පුරෝකථනය කිරීමේදී වේගවත් වන්නේ ඔබ මතක දෛශික හැඹිලි කළහොත් ඊළඟ ටෝකනය පුරෝකථනය කළ හැකි බැවිනි.
පුහුණුවවේගවත් කිරීම සඳහා, කඩදාසි සාකච්ඡා කරන්නේ කෙටි අනුක්රමික දිගකින් ආරම්භ කර එය ක්රමයෙන් වැඩි කිරීමයි. ආරම්භක ස්ථානය ලෙස පෙර පුහුණු සමාන්තර ට්රාන්ස්ෆෝමරයක් භාවිතා කිරීම ද ඔවුහු සාකච්ඡා කරති.
මුල්ප්රතිපෝෂණ ට්රාන්ස්ෆෝමරය සියලු ස්ථරවල ප්රතිදානයන් තබා නොගනී. ඒ වෙනුවට එය සියලු ස්ථරවල නිමැවුමේ බර තැබූ එකතුව තබා ගනී. මෙය අනාවැකිය තුළ හැඹිලි සඳහා භාවිතා කරන මතකය අඩු කරයි. මෙම ගොනුවේ පළමු භාගය මෙය ක්රියාත්මක කරයි.
යාවත්කාලීනකරන ලද ප්රතිපෝෂණ ට්රාන්ස්ෆෝමරය බර බෙදා ගන්නා අතර ස්ථර අතර යතුරු සහ අගයන් ගණනය කිරීමට භාවිතා කරයි. ඉන්පසු අපි එක් එක් පියවර සඳහා යතුරු සහ අගයන් එක් වරක් පමණක් ගණනය කර ඒවා හැඹිලි කර තබමු. මෙම ගොනුවේ දෙවන භාගය මෙය ක්රියාත්මක කරයි. කාර්ය සාධනය වැඩි දියුණු කිරීම සඳහා අපි අභිරුචි PyTorch ශ්රිතයක් ක්රියාත්මක කළෙමු.
කුඩාෂේක්ස්පියර් දත්ත කට්ටලය පිළිබඳ ප්රතිපෝෂණ ට්රාන්ස්ෆෝමරයක් පුහුණු කිරීම සඳහා පුහුණු කේතය සහ සටහන් පොතක් මෙන්න.
43import math
44from typing import Optional
45
46import torch
47from torch import nn
48
49from labml_helpers.module import Module
50from labml_nn.transformers.feed_forward import FeedForward
51from labml_nn.transformers.mha import PrepareForMultiHeadAttention
52from labml_nn.utils import clone_module_listමෙමමොඩියුලය මුල් ට්රාන්ස්ෆෝමර් කඩදාසි වලින් අවධානයට සමාන පුනරාවර්තන අවධානයක් ගණනය කරයි.
55class FeedbackAttention(Module):d_model
ට්රාන්ස්ෆෝමරයේ ඇති ලක්ෂණ ගණන dropout_prob
අවධානය යොමු කිරීමේ සම්භාවිතාව is_kv_precomputed
යතුරද යන්න, අගය ආතතීන් දැනටමත් ගණනය කර ඇත66 def __init__(self, heads: int, d_model: int, dropout_prob: float = 0.1, *,
67 is_kv_precomputed: bool = False):75 super().__init__()හිසකටවිශේෂාංග ගණන
78 self.d_k = d_model // heads80 self.heads = headsමේවා query
බහු-ශීර්ෂ අවධානය පරිවර්තනය කරයි.
83 self.query = PrepareForMultiHeadAttention(d_model, heads, self.d_k, bias=False)මේවාබහු ශීර්ෂ අවධානය value
සඳහා පරිවර්තනය කරයි. key
85 if not is_kv_precomputed:
86 self.key = PrepareForMultiHeadAttention(d_model, heads, self.d_k, bias=False)
87 self.value = PrepareForMultiHeadAttention(d_model, heads, self.d_k, bias=True)යතුරුසහ අගයන් දැනටමත් ගණනය කර ඇත
89 else:
90 self.key = None
91 self.value = Noneප්රතිදානස්ථරය
94 self.output = nn.Linear(d_model, d_model)හැලීම
96 self.dropout = nn.Dropout(dropout_prob)සොෆ්ට්මැක්ස්වලට පෙර පරිමාණ සාධකය
98 self.scale = 1 / math.sqrt(self.d_k)කාලමානය ඔස්සේ අවධානය යොමු කිරීම සඳහා සොෆ්ට්මැක්ස් key
101 self.softmax = nn.Softmax(dim=0)සාපේක්ෂතනතුරු ගණන
104 self.P = 2 ** 12විමසුමටසාපේක්ෂව යතුර සඳහා සාපේක්ෂ ස්ථානීය කාවැද්දීම්.
107 self.key_pos_embeddings = nn.Parameter(torch.zeros((self.P, heads, self.d_k)), requires_grad=True)විමසුමටසාපේක්ෂව යතුර සඳහා සාපේක්ෂ ස්ථානීය කාවැද්දීමේ නැඹුරුව.
109 self.key_pos_bias = nn.Parameter(torch.zeros((self.P, heads)), requires_grad=True)විමසුමසඳහා ස්ථානීය කාවැද්දීම් විමසුමේ පිහිටුමෙන් ස්වාධීන වේ
111 self.query_pos_bias = nn.Parameter(torch.zeros((heads, self.d_k)), requires_grad=True)අවශ්යනම් ලොග් වීම හෝ වෙනත් ගණනය කිරීම් සඳහා භාවිතා කළ හැකි වන පරිදි අපි අවධානය ගබඩා කරමු
114 self.attn = Noneඅපිඅවධානය සඳහා සාපේක්ෂ ස්ථානීය කේතීකරණ භාවිතා කරමු, සාපේක්ෂ බහු-හිස අවධානය ආකෘති ට්රාන්ස්ෆෝමර්-එක්ස්එල් කඩදාසිවලට සමානය.
පියවරප්රධාන වත්මන් පියවර ගේ විමසුම සිට අවධානය (වත්මන් පියවර සාපේක්ෂව) වේ,
මුල්කාවැද්දීම්වල රේඛීය පරිවර්තනයන් වන අතර ස්ථානීය කේතීකරණයේ රේඛීය පරිවර්තනයන් වේ .
අපිපදය වෙනුවට ආදේශ කරමු .
116 def get_scores(self, query: torch.Tensor, key: torch.Tensor):144 key_pos_emb = self.key_pos_embeddings[-key.shape[0]:]146 query_pos_bias = self.query_pos_bias[None, :, :]148 key_pos_bias = self.key_pos_bias[-key.shape[0]:]151 ac = torch.einsum('bhd,jbhd->jbh', query + query_pos_bias, key)153 bd = torch.einsum('bhd,jhd->jbh', query, key_pos_emb) + key_pos_bias[:, None, :]156 return ac + bdquery
හැඩය ඇත [batch_size, d_model]
key
සහ හැඩය value
ඇත [seq_len, batch_size, d_model]
158 def forward(self, *,
159 query: torch.Tensor,
160 key: torch.Tensor,
161 value: torch.Tensor):සූදානම්වන්න query
, key
සහ අවධානය ගණනය කිරීම value
සඳහා key
සහ පසුව හැඩය value
ඇත [seq_len, batch_size, heads, d_k]
සහ හැඩය query
ඇත [batch_size, heads, d_k]
170 query = self.query(query)
171 if self.key:
172 key = self.key(key)
173 if self.value:
174 value = self.value(value)අවධානයලකුණු ගණනය කරන්න. හැඩයේ ආතතියෙන් ප්රති Results ල [seq_len, batch_size, heads]
178 scores = self.get_scores(query, key)පරිමාණලකුණු
181 scores *= self.scaleසොෆ්ට්මැක්ස්
184 attn = self.softmax(scores)අතහැරදැමීම යොදන්න
187 attn = self.dropout(attn)අගයන්අනුව ගුණ කරන්න
190 x = torch.einsum("jbh,jbhd->bhd", attn, value)බහුහිස් සංයුක්ත කරන්න
193 x = x.reshape(x.shape[0], -1)ප්රතිදානස්ථරය
196 return self.output(x)මෙයප්රතිපෝෂණ ට්රාන්ස්ෆෝමරයේ තනි ට්රාන්ස්ෆෝමර් තට්ටුවක් ක්රියාත්මක කරයි.
199class FeedbackTransformerLayer(Module):d_model
ට්රාන්ස්ෆෝමරයේ ඇති ලක්ෂණ ගණන attn
යනු ප්රතිපෝෂණ අවධානය මොඩියුලයයි feed_forward
ස්ථාන-wise ානවන්ත ආහාර ඉදිරි ස්ථරයයි dropout_prob
යනු අවධානය සහ පෝෂණය කිරීමෙන් පසු ස්ථර අතහැර දැමීමේ සම්භාවිතාවයයි206 def __init__(self, *,
207 d_model: int,
208 attn: FeedbackAttention,
209 feed_forward: FeedForward,
210 dropout_prob: float):217 super().__init__()ට්රාන්ස්ෆෝමර්ප්රමාණය
219 self.size = d_model221 self.attn = attn
222 self.feed_forward = feed_forward
223 self.dropout = nn.Dropout(dropout_prob)සාමාන්යකරණයස්ථර
226 self.norm_self_attn = nn.LayerNorm([d_model])
227 self.norm_ff = nn.LayerNorm([d_model])229 def forward(self, *,
230 x: torch.Tensor,
231 key: Optional[torch.Tensor],
232 value: Optional[torch.Tensor]):මතකයක්තිබේ නම්
234 if key is not None:ස්වයංඅවධානය යොමු කිරීමට පෙර දෛශික සාමාන්යකරණය කරන්න
236 z = self.norm_self_attn(x)ස්වයංඅවධානය හරහා ධාවනය කරන්න, i.e. යතුරු සහ වටිනාකම් ස්වයං සිට
238 self_attn = self.attn(query=z, key=key, value=value)ස්වයංඅවධානය ප්රතිඵල එකතු
240 x = x + self.dropout(self_attn)පෝෂණයසඳහා සාමාන්යකරණය කරන්න
243 z = self.norm_ff(x)Feed-forwardජාලය හරහා ගමන් කරන්න
245 ff = self.feed_forward(z)ප්රතිපෝෂණඉදිරි ප්රති results ල නැවත එක් කරන්න
247 x = x + self.dropout(ff)250 return x253class FeedbackTransformer(Module):layer
අපි එක් එක් ස්ථරයක් සඳහා පරිගණක ක්රිඩාවට සමාන වන ප්රතිපෝෂණ ට්රාන්ස්ෆෝමර් ස්ථරය, වේ n_layers
ට්රාන්ස්ෆෝමරයේ ස්ථර ගණන258 def __init__(self, layer: FeedbackTransformerLayer, n_layers: int):264 super().__init__()ට්රාන්ස්ෆෝමර්ස්ථරයේ පිටපත් සාදන්න
266 self.layers = clone_module_list(layer, n_layers)අවසානසාමාන්යකරණ ස්තරය
268 self.norm = nn.LayerNorm([layer.size])මතකදෛශික ගණනය කරනු ලබන්නේ එක් එක් ස්ථරයේ නිරූපණවල බර කිරන ලද එකතුවකි. ඒ සඳහා බර පරාමිතිය මෙයයි.
271 self.weights = nn.Parameter(torch.ones(n_layers + 1), requires_grad=True)බරතැබූ මුදල ගැනීමට පෙර බර සඳහා සොෆ්ට්මැක්ස්
273 self.softmax = nn.Softmax(0)x_seq
හැඩය සහිත ආදානය වේ [seq_len, batch_size, d_model]
275 def forward(self, x_seq: torch.Tensor):අනුක්රමිකඅක්ෂය දිගේ ලැයිස්තුවකට ආදානය බෙදන්න
281 x_seq = torch.unbind(x_seq, dim=0)ප්රතිදානයන්ගබඩා කිරීම සඳහා ලැයිස්තුව
283 res = []මතකදෛශික ගබඩා කිරීමට ලැයිස්තුව
285 mem = []එක්එක් ආදාන පියවර සඳහා
287 for x in x_seq:ස්ථරප්රතිදානයන් ගබඩා කිරීම සඳහා ලැයිස්තුව
289 layer_outputs = [x]මතකයක්තිබේ නම්, ඒවා දෛශිකයකට ගොඩගසන්න
292 mem_tensor = torch.stack(mem) if mem else Noneඑක්එක් ස්ථරය හරහා ධාවනය කරන්න
295 for layer in self.layers:ස්ථරප්රතිදානය ලබා ගන්න
297 x = layer(x=x, key=mem_tensor, value=mem_tensor)ස්ථරප්රතිදානයන් ලැයිස්තුවට ඒවා එකතු කරන්න
299 layer_outputs.append(x)ස්ථරයේප්රතිදානයන් ටෙන්සරයකට ගොඩගසන්න
302 layer_outputs = torch.stack(layer_outputs)ස්ථරප්රතිදානවල බර තැබූ එකතුවක් ලෙස මතක දෛශිකය ගණනය කරන්න
304 mem.append(torch.einsum('lbd,l->bd', layer_outputs, self.softmax(self.weights)))ප්රති. ල සඳහා ප්රතිදානය එක් කරන්න
306 res.append(x)නිමැවුම්ආතතීන් ගොඩගසන්න
309 res = torch.stack(res)ප්රතිදානයසාමාන්යකරණය කරන්න
311 return self.norm(res)අපිpython ලැයිස්තුවකට appending හා පසුව කරන්නේ වෙනුවට අභිරුචි ශ්රිතයක් ක්රියාත්මක torch.stack
. මෙම බොහෝ සෙයින් අනුක්රමය ඔස්සේ එක් එක් පියවර torch.stack
දී ඉල්ලා පුරා කාර්ය සාධනය වැඩි දියුණු කරන ලදි. සෑම විටම කැඳවනු torch.stack
ලැබේ, එය නව ආතතියක් නිර්මාණය කරයි, මෙම ක්රමය සහ ඒ සමඟ ඇති පන්ති Stack
කොටස් මතකය එක් එක් පියවර සඳහා.
318class StackFunction(torch.autograd.Function):ctx
යනු ශ්රිතයේ සන්දර්භය (එය අපට හැඹිලි දේවල් වලට ඉඩ දෙයි) memory
යනු හවුල් මතක ටෙන්සරය වන අතර එහිදී අපි එක් එක් පියවරේ අගයන් ගබඩා කර ගබඩා කරමු (යතුරු සහ අගයන්) memory_grad
යනු එක් එක් පියවරේ අනුක්රමික ගබඩා කිරීම හා රැස් කිරීම සඳහා හවුල් මතක ආතතියකි last
අවසාන අගය ගොඩගැසී ඇත n
පියවර ගණන (එනම් අඩුක්කුව ප්රමාණය)මෙයපියවර සඳහා ගොඩගැසී ඇති ටෙන්සරය නැවත ලබා දෙයි n
.
330 @staticmethod
331 def forward(ctx, memory, memory_grad, last, n):හැඹිලිසමුච්චිත අනුක්රමික
343 ctx._mem_grad = memory_gradතොගයේප්රමාණය හැඹිලිය
345 ctx._n = nතොගයආපසු දෙන්න
347 return memory[:n + 1]grad_output
forward
ශ්රිතයේ ප්රතිදානය සම්බන්ධයෙන් ශ්රේණිය වේමෙයහවුල් මතක ටෙන්සරයේ ඇති අනුක්රමික සමුච්චය වන අතර තොගයේ last
ප්රති result ලය සම්බන්ධයෙන් අනුක්රමික ආපසු ලබා දෙන්න.
349 @staticmethod
350 def backward(ctx, grad_output):තොගයේවත්මන් ප්රමාණය ලබා ගන්න
358 n = ctx._nසමුච්චිතඅනුක්රමික ලබා ගන්න
360 memory_grad = ctx._mem_gradඅනුක්රමිකඑකතු කරන්න
362 memory_grad[:n + 1] += grad_outputW.r.tඅනුක්රමික තොගයේ අවසාන අගය වෙත ආපසු ලබා දෙන්න
364 return None, None, memory_grad[n], None367class Stack:max_len
අඩුක්කුව උපරිම ප්රමාණය374 def __init__(self, max_len: int):378 self.max_len = max_len
379 self.memory = None
380 self.memory_grad = None
381 self.last = None
382 self.n = -1
383 self.last_get_n = -1n
අඩුක්කුව ප්රමාණය වේ value
අඩුක්කුව එකතු කළ යුතු බව tensor වේ385 def append(self, n: int, value: torch.Tensor):අගයක්එකතු කිරීමෙන් පසු ඔබට අඩුක්කුව ලබා ගත යුතුය (භාවිතා කරන්න). එසේ නොමැතිනම් මෙම ක්රියාත්මක කිරීම අසමත් වේ
393 assert n == 0 or self.last_get_n == n - 1, f"{n}, {self.last_get_n}"අනුක්රමිකනොමැතිව මෙය කරන්න
396 with torch.no_grad():තොගයතබා ගැනීම සඳහා හවුල් මතක ටෙන්සරය ආරම්භ කරන්න
398 if self.memory is None or self.memory.shape[1:] != value.shape:මෙයසිදුවිය යුත්තේ තොගය හිස් වූ විට පමණි
400 assert n == 0අඩුක්කුවසඳහා ටෙන්සරයක් සාදන්න
402 self.memory = value.new_zeros(self.max_len, *value.shape, requires_grad=False)අනුක්රමිකසමුච්චය කිරීමට tensor සාදන්න
404 self.memory_grad = value.new_zeros(self.memory.shape, requires_grad=False)මතකයදැනටමත් ආරම්භ කර ඇති නමුත් අපි තොගය නැවත සකසමින් සිටිමු.
මෙයතවත් කාර්යයක් විය හැකිය reset
, නමුත් මෙය භාවිතා කිරීම පහසු බව අපට පෙනී ගියේය.
409 elif n == 0:සමුච්චිතඅනුක්රමික නැවත සකසන්න
411 self.memory_grad.fill_(0.)තොගයේනිවැරදි ස්ථානයේ වටිනාකම සකසන්න
414 self.memory.data[n] = value.detach()(නිදොස්කරණය සඳහා) අඩුක්කුව පිළිබඳ වාර්තාවක් තබා ගන්න
416 self.n = nතොගයටඑකතු කරන ලද අවසාන අගය පිළිබඳ වාර්තාවක් තබා ගන්න. ආපස්සට ප්රචාරය කිරීම සඳහා අපට මෙය සම්මත කර ගත යුතුය. StackFunction
421 self.last = valueතොගයආපසු ලබා දෙයි
423 def get(self):එයභාවිතා කරන විට අඩුක්කුව ප්රමාණය පිළිබඳ වාර්තාවක් තබා ගන්න. මෙය සනීපාරක්ෂක පරීක්ෂණයක් සඳහා භාවිතා වේ append
.
430 self.last_get_n = self.nපසුපසටප්රචාරණය කිරීමේදී PyTorch විසින් කැඳවනු ලබන StackFunction
ඒ StackFunction.backwards
සියල්ල හරහා ගන්න.
433 return StackFunction.apply(self.memory, self.memory_grad, self.last, self.n)මතකයමුදා හැරීමට
435 def free(self):440 self.memory = None
441 self.memory_grad = None
442 self.last = Noneයතුරුසහ අගයන් හැඹිලි කරන යාවත්කාලීන කරන ලද ප්රතිපෝෂණ ට්රාන්ස්ෆෝමර් මොඩියුලය මෙයයි.
445class FeedbackTransformerKV(Module):layer
අපි එක් එක් ස්ථරයක් සඳහා පරිගණක ක්රිඩාවට සමාන වන ප්රතිපෝෂණ ට්රාන්ස්ෆෝමර් ස්ථරය, වේ n_layers
ට්රාන්ස්ෆෝමරයේ ස්ථර ගණන d_model
ට්රාන්ස්ෆෝමරයේ ඇති ලක්ෂණ ගණන 452 def __init__(self, layer: FeedbackTransformerLayer, n_layers: int, d_model: int, heads: int):460 super().__init__()ට්රාන්ස්ෆෝමර්ස්ථරයේ පිටපත් සාදන්න
462 self.layers = clone_module_list(layer, n_layers)අවසානසාමාන්යකරණ ස්තරය
464 self.norm = nn.LayerNorm([layer.size])මතකදෛශික ගණනය කරනු ලබන්නේ එක් එක් ස්ථරයේ නිරූපණවල බර කිරන ලද එකතුවකි. ඒ සඳහා බර පරාමිතිය මෙයයි.
467 self.weights = nn.Parameter(torch.ones(n_layers + 1), requires_grad=True)බරතැබූ මුදල ගැනීමට පෙර බර සඳහා සොෆ්ට්මැක්ස්
469 self.softmax = nn.Softmax(0)හිසෙහිවිශේෂාංග ගණන
472 d_k = d_model // headsයතුරුලබා ගැනීම සඳහා කාවැද්දීම් (මතකය) පරිවර්තනය කිරීමේ මොඩියුලය
474 self.key = PrepareForMultiHeadAttention(d_model, heads, d_k, bias=False)යතුරුලබා ගැනීම සඳහා කාවැද්දීම් (මතකය) පරිවර්තනය කිරීමේ මොඩියුලය
476 self.value = PrepareForMultiHeadAttention(d_model, heads, d_k, bias=False)සිරස්වඇති යතුරු සඳහා මතකය
479 self.mem_key = Stack(512)සිරස්වඇති අගයන් සඳහා මතකය
481 self.mem_value = Stack(512)x_seq
හැඩය සහිත ආදානය වේ [seq_len, batch_size, d_model]
483 def forward(self, x_seq: torch.Tensor):අනුක්රමිකඅක්ෂය දිගේ ලැයිස්තුවකට ආදානය බෙදන්න
489 x_seq = torch.unbind(x_seq, dim=0)ප්රතිදානයන්ගබඩා කිරීම සඳහා ලැයිස්තුව
491 res = []එක්එක් ආදාන පියවර සඳහා
493 for step, x in enumerate(x_seq):ස්ථරප්රතිදානයන් ගබඩා කිරීම සඳහා ලැයිස්තුව
495 layer_outputs = [x]යතුරුසහ වටිනාකම් තොගයක්
498 key_tensor = None
499 value_tensor = Noneඅපිආරම්භක පියවර ඔබ්බට නම් යතුරු සහ අගයන් tensors ලබා ගන්න
501 if step > 0:
502 key_tensor = self.mem_key.get()
503 value_tensor = self.mem_value.get()එක්එක් ස්ථරය හරහා ධාවනය කරන්න
506 for layer in self.layers:ස්ථරප්රතිදානය ලබා ගන්න
508 x = layer(x=x, key=key_tensor, value=value_tensor)ස්ථරප්රතිදානයන් ලැයිස්තුවට ඒවා එකතු කරන්න
510 layer_outputs.append(x)ස්ථරයේප්රතිදානයන් ටෙන්සරයකට ගොඩගසන්න
513 layer_outputs = torch.stack(layer_outputs)ස්ථරප්රතිදානවල බර තැබූ එකතුවක් ලෙස මතක දෛශිකය ගණනය කරන්න
515 mem = torch.einsum('lbd,l->bd', layer_outputs, self.softmax(self.weights))මතකයෙන්යතුරු ගණනය කර එය තොගයට එක් කරන්න
517 self.mem_key.append(step, self.key(mem))මතකයෙන්අගයන් ගණනය කර එය තොගයට එක් කරන්න
519 self.mem_value.append(step, self.value(mem))ප්රති. ල සඳහා ප්රතිදානය එක් කරන්න
521 res.append(x)නිමැවුම්ආතතීන් ගොඩගසන්න
524 res = torch.stack(res)ප්රතිදානයසාමාන්යකරණය කරන්න
526 return self.norm(res)528 def free(self):
529 self.mem_key.free()
530 self.mem_value.free()