මෙය PyTorch කඩදාසි ක්රියාත්මක කිරීම රූප හඳුනාගැනීම සඳහා ගැඹුරු අවශේෂ ඉගෙනීම .
පිරිහීමේගැටළුවමඟහරවා ගැනීම සඳහා අවශේෂ කාර්යයන් ලෙස රෙස්නෙට්ස් ස්ථර පුහුණු කරයි. පිරිහීමේ ගැටළුව වන්නේ ස්ථර ගණන ඉතා ඉහළ වන විට ගැඹුරු ස්නායුක ජාල පිරිහීමේ නිරවද්යතාවයයි. ස්ථර ගණන වැඩි වන විට නිරවද්යතාව වැඩි වන අතර පසුව සන්තෘප්ත වන අතර පසුව පිරිහීමට පටන් ගනී.
අමතරස්ථරවලට අනන්යතා සිතියම්ගත කිරීමක් සිදු කිරීමට ඉගෙන ගත හැකි නිසා ගැඹුරු ආකෘති අවම වශයෙන් මෙන්ම නොගැඹුරු ආකෘති ඉටු කළ යුතු බව කඩදාසි තර්ක කරයි.
ස්ථරකිහිපයකින් ඉගෙන ගත යුතු සිතියම්කරණය නම් , ඒවා අවශේෂ ක්රියාකාරිත්වය පුහුණු කරයි
ඒවෙනුවට. මුල් කාර්යය බවට පත්වේ .
මේඅවස්ථාවේ දී, සඳහා අනන්යතා සිතියම්කරණය ඉගෙන ගැනීමට ඉගෙනීමට සමාන වේ , එය ඉගෙන ගැනීමට පහසු වේ.
පරාමිතිකස්වරූපයෙන් මෙය ලිවිය හැකිය,
විශේෂාංගසිතියම් ප්රමාණ හා වෙනස් වූ විට කඩදාසි යෝජනා කරන්නේ ඉගෙනගත් බර සමඟ රේඛීය ප්රක්ෂේපණයක් කිරීමයි.
කඩදාසිරේඛීය ප්රක්ෂේපණ වෙනුවට ශුන්ය පෑඩින් සමඟ අත්හදා බැලූ අතර රේඛීය ප්රක්ෂේපණ වඩා හොඳින් ක්රියා කරන බව සොයා ගන්නා ලදී. විශේෂාංග සිතියම් ප්රමාණ ගැලපෙන විට අනන්යතා සිතියම්කරණය රේඛීය ප්රක්ෂේපණවලට වඩා හොඳ බව ඔවුන්ට පෙනී ගියේය.
එක් ස්ථරයකට වඩා තිබිය යුතුය, එසේ නොමැතිනම් එකතුවට රේඛීය නොවන නොවන අතර රේඛීය තට්ටුවක් මෙන් වනු ඇත.
CIFA-10හි රෙස්නෙට් පුහුණු කිරීම සඳහා පුහුණු කේතය මෙන්න.
57from typing import List, Optional
58
59import torch
60from torch import nn
61
62from labml_helpers.module import Module
65class ShortcutProjection(Module):
in_channels
යනු නාලිකා ගණන out_channels
යනු නාලිකා ගණන stride
සඳහා convolution මෙහෙයුම දී stride දිග වේ. විශේෂාංග-සිතියම් ප්රමාණයට ගැලපෙන පරිදි අපි කෙටිමං සම්බන්ධතාවයේ එකම පියවර ගනිමු. 72 def __init__(self, in_channels: int, out_channels: int, stride: int):
79 super().__init__()
රේඛීයප්රක්ෂේපණය සඳහා සංයුක්ත ස්ථරය
82 self.conv = nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride)
කඩදාසිඑක් එක් convolution මෙහෙයුම පසු කණ්ඩායම සාමාන්යකරණය එකතු යෝජනා
84 self.bn = nn.BatchNorm2d(out_channels)
86 def forward(self, x: torch.Tensor):
සම්මුතිසහ කණ්ඩායම් සාමාන්යකරණය
88 return self.bn(self.conv(x))
මෙයකඩදාසි විස්තර කර ඇති අවශේෂ කොටස ක්රියාත්මක කරයි. එය කැටි ගැසුණු ස්ථර දෙකක් ඇත.
පළමුconvolution ස්ථරය සිතියම් out_channels
, අපි stride දිග සමග ලක්ෂණය සිතියම් ප්රමාණය අඩු කරන in_channels
විට වඩා වැඩි කොහෙද in_channels
out_channels
වඩා විශාල .
සිට out_channels
දෙවන convolution ස්ථරය සිතියම් out_channels
හා සෑම විටම 1 ක stride දිග ඇත.
සංවහනස්ථර දෙකම කණ්ඩායම් සාමාන්යකරණය කිරීමෙන් පසුව සිදු වේ.
91class ResidualBlock(Module):
in_channels
යනු නාලිකා ගණන out_channels
ප්රතිදාන නාලිකා ගණන වේ stride
මෙම convolution මෙහෙයුම දී stride දිග වේ. 112 def __init__(self, in_channels: int, out_channels: int, stride: int):
118 super().__init__()
පළමු සංවහන ස්තරය, මෙය සිතියම් ගත කරයි out_channels
121 self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1)
පළමුකැටි ගැසීමෙන් පසු කණ්ඩායම් සාමාන්යකරණය
123 self.bn1 = nn.BatchNorm2d(out_channels)
පළමුසක්රිය කිරීමේ කාර්යය (RELU)
125 self.act1 = nn.ReLU()
දෙවන කැටි ගැසුණු ස්ථරය
128 self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1)
දෙවනකැටි ගැසීම්වලින් පසු කණ්ඩායම් සාමාන්යකරණය
130 self.bn2 = nn.BatchNorm2d(out_channels)
නාලිකාගණන වෙනස් වුවහොත් ස්ට්රයිඩ් දිග නොවේ නම් කෙටිමං සම්බන්ධතාවය ප්රක්ෂේපණයක් විය යුතුය
134 if stride != 1 or in_channels != out_channels:
ප්රක්ෂේපණය
136 self.shortcut = ShortcutProjection(in_channels, out_channels, stride)
137 else:
අනන්යතාවය
139 self.shortcut = nn.Identity()
දෙවනසක්රිය කිරීමේ කාර්යය (RelU) (කෙටිමඟ එකතු කිරීමෙන් පසු)
142 self.act2 = nn.ReLU()
x
හැඩයේ ආදානය වේ [batch_size, in_channels, height, width]
144 def forward(self, x: torch.Tensor):
කෙටිමංසම්බන්ධතාවය ලබා ගන්න
149 shortcut = self.shortcut(x)
පළමුකැටි කිරීම සහ සක්රිය කිරීම
151 x = self.act1(self.bn1(self.conv1(x)))
දෙවනකැටි ගැසිම
153 x = self.bn2(self.conv2(x))
කෙටිමඟඑකතු කිරීමෙන් පසු සක්රිය කිරීමේ කාර්යය
155 return self.act2(x + shortcut)
මෙයකඩදාසි වල විස්තර කර ඇති බාධක කොටස ක්රියාත්මක කරයි. එය , සහ කැටි ගැසුණු ස්ථර ඇත.
පළමුconvolution ස්ථරය වඩා අඩු කොහෙද convolution, bottleneck_channels
සමග සිට in_channels
සිතියම් bottleneck_channels
in_channels
.
දෙවන කැටි ගැසුණු ස්ථරය සිතියම් bottleneck_channels
සිට bottleneck_channels
. විශේෂාංග සිතියම් ප්රමාණය සම්පීඩනය කිරීමට අපට අවශ්ය වන විට වඩා විශාල දිගක් මෙයට තිබිය හැකිය.
තෙවන, අවසාන කැටි ගැසුණු ස්ථරය සිතියම් වෙත out_channels
. out_channels
මෙම stride දිග වඩා වැඩි in_channels
නම් වඩා වැඩි ය ; එසේ නොමැති නම්, සමාන වේ in_channels
.
bottleneck_channels
වඩා අඩු වන in_channels
අතර මෙම හැකිලී අවකාශය මත කැටි කිරීම සිදු කරනු ලැබේ (එබැවින් බාධකය). සංවහන දෙක අඩු වන අතර නාලිකා ගණන වැඩි කරයි.
158class BottleneckResidualBlock(Module):
in_channels
යනු නාලිකා ගණන bottleneck_channels
යනු සංවහන සඳහා නාලිකා ගණන out_channels
ප්රතිදාන නාලිකා ගණන වේ stride
මෙම convolution මෙහෙයුම දී stride දිග වේ. 186 def __init__(self, in_channels: int, bottleneck_channels: int, out_channels: int, stride: int):
193 super().__init__()
පළමු සංවහන ස්තරය, මෙය සිතියම් ගත කරයි bottleneck_channels
196 self.conv1 = nn.Conv2d(in_channels, bottleneck_channels, kernel_size=1, stride=1)
පළමුකැටි ගැසීමෙන් පසු කණ්ඩායම් සාමාන්යකරණය
198 self.bn1 = nn.BatchNorm2d(bottleneck_channels)
පළමුසක්රිය කිරීමේ කාර්යය (RELU)
200 self.act1 = nn.ReLU()
දෙවන කැටි ගැසුණු ස්ථරය
203 self.conv2 = nn.Conv2d(bottleneck_channels, bottleneck_channels, kernel_size=3, stride=stride, padding=1)
දෙවනකැටි ගැසීම්වලින් පසු කණ්ඩායම් සාමාන්යකරණය
205 self.bn2 = nn.BatchNorm2d(bottleneck_channels)
දෙවනසක්රිය කිරීමේ ශ්රිතය (RelU)
207 self.act2 = nn.ReLU()
තෙවන සංවහන ස්තරය, මෙම සිතියම් වෙත out_channels
.
210 self.conv3 = nn.Conv2d(bottleneck_channels, out_channels, kernel_size=1, stride=1)
දෙවනකැටි ගැසීම්වලින් පසු කණ්ඩායම් සාමාන්යකරණය
212 self.bn3 = nn.BatchNorm2d(out_channels)
නාලිකාගණන වෙනස් වුවහොත් ස්ට්රයිඩ් දිග නොවේ නම් කෙටිමං සම්බන්ධතාවය ප්රක්ෂේපණයක් විය යුතුය
216 if stride != 1 or in_channels != out_channels:
ප්රක්ෂේපණය
218 self.shortcut = ShortcutProjection(in_channels, out_channels, stride)
219 else:
අනන්යතාවය
221 self.shortcut = nn.Identity()
දෙවනසක්රිය කිරීමේ කාර්යය (RelU) (කෙටිමඟ එකතු කිරීමෙන් පසු)
224 self.act3 = nn.ReLU()
x
හැඩයේ ආදානය වේ [batch_size, in_channels, height, width]
226 def forward(self, x: torch.Tensor):
කෙටිමංසම්බන්ධතාවය ලබා ගන්න
231 shortcut = self.shortcut(x)
පළමුකැටි කිරීම සහ සක්රිය කිරීම
233 x = self.act1(self.bn1(self.conv1(x)))
දෙවනකැටි ගැසිම සහ සක්රිය කිරීම
235 x = self.act2(self.bn2(self.conv2(x)))
තෙවනකැටි ගැසිම
237 x = self.bn3(self.conv3(x))
කෙටිමඟඑකතු කිරීමෙන් පසු සක්රිය කිරීමේ කාර්යය
239 return self.act3(x + shortcut)
මෙයවර්ගීකරණය සඳහා අවසාන රේඛීය ස්තරය සහ සොෆ්ට්මැක්ස් නොමැතිව රෙස්නෙට් ආකෘතියේ පාදමකි.
රෙස්නෙට්සෑදී ඇත්තේ ගොඩගැසී ඇති අවශේෂ කුට්ටි හෝ බාධක අවශේෂ කුට්ටි වලින් ය. විශේෂාංග සිතියම් ප්රමාණය අඩක් පමණ දිග බ්ලොක් කිහිපයකින් පසුව අඩක් පමණ වේ. විශේෂාංග සිතියම් ප්රමාණය අඩු වූ විට නාලිකා ගණන වැඩි වේ. අවසාන වශයෙන් විශේෂාංග සිතියම දෛශික නිරූපණයක් ලබා ගැනීම සඳහා සාමාන්යයෙන් සකස් කර ඇත.
242class ResNetBase(Module):
n_blocks
යනු එක් එක් විශේෂාංග සිතියම් ප්රමාණය සඳහා කුට්ටි ගණන ලැයිස්තුවකි. n_channels
එක් එක් විශේෂාංග සිතියම් ප්රමාණය සඳහා නාලිකා ගණන වේ. bottlenecks
යනු බාධක වල නාලිකා ගණන වේ. මෙය නම් None
, අවශේෂ කුට්ටි භාවිතා වේ. img_channels
යනු ආදානයේ ඇති නාලිකා ගණන වේ. first_kernel_size
ආරම්භක සංවලිත ස්ථරයේ කර්නල් ප්රමාණයයි256 def __init__(self, n_blocks: List[int], n_channels: List[int],
257 bottlenecks: Optional[List[int]] = None,
258 img_channels: int = 3, first_kernel_size: int = 7):
267 super().__init__()
එක්එක් විශේෂාංග සිතියම් ප්රමාණය සඳහා බ්ලොක් ගණන සහ නාලිකා ගණන
270 assert len(n_blocks) == len(n_channels)
බාධක අවශේෂ කුට්ටි භාවිතා කරන්නේ නම්, එක් එක් විශේෂාංග සිතියම් ප්රමාණය සඳහා බාධක වල නාලිකා ගණන සැපයිය යුතුය
273 assert bottlenecks is None or len(bottlenecks) == len(n_channels)
පළමුඅවශේෂ කොටසෙහි නාලිකා ගණන img_channels
දක්වා ආරම්භක සංවහන ස්ථර සිතියම් (n_channels[0]
)
277 self.conv = nn.Conv2d(img_channels, n_channels[0],
278 kernel_size=first_kernel_size, stride=2, padding=first_kernel_size // 2)
මූලිකකැටි ගැසීමෙන් පසු කණ්ඩායම් සම්මතය
280 self.bn = nn.BatchNorm2d(n_channels[0])
කුට්ටිලැයිස්තුව
283 blocks = []
පෙරස්ථරයෙන් (හෝ බ්ලොක්) නාලිකා ගණන
285 prev_channels = n_channels[0]
එක්එක් විශේෂාංග සිතියම් ප්රමාණය හරහා ලූප්
287 for i, channels in enumerate(n_channels):
නවවිශේෂාංග සිතියම් ප්රමාණය සඳහා වන පළමු කොටස, පළමු කොටස හැර දිගු දිගක් ඇත
290 stride = 2 if len(blocks) == 0 else 1
291
292 if bottlenecks is None:
සිට prev_channels
සිතියම් ගත කරනඅවශේෂ කොටස් channels
294 blocks.append(ResidualBlock(prev_channels, channels, stride=stride))
295 else:
සිට prev_channels
සිතියම්ගත කරන බාධක අවශේෂ කොටස් channels
298 blocks.append(BottleneckResidualBlock(prev_channels, bottlenecks[i], channels,
299 stride=stride))
නාලිකාගණන වෙනස් කරන්න
302 prev_channels = channels
ඉතිරිකොටස් එකතු කරන්න - විශේෂාංග සිතියම් ප්රමාණය හෝ නාලිකා වල වෙනසක් නොමැත
304 for _ in range(n_blocks[i] - 1):
305 if bottlenecks is None:
307 blocks.append(ResidualBlock(channels, channels, stride=1))
308 else:
310 blocks.append(BottleneckResidualBlock(channels, bottlenecks[i], channels, stride=1))
කුට්ටිගොඩගසන්න
313 self.blocks = nn.Sequential(*blocks)
x
හැඩය ඇත [batch_size, img_channels, height, width]
315 def forward(self, x: torch.Tensor):
මූලිකකැටි ගැසීම්සහ කණ්ඩායම් සාමාන්යකරණය
321 x = self.bn(self.conv(x))
අවශේෂ(හෝ බාධක) කුට්ටි
323 x = self.blocks(x)
x
හැඩයෙන් වෙනස් [batch_size, channels, h, w]
කරන්න [batch_size, channels, h * w]
325 x = x.view(x.shape[0], x.shape[1], -1)
ගෝලීයසාමාන්ය තටාක
327 return x.mean(dim=-1)