මෙයකඩදාසි ස්විච් ට්රාන්ස්ෆෝමර්වල කුඩා පයිටෝච් ක්රියාත්මක කිරීමකි: සරල හා කාර්යක්ෂම ස්පාර්ටිටි සහිත ට්රිලියන පරාමිති ආකෘති වලට පරිමාණය කිරීම. අපගේ ක්රියාත්මක කිරීම සඳහා ඇත්තේ පරාමිතීන් මිලියන කිහිපයක් පමණක් වන අතර සමාන්තරව බෙදා හරින ලද පුහුණුව ආදර්ශයට නොගනී. එය තනි GPU පුහුණුව කරන්නේ, නමුත් අපි කඩදාසි විස්තර කර ඇති පරිදි මාරුවීමේ සංකල්පය ක්රියාත්මක කරමු.
ස්විච්ට්රාන්ස්ෆෝමරය ටෝකනය මත පදනම්ව පරාමිතීන් අතර මාරුවීමෙන් එක් එක් ටෝකනය සඳහා විවිධ පරාමිතීන් භාවිතා කරයි. එබැවින්, එක් එක් ටෝකනය සඳහා තෝරා ගනු ලබන්නේ පරාමිතීන්ගෙන් කොටසක් පමණි. එබැවින් ඔබට වැඩි පරාමිතීන් තිබිය හැකි නමුත් අඩු පරිගණකමය පිරිවැයක් ඇත.
මාරුවීමසිදුවන්නේ එක් එක් ට්රාන්ස්ෆෝමර් බ්ලොක් එකේ ස්ථාන-නැණවත් Feedforward ජාලයේ (FFN) ය. ස්ථාන-නැණවත් පෝෂක ජාලය අනුක්රමිකව පූර්ණ සම්බන්ධිත ස්ථර දෙකකින් සමන්විත වේ. ස්විච් ට්රාන්ස්ෆෝමරයේ අපට FFNs (බහු විශේෂ experts යින්) කිහිපයක් ඇති අතර, රවුටරයක් මත පදනම්ව භාවිතා කළ යුත්තේ කුමන එකද යන්න අපි තෝරා ගත්තෙමු. ප්රතිදානය යනු එෆ්එෆ්එන් තෝරා ගැනීම සඳහා වන සම්භාවිතාවන් සමූහයක් වන අතර, අපි ඉහළම සම්භාවිතාව ඇති එකක් තෝරාගෙන එය ඇගයීමට ලක් කරමු. එබැවින් අත්යවශ්යයෙන්ම පරිගණකමය පිරිවැය තනි එෆ්එෆ්එන් එකක් තිබීම හා සමාන වේ. අපගේ ක්රියාත්මක කිරීමේදී මෙය ඔබට බොහෝ හෝ විශාල එෆ්එෆ්එන්එස් ඇති විට සමාන්තරගත නොවේ. බෙදා හරින ලද සැකසුමක ඔබට එක් එක් FFN (සෑම ඉතා විශාල) වෙනත් උපාංගයක ඇත.
විශේෂexperts යන් (එෆ්එෆ්එන්එස්) අතර බර සමතුලිත කිරීම සඳහා කඩදාසි තවත් පාඩු යෙදුමක් හඳුන්වා දෙන අතර රවුටින් සමතුලිත නොවන විට ටෝකන අතහැර දැමීම සාකච්ඡා කරයි.
කුඩාෂේක්ස්පියර් දත්ත කට්ටුවේ ස්විච් ට්රාන්ස්ෆෝමරයක් පුහුණු කිරීම සඳහා පුහුණු කේතය සහ සටහන් පොතක් මෙන්න.
40import torch
41from torch import nn
42
43from labml_helpers.module import Module
44from labml_nn.transformers.feed_forward import FeedForward
45from labml_nn.transformers.mha import MultiHeadAttention
46from labml_nn.utils import clone_module_list49class SwitchFeedForward(Module):capacity_factor
පරමාදර්ශී සමබර බරට සාපේක්ෂව සාධකයක් ලෙස එක් එක් විශේෂ expert යාගේ ධාරිතාවයි drop_tokens
ධාරිතාවයට වඩා වැඩි ටෝකන විශේෂ expert යෙකු වෙත යොමු කළහොත් ටෝකන අතහැර දැමිය යුතුද යන්න නියම කරයි is_scale_prob
රවුටින් සම්භාවිතාව අනුව එෆ්එෆ්එන් වෙත ආදානය ගුණ කළ යුතුද යන්න නියම කරයි n_experts
විශේෂඥයන් සංඛ්යාව expert
විශේෂ expert ස්තරය, එෆ්එෆ්එන් මොඩියුලයකි d_model
යනු ටෝකන කාවැද්දීම තුළ ඇති විශේෂාංග ගණන d_ff
යනු FFN හි සැඟවුණු ස්ථරයේ ඇති ලක්ෂණ ගණන dropout
FFN හි අතහැර දැමීමේ සම්භාවිතාව54 def __init__(self, *,
55 capacity_factor: float,
56 drop_tokens: bool,
57 is_scale_prob: bool,
58 n_experts: int,
59 expert: FeedForward,
60 d_model: int):71 super().__init__()
72
73 self.capacity_factor = capacity_factor
74 self.is_scale_prob = is_scale_prob
75 self.n_experts = n_experts
76 self.drop_tokens = drop_tokensFFNsහි පිටපත් සාදන්න
79 self.experts = clone_module_list(expert, n_experts)රවුටින්ස්තරය සහ සොෆ්ට්මැක්ස්
81 self.switch = nn.Linear(d_model, n_experts)
82 self.softmax = nn.Softmax(dim=-1)x
හැඩය සහිත මාරුවීමේ මොඩියුලයට ආදානය වේ [seq_len, batch_size, d_model]
84 def forward(self, x: torch.Tensor):පසුවහැඩයන් වෙනස් කිරීම සඳහා හැඩය අල්ලා ගන්න
90 seq_len, batch_size, d_model = x.shapeඅනුක්රමයසහ කණ්ඩායම් මානයන් සමතලා කරන්න
92 x = x.view(-1, d_model)එක්එක් ටෝකන සඳහා මාර්ගගත කිරීමේ සම්භාවිතාව ලබා ගන්න. විශේෂ experts යන්ගේ සංඛ්යාව n_experts
කොතැනද සහ ටෝකන් කාවැද්දීම් රේඛීය පරිවර්තනය වේ.
98 route_prob = self.softmax(self.switch(x))උපරිමමාර්ගගත කිරීමේ සම්භාවිතාව සහ මාර්ග ලබා ගන්න. අපි ඉහළම සම්භාවිතාව සහිත විශේෂ expert යා වෙත ගමන් කරමු
102 route_prob_max, routes = torch.max(route_prob, dim=-1)එක්එක් විශේෂ. යා වෙත යන ටෝකන වල දර්ශක ලබා ගන්න
105 indexes_list = [torch.eq(routes, i).nonzero(as_tuple=True)[0] for i in range(self.n_experts)]ප්රතිදානයන්ගබඩා කිරීම සඳහා හිස් ටෙන්සරයක් ආරම්භ කරන්න
108 final_output = x.new_zeros(x.shape)එක්එක් විශේෂඥයාගේ ධාරිතාව.
114 capacity = int(self.capacity_factor * len(x) / self.n_experts)එක්එක් විශේෂ. යා වෙත යොමු කරන ලද ටෝකන ගණන.
116 counts = x.new_tensor([len(indexes_list[i]) for i in range(self.n_experts)])පහතවැටුණු ටෝකන වල හිස් ලැයිස්තුවක් ආරම්භ කරන්න
119 dropped = []නම්පමණක් ටෝකන drop_tokens
අතහරින්න True
.
121 if self.drop_tokens:එක්එක් විශේෂ. යන් තුළ ටෝකන අතහරින්න
123 for i in range(self.n_experts):විශේෂexpert යා ධාරිතාව වැඩි නොවේ නම් නොසලකා හරින්න
125 if len(indexes_list[i]) <= capacity:
126 continueඅතහැරදැමීමට පෙර දර්ශක කලවම් කරන්න
128 indexes_list[i] = indexes_list[i][torch.randperm(len(indexes_list[i]))]පහතවැටුණු ටෝකන ලෙස ධාරිතාවයට වඩා ටෝකන එකතු කරන්න
130 dropped.append(indexes_list[i][capacity:])විශේෂexpert යාගේ ධාරිතාව දක්වා ටෝකන පමණක් තබා ගන්න
132 indexes_list[i] = indexes_list[i][:capacity]විශේෂexpert එෆ්එෆ්එන්එස් හි ප්රතිදානයන් ලබා ගන්න
135 expert_output = [self.experts[i](x[indexes_list[i], :]) for i in range(self.n_experts)]අවසානනිමැවුමට පවරන්න
138 for i in range(self.n_experts):
139 final_output[indexes_list[i], :] = expert_output[i]පහතවැටුණු ටෝකන හරහා යන්න
142 if dropped:
143 dropped = torch.cat(dropped)
144 final_output[dropped, :] = x[dropped, :]
145
146 if self.is_scale_prob:සම්භාවිතාවවිසින් විශේෂඥ ප්රතිදානයන් විසින් ගුණ
148 final_output = final_output * route_prob_max.view(-1, 1)
149 else:අගයන්පරිමාණය නොකරන්න, එවිට අනුක්රමික ගලා යන පරිදි ගුණ කරන්න (මෙය අප අත්හදා බැලූ දෙයකි).
152 final_output = final_output * (route_prob_max / route_prob_max.detach()).view(-1, 1)අවසානනිමැවුමේ හැඩය නැවත වෙනස් කරන්න [seq_len, batch_size, d_model]
155 final_output = final_output.view(seq_len, batch_size, d_model)ආපසු
බරතුලනය කිරීමේ අලාභය සහ ලොග් වීම සඳහා මේවා භාවිතා වේ
166 return final_output, counts, route_prob.sum(0), len(dropped), route_prob_maxස්විච්පෝෂක මොඩියුලයේ අමතර ප්රතිදානයන් හැසිරවීමත් සමඟ මෙය සාමාන්ය ට්රාන්ස්ෆෝමර් කොටුවට සමාන වේ.
169class SwitchTransformerLayer(Module):d_model
ටෝකනය කාවැද්දීමේ ප්රමාණයයි attn
අවධානය යොමු මොඩියුලය වේ feed_forward
යනු ආහාර ඉදිරි මොඩියුලයයි (මෙම නඩුවේ මාරුවීමේ මොඩියුලය වන) dropout_prob
ස්වයං අවධානයෙන් පසු ඉවත් වීමේ සම්භාවිතාව සහ FFN177 def __init__(self, *,
178 d_model: int,
179 attn: MultiHeadAttention,
180 feed_forward: SwitchFeedForward,
181 dropout_prob: float):188 super().__init__()
189 self.size = d_model
190 self.attn = attn
191 self.feed_forward = feed_forward
192 self.dropout = nn.Dropout(dropout_prob)
193 self.norm_self_attn = nn.LayerNorm([d_model])
194 self.norm_ff = nn.LayerNorm([d_model])196 def forward(self, *,
197 x: torch.Tensor,
198 mask: torch.Tensor):ස්වයංඅවධානය යොමු කිරීමට පෙර දෛශික සාමාන්යකරණය කරන්න
200 z = self.norm_self_attn(x)ස්වයංඅවධානය හරහා ධාවනය කරන්න, i.e. යතුරු සහ වටිනාකම් ස්වයං සිට
202 self_attn = self.attn(query=z, key=z, value=z, mask=mask)ස්වයංඅවධානය ප්රතිඵල එකතු
204 x = x + self.dropout(self_attn)පෝෂණයසඳහා සාමාන්යකරණය කරන්න
207 z = self.norm_ff(x)මාරුවීමේපෝෂක-ඉදිරි ජාලය හරහා ගමන් කරන්න
209 ff, counts, route_prob, n_dropped, route_prob_max = self.feed_forward(z)ප්රතිපෝෂණඉදිරි ප්රති results ල නැවත එක් කරන්න
211 x = x + self.dropout(ff)
212
213 return x, counts, route_prob, n_dropped, route_prob_max216class SwitchTransformer(Module):221 def __init__(self, layer: SwitchTransformerLayer, n_layers: int):
222 super().__init__()ට්රාන්ස්ෆෝමර්ස්ථරයේ පිටපත් සාදන්න
224 self.layers = clone_module_list(layer, n_layers)අවසානසාමාන්යකරණ ස්තරය
226 self.norm = nn.LayerNorm([layer.size])228 def forward(self, x: torch.Tensor, mask: torch.Tensor):එක්එක් ට්රාන්ස්ෆෝමර් ස්ථරය හරහා ධාවනය කරන්න
230 counts, route_prob, n_dropped, route_prob_max = [], [], [], []
231 for layer in self.layers:
232 x, f, p, n_d, p_max = layer(x=x, mask=mask)
233 counts.append(f)
234 route_prob.append(p)
235 n_dropped.append(n_d)
236 route_prob_max.append(p_max)අවසානවශයෙන්, දෛශික සාමාන්යකරණය කරන්න
238 x = self.norm(x)240 return x, torch.stack(counts), torch.stack(route_prob), n_dropped, torch.stack(route_prob_max)