ට්රාන්ස්ෆෝමර්ස්විචය

මෙයකඩදාසි ස්විච් ට්රාන්ස්ෆෝමර්වල කුඩා පයිටෝච් ක්රියාත්මක කිරීමකි: සරල හා කාර්යක්ෂම ස්පාර්ටිටි සහිත ට්රිලියන පරාමිති ආකෘති වලට පරිමාණය කිරීම. අපගේ ක්රියාත්මක කිරීම සඳහා ඇත්තේ පරාමිතීන් මිලියන කිහිපයක් පමණක් වන අතර සමාන්තරව බෙදා හරින ලද පුහුණුව ආදර්ශයට නොගනී. එය තනි GPU පුහුණුව කරන්නේ, නමුත් අපි කඩදාසි විස්තර කර ඇති පරිදි මාරුවීමේ සංකල්පය ක්රියාත්මක කරමු.

ස්විච්ට්රාන්ස්ෆෝමරය ටෝකනය මත පදනම්ව පරාමිතීන් අතර මාරුවීමෙන් එක් එක් ටෝකනය සඳහා විවිධ පරාමිතීන් භාවිතා කරයි. එබැවින්, එක් එක් ටෝකනය සඳහා තෝරා ගනු ලබන්නේ පරාමිතීන්ගෙන් කොටසක් පමණි. එබැවින් ඔබට වැඩි පරාමිතීන් තිබිය හැකි නමුත් අඩු පරිගණකමය පිරිවැයක් ඇත.

මාරුවීමසිදුවන්නේ එක් එක් ට්රාන්ස්ෆෝමර් බ්ලොක් එකේ ස්ථාන-නැණවත් Feedforward ජාලයේ (FFN) ය. ස්ථාන-නැණවත් පෝෂක ජාලය අනුක්රමිකව පූර්ණ සම්බන්ධිත ස්ථර දෙකකින් සමන්විත වේ. ස්විච් ට්රාන්ස්ෆෝමරයේ අපට FFNs (බහු විශේෂ experts යින්) කිහිපයක් ඇති අතර, රවුටරයක් මත පදනම්ව භාවිතා කළ යුත්තේ කුමන එකද යන්න අපි තෝරා ගත්තෙමු. ප්රතිදානය යනු එෆ්එෆ්එන් තෝරා ගැනීම සඳහා වන සම්භාවිතාවන් සමූහයක් වන අතර, අපි ඉහළම සම්භාවිතාව ඇති එකක් තෝරාගෙන එය ඇගයීමට ලක් කරමු. එබැවින් අත්යවශ්යයෙන්ම පරිගණකමය පිරිවැය තනි එෆ්එෆ්එන් එකක් තිබීම හා සමාන වේ. අපගේ ක්රියාත්මක කිරීමේදී මෙය ඔබට බොහෝ හෝ විශාල එෆ්එෆ්එන්එස් ඇති විට සමාන්තරගත නොවේ. බෙදා හරින ලද සැකසුමක ඔබට එක් එක් FFN (සෑම ඉතා විශාල) වෙනත් උපාංගයක ඇත.

විශේෂexperts යන් (එෆ්එෆ්එන්එස්) අතර බර සමතුලිත කිරීම සඳහා කඩදාසි තවත් පාඩු යෙදුමක් හඳුන්වා දෙන අතර රවුටින් සමතුලිත නොවන විට ටෝකන අතහැර දැමීම සාකච්ඡා කරයි.

කුඩාෂේක්ස්පියර් දත්ත කට්ටුවේ ස්විච් ට්රාන්ස්ෆෝමරයක් පුහුණු කිරීම සඳහා පුහුණු කේතය සහ සටහන් පොතක් මෙන්න.

Open In Colab View Run

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_list

බහුFFNs අතර මාර්ගගත කිරීම

49class 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_tokens

FFNsහි පිටපත් සාදන්න

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 ස්වයං අවධානයෙන් පසු ඉවත් වීමේ සම්භාවිතාව සහ FFN
177    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_max

ට්රාන්ස්ෆෝමර්ස්විචය

216class 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)