12from typing import Optional, Tuple
13
14import torch
15from torch import nn
16
17from labml_helpers.module import Module
LSTMසෛල ගණනය , සහ . දිගු කාලීන මතකය හා සමාන වන අතර එය කෙටිකාලීන මතකය හා සමාන වේ. අපි ආදානය සහ දිගු කාලීන මතකය යාවත්කාලීන කිරීමට භාවිතා කරමු. යාවත්කාලීනයේදී, සමහර අංග අමතක කිරීමේ ගේට්ටුවකින් ඉවත් කර ඇති අතර සමහර විශේෂාංග ගේට්ටුවක් හරහා එකතු වේ .
නවකෙටිකාලීන මතකය යනු ප්රතිදාන ගේට්ටුවෙන් ගුණ කරන දිගු කාලීන මතකයයි .
යාවත්කාලීනයසිදු කරන විට සෛලය දිගු කාලීන මතකය දෙස නොබලන බව සලකන්න. එය වෙනස් කරන්නේ එය පමණි. එසේම කිසි විටෙකත් රේඛීය පරිවර්තනයක් හරහා නොයයි. අතුරුදහන් වීම සහ පුපුරා යන ශ්රේණිය විසඳන්නේ මෙයයි.
මෙන්නයාවත්කාලීන රීතිය.
මූලද්රව්ය-නැණවත් ගුණ කිරීම සඳහා වේ.
අතරමැදිඅගයන් සහ ගේට්ටු සැඟවුණු තත්වයේ සහ ආදානයේ රේඛීය පරිවර්තනයන් ලෙස ගණනය කෙරේ.
20class LSTMCell(Module):
57 def __init__(self, input_size: int, hidden_size: int, layer_norm: bool = False):
58 super().__init__()
මේවා input
සහ hidden
දෛශික පරිවර්තනය කිරීම සඳහා රේඛීය ස්තරය වේ. අපි පරිවර්තනයන් එකතු කරන බැවින් ඒවායින් එකකට නැඹුරුවක් අවශ්ය නොවේ.
මෙයඒකාබද්ධ , , සහ පරිවර්තනයන්.
64 self.hidden_lin = nn.Linear(hidden_size, 4 * hidden_size)
මෙයඒකාබද්ධ , , සහ පරිවර්තනයන්.
66 self.input_lin = nn.Linear(input_size, 4 * hidden_size, bias=False)
ස්ථරසාමාන්යකරණය යෙදිය යුතුද යන්න.
ස්ථරසාමාන්යකරණය කිරීම වඩා හොඳ ප්රති. ල ලබා දෙයි. , , සහ කාවැද්දීම් සාමාන්යකරණය කර ඇති අතර එය සාමාන්යකරණය වේ
73 if layer_norm:
74 self.layer_norm = nn.ModuleList([nn.LayerNorm(hidden_size) for _ in range(4)])
75 self.layer_norm_c = nn.LayerNorm(hidden_size)
76 else:
77 self.layer_norm = nn.ModuleList([nn.Identity() for _ in range(4)])
78 self.layer_norm_c = nn.Identity()
80 def forward(self, x: torch.Tensor, h: torch.Tensor, c: torch.Tensor):
අපිරේඛීය පරිවර්තනයන් ගණනය කරමු , සහ එකම රේඛීය ස්ථර භාවිතා කිරීම.
83 ifgo = self.hidden_lin(h) + self.input_lin(x)
සෑමස්ථරයක්ම 4 ගුණයක ප්රතිදානයක් නිපදවන hidden_size
අතර අපි ඒවා බෙදුවෙමු
85 ifgo = ifgo.chunk(4, dim=-1)
ස්ථරසාමාන්යකරණය යොදන්න (මුල් කඩදාසිවල නොව, වඩා හොඳ ප්රතිඵල ලබා දෙයි)
88 ifgo = [self.layer_norm[i](ifgo[i]) for i in range(4)]
91 i, f, g, o = ifgo
94 c_next = torch.sigmoid(f) * c + torch.sigmoid(i) * torch.tanh(g)
විකල්පයක් ලෙස, ස්ථර සම්මතය යොදන්න
98 h_next = torch.sigmoid(o) * torch.tanh(self.layer_norm_c(c_next))
99
100 return h_next, c_next
103class LSTM(Module):
LSTMජාලයක් සාදන්න. n_layers
108 def __init__(self, input_size: int, hidden_size: int, n_layers: int):
113 super().__init__()
114 self.n_layers = n_layers
115 self.hidden_size = hidden_size
එක්එක් ස්ථරය සඳහා සෛල සාදන්න. පළමු ස්ථරයට පමණක් ආදානය කෙලින්ම ලැබෙන බව සලකන්න. සෙසු ස්ථර පහත ස්ථරයෙන් ආදානය ලබා ගනී
118 self.cells = nn.ModuleList([LSTMCell(input_size, hidden_size)] +
119 [LSTMCell(hidden_size, hidden_size) for _ in range(n_layers - 1)])
x
හැඩය ඇති [n_steps, batch_size, input_size]
අතර state
එය ටූල් එකක් වන අතර එක් එක් හැඩයකින් යුක්ත වේ [batch_size, hidden_size]
.
121 def forward(self, x: torch.Tensor, state: Optional[Tuple[torch.Tensor, torch.Tensor]] = None):
126 n_steps, batch_size = x.shape[:2]
රාජ්යයආරම්භ කරන්න නම් None
129 if state is None:
130 h = [x.new_zeros(batch_size, self.hidden_size) for _ in range(self.n_layers)]
131 c = [x.new_zeros(batch_size, self.hidden_size) for _ in range(self.n_layers)]
132 else:
133 (h, c) = state
එක්එක් ස්ථරයේ තත්වයන් ලබා ගැනීම සඳහා ආතතීන් ආපසු හරවන්න
📝ඔබට ටෙන්සර් සමඟ වැඩ කළ හැකි නමුත් මෙය නිදොස් කිරීමට පහසුය
137 h, c = list(torch.unbind(h)), list(torch.unbind(c))
එක්එක් කාල පියවරේදී අවසාන ස්ථරයේ ප්රතිදානයන් එකතු කිරීමට අරා.
140 out = []
141 for t in range(n_steps):
පළමුස්ථරයට ආදානය යනු ආදානය ම වේ
143 inp = x[t]
ස්ථරහරහා ලූප්
145 for layer in range(self.n_layers):
ස්ථරයේතත්වය ලබා ගන්න
147 h[layer], c[layer] = self.cells[layer](inp, h[layer], c[layer])
ඊළඟස්ථරයට ආදානය මෙම ස්ථරයේ තත්වයයි
149 inp = h[layer]
අවසාන ස්ථරයේ ප්රතිදානය එකතු කරන්න
151 out.append(h[-1])
ප්රතිදානයන්සහ ප්රාන්ත ගොඩගසන්න
154 out = torch.stack(out)
155 h = torch.stack(h)
156 c = torch.stack(c)
157
158 return out, (h, c)