You are on page 1of 356

‫بسمه تعالى‬

‫تأليف‪:‬‬
‫آ ستون زانغ وآخرون‬

‫ترجمة‪:‬‬
‫د‪ .‬عالء طعيمة‬
‫على مدى السنوات القليلة الماضية‪ ،‬طور فريق من علماء أمازون كتاباً " ‪Dive into Deep‬‬
‫‪ "Learning‬يكتسب شعبية بين الطالب والمطورين الذين ينجذبون إلى مجال التعلم العميق‬
‫المزدهر‪ ،‬وهو مجموعة فرعية من التعلم اآللي تركز على الشبكات العصبية االصطناعية واسعة‬
‫النطاق‪.‬‬

‫عند انتهائي من قراءه هذا الكتاب‪ ،‬احببت ان اترجم هذا الكتاب وأشارككم هذه الترجمة الن‬
‫هناك عدد من األشياء الرائعة حول هذا الكتاب وأكثر ما يعجبني هو أنه يغطي كل مجاالت التعلم‬
‫العميق تقريبًا مثالً للمبتدئين هناك فصول مثل الشبكات العصبية والبيرسيبترون متعدد الطبقات‬
‫واالنحدار والتصنيف باإلضافة الى المفاهيم األساسية من الجبر الخطي‪ ،‬وحساب التفاضل‬
‫والتكامل‪ ،‬واالحتمال الى فصول متقدمة مثل الشبكات العصبية االلتفافية ‪ ،CNN‬تم تضمين‬
‫الشبكات العصبية المتكررة ‪ RNN‬والرؤية الحاسوبية ‪ CV‬ومعالجة اللغات الطبيعية ‪NLP‬‬
‫أيضًا‪.‬‬

‫هذا كتاب تفاعلي مفتوح المصدر مقدميف شكل فريد يدمج النص والرياضيات والكود‪،‬‬
‫ويدعم اآلن أطر برمجة ‪ TensorFlow‬و‪ PyTorch‬و‪ ،Apache MXNet‬والتي تمت‬
‫صياغتها بالكامل من خالل ‪.Jupyter Notebook‬‬

‫يمكن تقسيم الكتاب إلى ثالثة أجزاء تقريبًا‪ ،‬لقد قمنايف الوقت الحالي بترجمة الجزء األول‬
‫والذي يشمل األساسيات والمقدمات والجزء الثاني والذي يشمل التقنيات الحديثة للتعلم العميق‬
‫وان شاء اللهيف المستقبل القريب سنقوم بترجمة الجزء الثالث والذي يشمل مواضيع مثل الرؤية‬
‫الحاسوبية ومعالجة اللغات الطبيعية‪.‬‬

‫لقد اخترت كتاب "‪ "Dive into Deep Learning‬لما رأيته من جودة هذا الكتاب‪،‬‬
‫وللمنهجية التي اتبعها المؤلفونيف ترتيبه وبساطة شرحه‪ .‬لقد حاولت قدر المستطاع ان اخرج‬
‫بترجمة ذات جودة عالية‪ ،‬ومع هذا يبقى عمالً بشرياً يحتمل النقص‪ ،‬فاذا كان لديك أي مالحظات‬
‫حول هذا الكتاب‪ ،‬فال تتردد بمراسلتنا عبر بريدنا االلكتروني ‪. alaa.taima@qu.edu.iq‬‬

‫نأمل ان يساعد هذا الكتاب كل من يريد ان يدخليف مجال التعلم العميق ومساعدة القارئ‬
‫العربي على تعلم هذا المجال‪ .‬اسأل الله التوفيقيف هذا العمل ألثراء المحتوى العربي الذي يفتقر‬
‫أشد االفتقار إلى محتوى جيد ورصينيف مجال الذكاء االصطناعي وتعلم االلة والتعلم العميق‪.‬‬
‫ونرجو لك االستمتاع مع التعلم العميق وال تنسونا من صالح الدعاء‪.‬‬
‫المحتويات‬
19 Builders’ Guide 1

19 ............................. Layers and Modules 6.1


22 ......................... A Custom Module 6.1.1
23 ............... The Sequential Module 6.1.2
Executing Code 6.1.3
24 ............ ................................ in the Forward Propagation Method
26 ............ ................................ ................................ 6.1.4
26 ............. ................................ ................................ 6.1.5
27 ....................................... Parameter Management 6.2
28 ................................... Parameter Access 6.2.1
28 .................... Targeted Parameters 6.2.1.1
28 ........... All Parameters at Once 6.2.1.2
29 ..................................... Tied Parameters 6.2.2
30 ............ ................................ ................................ 6.2.3
30 ............. ................................ ................................ 6.2.4
30 ........................................ Parameter Initialization 6.3
31 ................................... Built-in Initialization 6.3.1
33 .......................... Custom Initialization 6.3.1.1
34 ............ ................................ ................................ 6.3.2
34 ............. ................................ ................................ 6.3.3
34 .............. ................................ Lazy Initialization 6.4
35 ............ ................................ ................................ 6.4.1
36 ............. ................................ ................................ 6.4.2
36 .............. ................................ Custom Layers 6.5
36 ................. Layers without Parameters 6.5.1
37 ......................... Layers with Parameters 6.5.2
38 ............ ................................ ................................ 6.5.3
39 ............. ................................ ................................ 6.5.4
39 ........................ ................................ File I/O 6.6
39 ................ Loading and Saving Tensors 6.6.1
Loading and Saving Model 6.6.2
40 ................ ................................ ................................ Parameters
41 ............ ................................ ................................ 6.6.3
41 ............. ................................ ................................ 6.6.4
42 ..................... ................................ GPUs 6.7
44 ...................................... Computing Devices 6.7.1
45 ............. Tensors and GPUs 6.7.2
45 ... Storage on the GPU 6.7.2.1
46 ............................. ................................ Copying 6.7.2.2
47 ........... ................................ Side Notes 6.7.2.3
Neural Networks 6.7.3
48 ................... ................................ ................................ and GPUs
48 ............ ................................ ................................ 6.7.4
49 ............. ................................ ................................ 6.7.5
51 Convolutional Neural Networks 7

From Fully Connected 7.1


52 ................................... ................................ Layers to Convolutions
53 ................................ ................................ Invariance 7.1.1
55 ....................................... Constraining the MLP MLP 7.1.2
55 ............................... Translation Invariance 7.1.2.1
56 ........................... ................................ Locality 7.1.2.2
57 ......................... ................................ Convolutions 7.1.3
57 ................................ ................................ Channels 7.1.4
59 ............................ ................................ 7.1.5
60 ............. ................................ ................................ 7.1.6
60 ....................................... Convolutions for Images 7.2
60 ........ The Cross-Correlation Operation 7.2.1
62 ............................... Convolutional Layers 7.2.2
63 .. Object Edge Detection in Images 7.2.3
65 ............... ................................ Learning a Kernel 7.2.4
66 .. Cross-Correlation and Convolution 7.2.5
67 . Feature Map and Receptive Field 7.2.6
68 ............ ................................ ................................ 7.2.7
69 ............. ................................ ................................ 7.2.8
69 ............. ................................ Padding and Stride 7.3
70 ................................... ................................ Padding 7.3.1
73 .................................... ................................ Stride 7.3.2
74 ............................ ................................ 7.3.3
75 ............. ................................ ................................ 7.3.4
Multiple Input and Multiple 7.4
75 ............ ................................ ................................ Output Channels
75 ......................... Multiple Input Channels 7.4.1
77 ...................... Multiple Output Channels 7.4.2
78 .............. Convolutional Layer 𝟏 × 𝟏 𝟏 × 𝟏 7.4.3
80 ........... ................................ ................................ 7.4.4
80 ............. ................................ ................................ 7.4.5
81 ......................................... ................................ Pooling 7.5
Maximum Pooling and 7.5.1
82 ......................................... ................................ Average Pooling
84 ...................................... Padding and Stride 7.5.2
86 ......................................... Multiple Channels 7.5.3
87 ............ ................................ ................................ 7.5.4
87 ............. ................................ ................................ 7.5.5
88 ............ ................................ LeNet 7.6
89 ................ ................................ ................................ LeNet 7.6.1
92 ................................. ................................ Training 7.6.2
93 ............. ................................ ................................ 7.6.4
96 Modern Convolutional Neural Networks 8

97 ............................... AlexNet 8.1


99 .............................. Representation Learning 8.1.1
101 ......... Missing Ingredient: Data 8.1.1.1
102 . Missing Ingredient: Hardware 8.1.1.2
104 .......................................... ................................ AlexNet 8.1.2
105 ............... ................................ Architecture 8.1.2.1
105 .............................. Activation Functions 8.1.2.2
Capacity Control and 8.1.2.3
106 ....................................... ................................ Preprocessing
107 ............................... ................................ Training 8.1.3
108 ......................................... ................................ 8.1.4
109 ........... ................................ ................................ 8.1.5
110 ........... Networks Using Blocks VGG 8.2
110 ......................................... ................................ VGG 8.2.1
112 ...................................... ................................ VGG 8.2.2
114 ............................... ................................ Training 8.2.3
114 .......................................... ................................ 8.2.4
115 ........... ................................ ................................ 8.2.5
115 ......................... Network in Network NiN 8.3
116 .......................................... ................................ NiN 8.3.1
118 ....................................... ................................ NiN 8.3.2
119 ............................... ................................ Training 8.3.3
120 .......................................... ................................ 8.3.4
120 ........... ................................ ................................ 8.3.5
121 ......... Multi-Branch Networks GoogLeNet 8.4
121 ......................................... Inception Blocks 8.4.1
123 ............................ ................................ GoogLeNet 8.4.2
126 ............................... ................................ Training 8.4.3
127 ......................................... ................................ 8.4.4
127 ........... ................................ ................................ 8.4.5
128 ....................................... Batch Normalization 8.5
128 ................. Training Deep Networks 8.5.1
132 .............. Batch Normalization Layers 8.5.2
132 .............. Fully Connected Layers 8.5.2.1
132 .......................... Convolutional Layers 8.5.2.2
132 .............................. Layer Normalization 8.5.2.3
Batch Normalization During 8.5.2.4
133 ............. ................................ ................................ Prediction
133 .................. Implementation from Scratch 8.5.3
136 .................... ................................ LeNet 8.5.4
138 ........................... Concise Implementation 8.5.5
139 ......................................... ................................ 8.5.6
141 ........... ................................ ................................ 8.5.7
142 ............. Residual Networks ResNeXt ResNet 8.6
142 .............. ................................ Function Classes 8.6.1
144 .......................................... Residual Blocks 8.6.2
147 .................................. ................................ ResNet 8.6.3
149 ............................... ................................ Training 8.6.4
149 .......................................... ................................ ResNeXt 8.6.5
152 .......................... ................................ 8.6.6
154 ........... ................................ ................................ 8.6.7
154 . Densely Connected Networks DenseNet 8.7
154 ................... ................................ DenseNet ResNet 8.7.1
156 ................... ................................ Dense Blocks 8.7.2
157 ........................................ Transition Layers 8.7.3
158 .............................. ................................ DenseNet 8.7.4
159 ............................... ................................ Training 8.7.5
160 .......................... ................................ 8.7.6
160 ........... ................................ ................................ 8.7.7
Designing Convolution Network 8.8
160 ............... ................................ ................................ Architectures
161 ..................... ................................ AnyNet 8.8.1
Constraining Design 8.8.2
164 ........................................ Spaces with Lower Error Distributions
165 ........... ................................ ................................ RegNet 8.8.3
166 ............................... ................................ Training 8.8.4
167 ......................................... ................................ 8.8.5
167 ........... ................................ ................................ 8.8.6
170 Recurrent Neural Networks 9

172 ............................ Working with Sequences 9.1


174 ......................... Autoregressive Models 9.1.1
176 ...................................... Sequence Models 9.1.2
177 ..................................... Markov Models 9.1.2.1
177 ..................... The Order of Decoding 9.1.2.2
179 ............................... ................................ Training 9.1.3
180 ............................... ................................ Prediction 9.1.4
184 .......................................... ................................ 9.1.5
184 ........... ................................ ................................ 9.1.6
Converting Raw Text into 9.2
184 ............. ................................ ................................ Sequence Data
185 ........................ Reading the Dataset 9.2.1
186 ......................... ................................ Tokenization 9.2.2
186 ........................ ................................ Vocabulary 9.2.3
188 ............................. Putting It All Together 9.2.4
188 . Exploratory Language Statistics 9.2.5
192 .......................................... ................................ 9.2.6
192 ........... ................................ ................................ 9.2.7
192 .................... ................................ Language Models 9.3
193 ....................... Learning Language Models 9.3.1
193 ... Markov Models and 𝑛-grams n 9.3.1.1
194 ..................................... Word Frequency 9.3.1.2
194 ................................ Laplace Smoothing 9.3.1.3
195 .............................. ................................ Perplexity 9.3.2
197 ............................ Partitioning Sequences 9.3.3
199 .......................................... ................................ 9.3.4
199 ........... ................................ ................................ 9.3.5
199 ................ Recurrent Neural Networks 9.4
Neural Networks without 9.4.1
200 ........... ................................ ................................ Hidden States
Recurrent Neural 9.4.2
201 .................... ................................ Networks with Hidden States
RNN-based RNN 9.4.3
204 .............. ................................ Character-Level Language Models
205 .......................................... ................................ 9.4.4
205 ........... ................................ ................................ 9.4.5
Recurrent Neural Network 9.5
205 ........................ ................................ Implementation from Scratch
206 ...................................... ................................ RNN 9.5.1
207 .. RNN-based Language Model RNN 9.5.2
208 ................................. One-Hot Encoding 9.5.2.1
209 ........... Transforming RNN Outputs RNN 9.5.2.2
209 ............ ................................ Gradient Clipping 9.5.3
211 ............................... ................................ Training 9.5.4
212 ........................ ................................ Decoding 9.5.5
213 ........... ................................ ................................ 9.5.7
Concise Implementation 9.6
214 ....................... ................................ of Recurrent Neural Networks
215 ..................................... Defining the Model 9.6.1
215 ............................... Training and Predicting 9.6.2
216 .......................................... ................................ 9.6.3
216 ........... ................................ ................................ 9.6.4
216 ............. Backpropagation Through Time 9.7
217 .................... ................................ RNNs 9.7.1
219 ................................. Full Computation 9.7.1.1
219 ................. Truncating Time Steps 9.7.1.2
219 .................... Randomized Truncation 9.7.1.3
220 ................... Comparing Strategies 9.7.1.4
Backpropagation Through 9.7.2
221 ........... ................................ ................................ Time in Detail
223 .......................................... ................................ 9.7.3
224 ........... ................................ ................................ 9.7.4
226 Modern Recurrent Neural Networks 10

227 ... Long Short-Term Memory LSTM 10.1


227 ....................... Gated Memory Cell 10.1.1
228 .............. Gated Hidden State 10.1.1.1
Input Gate, Forget 10.1.1.2
228 .......................... ................................ Gate, and Output Gate
229 ........... ................................ Input Node 10.1.1.3
230 Memory Cell Internal State 10.1.1.4
230 ...................................... Hidden State 10.1.1.5
231 ................. Implementation from Scratch 10.1.2
231 ... Initializing Model Parameters 10.1.2.1
233 ....................... Training and Prediction 10.1.2.2
233 .......................... Concise Implementation 10.1.3
235 ......................................... ................................ 10.1.5
235 ....... Gated Recurrent Units GRU 10.2
Reset Gate and Update Gate 10.2.1
236 ............................... ................................ ................................
237 ................ Candidate Hidden State 10.2.2
238 ............. ................................ Hidden State 10.2.3
238 .......... Implementation from Scratch 10.2.3.1
239 ......... Initializing Model Parameters 10.2.4
239 ................................... Defining the Model 10.2.5
240 ............................. ................................ Training 10.2.6
241 ....................... Concise Implementation 10.2.6.1
242 .................................. ................................ 10.2.6.2
242 ................................... ................................ 10.2.6.3
Deep Recurrent Neural 10.3
242 ..................... ................................ ................................ Networks
244 ................. Implementation from Scratch 10.3.1
245 .......................... Concise Implementation 10.3.2
247 ........................................ ................................ 10.3.3
247 ......................................... ................................ 10.3.4
Bidirectional Recurrent 10.4
247 .......................................... ................................ Neural Networks
249 ................. Implementation from Scratch 10.4.1
250 .......................... Concise Implementation 10.4.2
250 .................................. ................................ 10.4.2.1
250 ................................... ................................ 10.4.2.2
Machine Translation and the 10.5
250 ....................... ................................ ................................ Dataset
Downloading and 10.5.1
251 ......................... ................................ Preprocessing the Dataset
252 ....................... ................................ Tokenization 10.5.2
Loading Sequences of 10.5.3
254 ............. ................................ ................................ Fixed Length
256 ...................... Reading the Dataset 10.5.4
257 ........................................ ................................ 10.5.5
258 ......................................... ................................ 10.5.6
258 .Encoder-Decoder Architecture 10.6
258 ............................. ................................ Encoder 10.6.1
259 ................... ................................ Decoder 10.6.2
Putting the Encoder and 10.6.3
260 ..................................... ................................ Decoder Together
260 ........................................ ................................ 10.6.4
260 ......................................... ................................ 10.6.5
Encoder-Decoder Seq2Seq 10.7
261 .................. ................................ Seq2Seq for Machine Translation
262 ............ ................................ Teacher Forcing 10.7.1
262 ............................. ................................ Encoder 10.7.2
264 ................... ................................ Decoder 10.7.3
Encoder- 10.7.4
266 ............................... Decoder for Sequence to Sequence Learning
267 ............... Loss Function with Masking 10.7.5
268 ............................. ................................ Training 10.7.6
269 ............................. ................................ Prediction 10.7.7.
Evaluation of Predicted 10.7.8
270 ................ ................................ ................................ Sequences
272 ........................................ ................................ 10.7.9
272 ....................................... ................................ 10.7.10
272 .................. ................................ Beam Search 10.8
273 ............ ................................ Greedy Search 10.8.1
275 ...................................... Exhaustive Search 10.8.2
275 ............ ................................ Beam Search 10.8.3
277 ........................................ ................................ 10.8.4
277 ......................................... ................................ 10.8.5
279 Attention Mechanisms and Transformers 11

280 ................. ................................ Attention Cues 11.1


280 ....... Attention Cues in Biology 11.1.1
282 ..... Queries, Keys, and Values 11.1.2
283 ............................. Visualization of Attention 11.1.3
284 ........................................ ................................ 11.1.4
285 ......................................... ................................ 11.1.5
285 .............. ................................ Attention Pooling 11.2
285 .................. Generating the Dataset 11.2.1
286 ..................................... Average Pooling 11.2.2
287 .. Nonparametric Attention Pooling 11.2.3
290 .......... Parametric Attention Pooling 11.2.4
290 ..... Batch Matrix Multiplication 11.2.4.1
291 ....................... ................................ Training 11.2.4.3
292 ........................................ ................................ 11.2.5
293 ......................................... ................................ 11.2.6
293 ...................... Attention Scoring Functions 11.3
294 .......... Masked Softmax Operation Softmax 11.3.1
296 ..................................... Additive Attention 11.3.2
299 .. Scaled Dot-Product Attention 11.3.3
301 ........................................ ................................ 11.3.4
301 ......................................... ................................ 11.3.5
301 .................................... ................................ Bahdanau 11.4
302 ............................... ................................ Model 11.4.1
Defining the Decoder with 11.4.2
303 ................. ................................ ................................ Attention
306 ............................. ................................ Training 11.4.3
308 ........................................ ................................ 11.4.4
309 ......................................... ................................ 11.4.5
309 ............................ Multi-Head Attention 11.5
310 ............................... ................................ Model 11.5.1
310 .................. ................................ Implementation 11.5.2
313 ........................................ ................................ 11.5.3
313 ......................................... ................................ 11.5.4
Self-Attention and Positional 11.6
313 ..................... ................................ ................................ Encoding
314 .............. ................................ Self-Attention 11.6.1
Comparing CNNs, RNNs, and RNNs CNNs 11.6.2
314 ........... ................................ ................................ Self-Attention
316 ................................ Positional Encoding 11.6.3
Absolute Positional Information 11.6.3.1
317 ............................ ................................ ................................
Relative Positional 11.6.3.2
319 .......................................... ................................ Information
319 ........................................ ................................ 11.6.4
319 ......................................... ................................ 11.6.5
320 ..................... The Transformer Architecture 11.7
321 ............................... ................................ Model 11.7.1
Positionwise Feed-Forward 11.7.2
322 ................. ................................ ................................ Networks
Residual Connection and Layer 11.7.3
323 .......................................... ................................ Normalization
324 ............................. ................................ Encoder 11.7.4
326 ................... ................................ Decoder 11.7.5
329 ............................. ................................ Training 11.7.6
334 ........................................ ................................ 11.7.7
335 ......................................... ................................ 11.7.8
335 ..................................... Transformers for Vision 11.8
336 ............................... ................................ Model 11.8.1
337 ...................................... Patch Embedding 11.8.2
338 ................. Vision Transformer Encoder 11.8.3
339 ........................... Putting It All Together 11.8.4
340 ............................. ................................ Training 11.8.5
341 ......................... ................................ 11.8.6
342 ......................................... ................................ 11.8.7
Large-Scale 11.9
342 ....................... ................................ Pretraining with Transformers
343 .............. ................................ Encoder-Only 11.9.1
344 ...................... Pretraining BERT 11.9.1.1
344 ........................ Fine-Tuning BERT 11.9.1.2
345 .......................... Encoder-Decoder 11.9.2
346 .................. ................................ T5 11.9.2.1
347 .............................. Fine-Tuning T5 T5 11.9.2.2
349 .................................... Decoder-Only 11.9.3
349 ............................. ................................ GPT-2 GPT 11.9.3.1
350 ..................................... ................................ GPT-3 11.9.3.2
352 .................. ................................ Scalability 11.9.4
354 ......................... ................................ 11.9.5
355 ......................................... ................................ 11.9.6
‫دليل البنائين‬
‫‪6‬‬

‫مقد‬
‫مها‬
‫‪19‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫‪Builders’ Guide‬‬ ‫‪1‬‬


‫إلى جانب مجموعات البيانات العمالقة واألجهزة القوية‪ ،‬لعبت أدوات البرامج الرائعة دورًا‬
‫ال غنى عنهيف التقدم السريع للتعلم العميق‪ .‬بدءًا من مكتبة ‪ Theano‬الرائدة التي تم إصدارهايف ‬
‫عام ‪ ،2007‬مكنت األدوات مفتوحة المصدر المرنة الباحثين من وضع نماذج أولية للنماذج‬
‫بسرعة‪ ،‬وتجنب العمل المتكرر عند إعادة تدوير المكونات القياسية مع الحفاظ على القدرة على‬
‫إجراء تعديالت منخفضة المستوى‪ .‬بمرور الوقت‪ ،‬تطورت مكتبات التعلم العميق لتقديم‬
‫تجريدات خشنة بشكل متزايد‪ .‬تمامًا كما انتقل مصممو أشباه الموصالت من تحديد‬
‫الترانزستورات إلى الدوائر المنطقية إلى كتابة التعليمات البرمجية‪ ،‬انتقل باحثو الشبكات العصبية‬
‫من التفكيريف سلوك الخاليا العصبية االصطناعية الفردية إلى تصور الشبكات من حيث الطبقات‬
‫الكاملة‪ ،‬واآلن غالبًا ما يصممون البنى مع وضع الكتل الخشنة ‪coarser blocks‬يف االعتبار‪.‬‬

‫حتى اآلن‪ ،‬قدمنا بعض مفاهيم التعلم اآللي األساسية‪ ،‬لتكثيف نماذج التعلم العميق كاملة‬
‫الوظائف‪.‬يف الفصل األخير‪ ،‬قمنا بتنفيذ كل مكون من مكونات ‪ MLP‬من البداية وحتى أوضحنا‬
‫كيفية االستفادة من واجهات برمجة التطبيقات ‪ API‬عالية المستوى لطرح نفس النماذج دون‬
‫عناء‪ .‬للوصول إلى هذا الحد بهذه السرعة‪ ،‬استدعينا المكتبات‪ ،‬لكننا تخطينا المزيد من التفاصيل‬
‫المتقدمة حول كيفية عملها‪.‬يف هذا الفصل‪ ،‬سنقوم بكشف الستارة‪ ،‬والبحث بشكل أعمقيف ‬
‫المكونات الرئيسية لحساب التعلم العميق‪ ،‬وهي بناء النموذج ‪،model construction‬‬
‫والوصول إلى المعلمات وتهيئتها‪ ،‬وتصميم الطبقات والكتل المخصصة‪ ،‬وقراءة النماذج وكتابتها‬
‫على القرص‪ ،‬واالستفادة من وحدات معالجة الرسومات ‪ GPU‬لتحقيق التعجيل الدراماتيكي‪.‬‬
‫ستنقلك هذه األفكار من مستخدم نهائي ‪ end user‬إلى مستخدم قوي ‪ ،power user‬مما‬
‫يمنحك األدوات الالزمة لجني فوائد مكتبة التعلم العميق الناضجة مع االحتفاظ بالمرونةيف تنفيذ‬
‫نماذج أكثر تعقيدًا‪ ،‬بمايف ذلك النماذج التي تخترعها بنفسك!يف حين أن هذا الفصل ال يقدم أي‬
‫نماذج أو مجموعات بيانات جديدة‪ ،‬فإن فصول النمذجة المتقدمة التي تليها تعتمد بشكل كبير‬
‫على هذه التقنيات‪.‬‬

‫‪Layers and Modules‬‬ ‫‪6.1‬‬


‫عندما قدمنا الشبكات العصبية ألول مرة‪ ،‬ركزنا على النماذج الخطية بإخراج واحد‪ .‬هنا‪ ،‬يتكون‬
‫النموذج بأكمله من خلية عصبية واحدة فقط‪ .‬الحظ أن خلية عصبية واحدة (‪ )1‬تأخذ مجموعة‬
‫من المدخالت؛ (‪ )2‬يولد مخرجات قياسية متطابقة‪ .‬و (‪ )3‬لديه مجموعة من المعلمات المرتبطة‬
‫التي يمكن تحديثها لتحسين بعض الدوال الموضوعية ذات األهمية‪ .‬بعد ذلك‪ ،‬بمجرد أن بدأنا‬
‫التفكيريف الشبكات ذات المخرجات المتعددة‪ ،‬استفدنا من الحساب المتجهي ‪vectorized‬‬
‫‪ arithmetic‬لتوصيف طبقة كاملة من الخاليا العصبية‪ .‬تمامًا مثل الخاليا العصبية الفردية‪ ،‬فإن‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪20‬‬

‫الطبقات (‪ )1‬تأخذ مجموعة من المدخالت‪ )2( ،‬تولد مخرجات مقابلة‪ ،‬و (‪ )3‬موصوفة‬
‫بمجموعة من المعلمات القابلة للضبط ‪ .tunable parameters‬عندما عملنا من خالل انحدار‬
‫‪ ،softmax‬كانت طبقة واحدة هي نفسها النموذج‪ .‬ومع ذلك‪ ،‬حتى عندما قدمنا الحقًا ‪،MLPs‬‬
‫ال يزال بإمكاننا التفكيريف النموذج على أنه يحتفظ بنفس ال ُبنية األساسية‪.‬‬

‫ومن المثير لالهتمام‪ ،‬بالنسبة لـ ‪ ،MLPs‬أن كل من النموذج بأكمله والطبقات المكونة له‬
‫تشتركيف هذا الهيكل‪ .‬يأخذ النموذج بأكمله المدخالت األولية (الميزات)‪ ،‬ويولد المخرجات‬
‫(التنبؤات)‪ ،‬ويمتلك المعلمات (المعلمات المدمجة من جميع الطبقات المكونة)‪ .‬وبالمثل‪ ،‬فإن‬
‫كل طبقة فردية تستوعب المدخالت (التي توفرها الطبقة السابقة) تولد النواتج (المدخالت إلى‬
‫الطبقة الالحقة)‪ ،‬وتمتلك مجموعة من المعلمات القابلة للضبط التي يتم تحديثها وفقًا لإلشارة‬
‫التي تتدفق للخلف من الطبقة الالحقة‪.‬‬

‫بينما قد تعتقد أن الخاليا العصبية والطبقات والنماذج تعطينا أفكارًا تجريدية كافية لمواصلة‬
‫أعمالنا‪ ،‬فقد اتضح أننا غالبًا ما نجد أنه من المناسب التحدث عن مكونات أكبر من طبقة فردية‬
‫ولكنها أصغر من النموذج بأكمله‪ .‬على سبيل المثال‪ ،‬تمتلك بنية ‪ ،ResNet-152‬التي تحظى‬
‫بشعبية كبيرةيف الرؤية الحاسوبية‪ ،‬مئات الطبقات‪ .‬تتكون هذه الطبقات من أنماط متكررة‬
‫لمجموعات من الطبقات‪ .‬يمكن أن يصبح تنفيذ مثل هذه الشبكة طبقة واحدةيف كل مرة ممالً‪.‬‬
‫هذا القلق ليس مجرد افتراض ‪ -‬أنماط التصميم هذه شائعةيف الممارسة‪ .‬فازت بُنية ‪ResNet‬‬
‫المذكورة أعالهيف مسابقات الرؤية الحاسوبية لعام ‪ ImageNet 2015‬و‪ COCO‬لكل من‬
‫التعرف والكشف (‪ ) 2016 ،He et al.‬وال تزال بنية االنتقال للعديد من مهام الرؤية‪ .‬إن البنى‬
‫المماثلة التي يتم فيها ترتيب الطبقاتيف أنماط متكررة مختلفة موجودة اآلنيف كل مكانيف ‬
‫مجاالت أخرى‪ ،‬بمايف ذلك معالجة اللغة الطبيعية والكالم‪.‬‬

‫لتنفيذ هذه الشبكات المعقدة‪ ،‬نقدم مفهوم وحدة النمطية للشبكة العصبية ‪ .module‬يمكن‬
‫أن تصف الوحدة النمطية طبقة واحدة‪ ،‬أو مكونًا يتكون من طبقات متعددة‪ ،‬أو النموذج بأكمله!‬
‫تتمثل إحدى فوائد العمل مع تجريد الوحدة النمطية ‪module abstraction‬يف أنه يمكن دمجها‬
‫في قطع أثرية أكبر‪ ،‬غالبًا بشكل متكرر‪ .‬وهذا موضحيف الشكل ‪ .6.1.1‬من خالل تحديد الكود‬
‫إلنشاء وحدات ذات تعقيد افتراضي عند الطلب‪ ،‬يمكننا كتابة كود مضغوط بشكل مدهش مع‬
‫االستمراريف تنفيذ الشبكات العصبية المعقدة‪.‬‬

‫من وجهة نظر البرمجة‪ ،‬يتم تمثيل الوحدة النمطية بواسطة فئة ‪ .class‬يجب أن تحدد أي فئة‬
‫فرعية منه طريقة انتشار أمامية تحول مدخالتها إلى مخرجات ويجب أن تخزن أي معلمات‬
‫ضرورية‪ .‬الحظ أن بعض الوحدات ال تتطلب أي معلمات على اإلطالق‪ .‬أخيرًا‪ ،‬يجب أن تمتلك‬
‫وحدة نمطية طريقة االنتشار الخلفي ‪ ،backpropagation‬ألغراض حساب التدرجات‬
‫‪21‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫‪ .gradients‬لحسن الحظ‪ ،‬نظرًا لبعض سحر ما وراء الكواليس الذي يوفره التفاضل التلقائي‬
‫‪( auto differentiation‬المقدميف القسم ‪ )2.5‬عند تحديد الوحدة النمطية الخاصة بنا‪ ،‬نحتاج‬
‫فقط إلى القلق بشأن المعلمات وطريقة االنتشار األمامية ‪.forward propagation‬‬

‫الشكل ‪ 6.1.1‬يتم دمج الطبقات المتعددةيف وحدات مكونة أنماطًا متكررة لنماذج أكبر‪.‬‬

‫للبدء‪ ،‬نعيد النظريف الكود الذي استخدمناه لتنفيذ ‪( MLPs‬القسم ‪ .)5.1‬يُنشئ الكود التالي شبكة‬
‫ذات طبقة مخفية واحدة متصلة بالكامل مع ‪ 256‬وحدة وتنشيط ‪ ،ReLU‬متبوعة بطبقة إخراج‬
‫متصلة بالكامل مع ‪ 10‬وحدات (بدون دالة تنشيط)‪.‬‬

‫‪import tensorflow as tf‬‬

‫[(‪net = tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Dense(256, activation=tf.nn.relu),‬‬
‫‪tf.keras.layers.Dense(10),‬‬
‫)]‬

‫))‪X = tf.random.uniform((2, 20‬‬


‫‪net(X).shape‬‬
‫)]‪TensorShape([2, 10‬‬

‫لـ‬ ‫مثيل‬ ‫إنشاء‬ ‫طريق‬ ‫عن‬ ‫نموذجنا‬ ‫ببناء‬ ‫قمنا‬ ‫المثال‪،‬‬ ‫هذا‬ ‫في‬
‫‪ ،keras.models.Sequential‬مع طبقات بالترتيب الذي يجب أن يتم تنفيذه بها‬
‫من‬ ‫خاصًا‬ ‫نوعًا‬ ‫‪Sequential‬‬ ‫يحدد‬ ‫باختصار‪،‬‬ ‫‪.arguments‬‬ ‫كوسيطات‬
‫‪ ،keras.Model‬وهو الكالس (الفئة) الذي يقدم وحدةيف ‪ .Keras‬يحتفظ بقائمة مرتبة من‬
‫النماذج المكونة ‪ .constituent Models‬الحظ أن كل طبقة من الطبقتين المتصلتين بالكامل‬
‫هي مثيل لكالس ‪ Dense‬التي تعديف حد ذاتها فئة فرعية من النموذج‪ .‬كما أن طريقة االنتشار‬
‫االمامي (االستدعاء ‪ )call‬بسيطة بشكل ملحوظ‪ :‬فهي تربط كل وحدةيف القائمة معًا‪ ،‬وتمرير‬
‫ناتج كل منها كمدخل إلى التالي‪ .‬الحظ أنه حتى اآلن‪ ،‬كنا نستدعي نماذجنا عبر البناء )‪net(X‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪22‬‬

‫للحصول على مخرجاتها‪ .‬هذايف الواقع مجرد اختصار لـ ))‪ ، net.call(X‬خدعة بايثون‬
‫الرائعة التي تم تحقيقها عبر طريقة __‪ __call‬لكالس الوحدة النمطية‪.‬‬

‫‪A Custom Module‬‬ ‫‪6.1.1‬‬


‫ربما تكون أسهل طريقة لتطوير الحدس حول كيفية عمل الوحدة النمطية هي أن ننفذها بأنفسنا‪.‬‬
‫قبل أن ننفذ الوحدة النمطية المخصصة ‪ custom module‬الخاصة بنا‪ ،‬نلخص بإيجاز الوظائف‬
‫األساسية التي يجب أن توفرها كل وحدة‪:‬‬

‫‪ .1‬استوعب بيانات اإلدخال كوسيطات ‪ arguments‬لطريقة االنتشار األمامي ‪forward‬‬


‫‪.propagation‬‬
‫‪ .2‬قم بتوليد مخرجات بجعل طريقة االنتشار األمامي ترجع قيمة‪ .‬الحظ أن اإلخراج قد‬
‫يكون له شكل مختلف عن المدخالت‪ .‬على سبيل المثال ‪ ،‬تستوعب أول طبقة متصلة‬
‫بالكامل ‪ fully connected layer‬في نموذجنا أعاله مدخالت ذات بُعد افتراضي‬
‫ولكنها تُرجع ناتجًا من البعد ‪.256‬‬
‫‪ .3‬احسب التدرج ‪ gradient‬لمخرجاته فيما يتعلق بمدخالته‪ ،‬والتي يمكن الوصول إليها‬
‫عبر أسلوب االنتشار االمامي ‪ backpropagation‬الخاص به‪ .‬عادةً ما يحدث هذا‬
‫تلقائيًا‪.‬‬
‫‪ .4‬قم بتخزين وتوفير الوصول إلى تلك المعلمات الالزمة لتنفيذ حساب االنتشار األمامي‪.‬‬
‫‪ .5‬قم بتهيئة معلمات النموذج حسب الحاجة‪.‬‬

‫في المقتطف التالي‪ ،‬نقوم ببرمجة وحدة نمطية من البداية تتوافق مع ‪ MLP‬بطبقة مخفية واحدة‬
‫تحتوي على ‪ 256‬وحدة مخفية وطبقة إخراج ‪ 10‬أبعاد‪ .‬الحظ أن فئة ‪ MLP‬أدناه ترث الفئة التي‬
‫تمثل وحدة نمطية‪ .‬سوف نعتمد بشكل كبير على طرق الفئة األصلية ‪ ،parent class‬ونزود‬
‫المُنشئ الخاص بنا فقط (طريقة __‪__init‬يف بايثون) وطريقة االنتشار األمامي‪.‬‬

‫‪class MLP(tf.keras.Model):‬‬
‫‪def __init__(self):‬‬
‫‪# Call the constructor of the parent class‬‬
‫‪tf.keras.Model to perform‬‬
‫‪# the necessary initialization‬‬
‫)(__‪super().__init‬‬
‫‪self.hidden = tf.keras.layers.Dense(units=256,‬‬
‫)‪activation=tf.nn.relu‬‬
‫)‪self.out = tf.keras.layers.Dense(units=10‬‬

‫‪# Define the forward propagation of the model, that‬‬


‫‪is, how to return the‬‬
‫‪23‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫‪# required model output based on the input X‬‬


‫‪def call(self, X):‬‬
‫)))‪return self.out(self.hidden((X‬‬
‫دعنا نركز أوالً على طريقة االنتشار األمامي‪ .‬الحظ أنه يأخذ ‪ X‬كمدخل‪ ،‬ويحسب التمثيل المخفي‬
‫مع تطبيق دالة التنشيط‪ ،‬ويخرج سجالته ‪.logits‬يف تطبيق ‪ MLP‬هذا‪ ،‬تعد كلتا الطبقتين‬
‫متغيرات حالة‪ .‬لمعرفة سبب كون ذلك معقوالً‪ ،‬تخيل إنشاء مثيل لـ ‪ net1 ،MLPs‬و ‪،net2‬‬
‫وتدريبهما على بيانات مختلفة‪ .‬بطبيعة الحال‪ ،‬نتوقع منهم أن يمثلوا نموذجين متعلمين مختلفين‪.‬‬

‫نقوم بإنشاء مثيل لطبقات ‪MLP‬يف المُنشئ ومن ثم استدعاء هذه الطبقاتيف كل استدعاء لطريقة‬
‫االنتشار األمامي‪ .‬الحظ بعض التفاصيل األساسية‪ .‬أوالً‪ ،‬تستدعي طريقة __‪__init‬‬
‫المخصصة لدينا طريقة __‪ __init‬الخاصة بالفئة األصلية عبر )(‪__init__() .super‬‬
‫يجنبنا ألم إعادة صياغة الكود المعياري المطبق على معظم الوحدات‪ .‬ثم نقوم بإنشاء مثيل‬
‫للطبقتين المتصلتين تمامًا‪ ،‬ونقوم بتعيينهما إلى ‪ self.hidden‬و ‪ .self.out‬الحظ أنه‬
‫ما لم ننفذ طبقة جديدة‪ ،‬فال داعي للقلق بشأن طريقة ‪ backpropagation‬أو تهيئة المعلمة‪.‬‬
‫سيقوم النظام بإنشاء هذه الطرق تلقائيًا‪ .‬دعونا نجرب هذا‪.‬‬

‫)(‪net = MLP‬‬
‫‪net(X).shape‬‬
‫)]‪TensorShape([2, 10‬‬

‫من المزايا الرئيسية لتجريد الوحدة تعدد استخداماتها ‪ .versatility‬يمكننا تصنيف وحدة نمطية‬
‫فرعية إلنشاء طبقات (مثل فئة الطبقة المتصلة بالكامل)‪ ،‬أو نماذج كاملة (مثل فئة ‪ MLP‬أعاله)‪،‬‬
‫أو مكونات مختلفة من التعقيد الوسيط‪ .‬نستغل هذا التنوعيف الفصول التالية‪ ،‬على سبيل المثال‬
‫عند معالجة الشبكات العصبية التالفيفية ‪.convolutional neural networks‬‬

‫‪The Sequential Module‬‬ ‫‪6.1.2‬‬


‫يمكننا اآلن إلقاء نظرة فاحصة على كيفية عمل الكالس التسلسلي ‪ .Sequential class‬تذكر‬
‫أن ‪ Sequential‬تم تصميمه لربط الوحدات األخرى معًا بطريقة سلسلة ديزي ‪daisy-‬‬
‫‪ .chain‬لبناء ‪ MySequential‬المبسطة الخاصة بنا‪ ،‬نحتاج فقط إلى تحديد طريقتين‬
‫رئيسيتين‪ .1 :‬طريقة إللحاق الوحدات واحدة تلو األخرى بالقائمة‪ .2 .‬طريقة انتشار أمامية لتمرير‬
‫مُدخل من خالل سلسلة الوحدات النمطية‪ ،‬بنفس الترتيب الذي تم إلحاقه به‪.‬‬

‫يوفر كالس ‪ MySequential‬التالي الوظيفة نفسها للكالس ‪ Sequential‬االفتراضي‪.‬‬

‫‪class MySequential(tf.keras.Model):‬‬
‫‪def __init__(self, *args):‬‬
‫)(__‪super().__init‬‬
‫‪self.modules = args‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪24‬‬

‫‪def call(self, X):‬‬


‫‪for module in self.modules:‬‬
‫)‪X = module(X‬‬
‫‪return X‬‬
‫عندما يتم استدعاء طريقة االنتشار األمامي الخاصة بـ ‪ ،MySequential‬يتم تنفيذ كل وحدة‬
‫نمطية مضافة بالترتيب الذي تمت إضافتها به‪ .‬يمكننا اآلن إعادة تطبيق ‪ MLP‬باستخدام كالس‬
‫‪MySequential.‬‬
‫(‪net = MySequential‬‬
‫‪tf.keras.layers.Dense(units=256,‬‬
‫‪activation=tf.nn.relu),‬‬
‫))‪tf.keras.layers.Dense(10‬‬
‫‪net(X).shape‬‬
‫)]‪TensorShape([2, 10‬‬

‫‪ MySequential‬مطابق للرمز الذي كتبناه سابقًا لكالس‬ ‫الحظ أن استخدام‬


‫‪( Sequential‬كما هو موضحيف القسم ‪.)5.1‬‬

‫‪Executing‬‬ ‫‪6.1.3‬‬
‫‪Code in the Forward Propagation Method‬‬
‫تجعل الفئة (الكالس) ‪ Sequential‬إنشاء النموذج أمرًا سهالً‪ ،‬مما يسمح لنا بتجميع بُنى جديدة‬
‫دون الحاجة إلى تحديد فئتنا الخاصة‪ .‬ومع ذلك‪ ،‬ليست كل األبنية عبارة عن سالسل أقحوان‬
‫بسيطة‪ .‬عندما يتطلب األمر مزيدًا من المرونة‪ ،‬سنرغبيف تحديد الكتل الخاصة بنا‪ .‬على سبيل‬
‫المثال‪ ،‬قد نرغبيف تنفيذ تدفق التحكم ‪ control flow‬يف بايثون داخل طريقة االنتشار األمامي‪.‬‬
‫عالوة على ذلك‪ ،‬قد نرغبيف إجراء عمليات حسابية عشوائية‪ ،‬وليس مجرد االعتماد على طبقات‬
‫الشبكة العصبية المحددة مسبقًا‪.‬‬

‫ربما الحظت أنه حتى اآلن‪ ،‬عملت جميع العملياتيف شبكاتنا على عمليات تنشيط شبكتنا‬
‫ومعلماتها‪ .‬ومع ذلك‪،‬يف بعض األحيان‪ ،‬قد نرغبيف دمج المصطلحات التي ليست نتيجة‬
‫الطبقات السابقة وال المعلمات القابلة للتحديث‪ .‬نسمي هذه المعلمات الثابتة ‪constant‬‬
‫‪ .parameters‬لنفترض على سبيل المثال أننا نريد طبقة تحسب الدالة 𝐱 ⊤ 𝐰 ⋅ 𝑐 = )𝐰 ‪،𝑓(𝐱,‬‬
‫حيث 𝐱 اإلدخال‪ ،‬و𝐰 هي المعلمة الخاصة بنا‪ ،‬و𝑐 هي ثابتة محددة لم يتم تحديثها أثناء‬
‫التحسين‪ .‬لذلك قمنا بتطبيق فئة ‪ FixedHiddenMLP‬على النحو التالي‪.‬‬

‫‪class FixedHiddenMLP(tf.keras.Model):‬‬
‫‪def __init__(self):‬‬
‫)(__‪super().__init‬‬
25 Builders’ Guide ‫ دليل البنائين‬:‫الفصل السادس‬

self.flatten = tf.keras.layers.Flatten()
# Random weight parameters created with
`tf.constant` are not updated
# during training (i.e., constant parameters)
self.rand_weight =
tf.constant(tf.random.uniform((20, 20)))
self.dense = tf.keras.layers.Dense(20,
activation=tf.nn.relu)

def call(self, inputs):


X = self.flatten(inputs)
# Use the created constant parameters, as well
as the `relu` and
# `matmul` functions
X = tf.nn.relu(tf.matmul(X, self.rand_weight) +
1)
# Reuse the fully connected layer. This is
equivalent to sharing
# parameters with two fully connected layers
X = self.dense(X)
# Control flow
while tf.reduce_sum(tf.math.abs(X)) > 1:
X /= 2
return tf.reduce_sum(X)
‫ نقوم بتنفيذ طبقة مخفية يتم تهيئة أوزانها‬،‫ هذا‬FixedHiddenMLP ‫في نموذج‬
‫ هذا‬.‫ ) بشكل عشوائي عند إنشاء مثيل لها ثم تصبح ثابتة بعد ذلك‬self.rand_weight(
‫ تقوم‬.backpropagation ‫الوزن ليس معلمة نموذجية وبالتالي ال يتم تحديثه أبدًا عن طريق‬
.‫الشبكة بعد ذلك بتمرير ناتج هذه الطبقة "الثابتة" عبر طبقة متصلة بالكامل‬

‫ واختبارنا‬،while ‫ قمنا بتشغيل حلقة‬.‫ فعل نموذجنا شيئًا غير عادي‬،‫الحظ أنه قبل إعادة اإلخراج‬
.‫ حتى يستوفي الشرط‬2 ‫ وقسمنا متجه اإلخراج على‬، 1 ‫ أكبر من‬ℓ1 ‫على الشرط أن معيارها‬
‫ ال توجد شبكة عصبية قياسية تقوم‬،‫ على حد علمنا‬.X ‫ قمنا بإرجاع مجموع اإلدخاالتيف‬،‫أخيرًا‬
.‫ الحظ أن هذه العملية المحددة قد ال تكون مفيدةيف أي مهمةيف العالم الحقيقي‬.‫بهذه العملية‬
‫ يف تدفق حسابات الشبكة‬arbitrary code ‫هدفنا هو فقط أن نوضح لك كيفية دمج رمز تعسفي‬
.‫العصبية الخاصة بك‬

net = FixedHiddenMLP()
net(X)
<tf.Tensor: shape=(), dtype=float32, numpy=0.81634015>
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪26‬‬

‫يمكننا المزج والتوفيق بين الطرق المختلفة لتجميع ‪ assembling‬الوحدات النمطية معًا‪.‬يف ‬
‫المثال التالي‪ ،‬نقوم بدمج الوحدات النمطية ببعض الطرق اإلبداعية‪.‬‬

‫‪class NestMLP(tf.keras.Model):‬‬
‫‪def __init__(self):‬‬
‫)(__‪super().__init‬‬
‫)(‪self.net = tf.keras.Sequential‬‬
‫‪self.net.add(tf.keras.layers.Dense(64,‬‬
‫))‪activation=tf.nn.relu‬‬
‫‪self.net.add(tf.keras.layers.Dense(32,‬‬
‫))‪activation=tf.nn.relu‬‬
‫‪self.dense = tf.keras.layers.Dense(16,‬‬
‫)‪activation=tf.nn.relu‬‬

‫‪def call(self, inputs):‬‬


‫))‪return self.dense(self.net(inputs‬‬

‫)(‪chimera = tf.keras.Sequential‬‬
‫))(‪chimera.add(NestMLP‬‬
‫))‪chimera.add(tf.keras.layers.Dense(20‬‬
‫))(‪chimera.add(FixedHiddenMLP‬‬
‫)‪chimera(X‬‬
‫>‪<tf.Tensor: shape=(), dtype=float32, numpy=0.63493085‬‬

‫‪6.1.4‬‬
‫الطبقات ‪ Layers‬عبارة عن وحدات نمطية ‪.modules‬‬ ‫•‬
‫يمكن أن تشتمل العديد من الطبقات على وحدة نمطية‪.‬‬ ‫•‬
‫يمكن أن تشتمل العديد من الوحدات على وحدة نمطية‪.‬‬ ‫•‬
‫يمكن أن تحتوي الوحدة النمطية على كود‪.‬‬ ‫•‬
‫تقوم الوحدات النمطية بالكثير المهام‪ ،‬بمايف ذلك تهيئة المعلمات ‪parameter‬‬ ‫•‬
‫‪ initialization‬واالنتشار الخلفي ‪.backpropagation‬‬
‫يتم التعامل مع التسلسل المتسلسل ‪ Sequential concatenations‬للطبقات‬ ‫•‬
‫والوحدات النمطية بواسطة الوحدة النمطية التسلسلية ‪.Sequential‬‬

‫‪6.1.5‬‬
‫‪ .1‬ما أنواع المشاكل التي ستحدث إذا قمت بتغيير ‪ MySequential‬لتخزين‬
‫الوحداتيف قائمة بايثون؟‬
‫‪27‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫‪ .2‬قم بتنفيذ وحدة نمطية تأخذ وحدتين كوسيطة‪ ،‬على سبيل المثال ‪ net1‬و ‪net2‬‬
‫وإرجاع اإلخراج المتسلسل لكلتا الشبكتينيف االنتشار األمامي‪ .‬وهذا ما يسمى أيضًا‬
‫بالوحدة المتوازية ‪.parallel module‬‬
‫‪ .3‬افترض أنك تريد ربط مثيالت متعددة ‪ multiple instances‬من نفس الشبكة‪ .‬قم‬
‫بتنفيذ دالة المصنع ‪ factory function‬التي تنشئ مثيالت متعددة لنفس الوحدة‬
‫وتبني منها شبكة أكبر‪.‬‬

‫‪Parameter Management‬‬ ‫‪6.2‬‬


‫بمجرد اختيار البنية ‪ architecture‬وتعيين المعلمات الفائقة ‪ hyperparameters‬الخاصة بنا‪،‬‬
‫ننتقل إلى حلقة التدريب ‪ ،training loop‬حيث يتمثل هدفنايف العثور على قيم المعلمات التي‬
‫تقلل من دالة الخسارة (الخطأ) لدينا‪ .‬بعد التدريب‪ ،‬سنحتاج إلى هذه المعلمات لعمل تنبؤات‬
‫مستقبلية‪ .‬باإلضافة إلى ذلك‪ ،‬نرغبيف بعض األحيانيف استخراج المعلمات إما إلعادة استخدامها‬
‫في سياق آخر‪ ،‬أو لحفظ نموذجنا على القرص بحيث يمكن تنفيذهيف برامج أخرى‪ ،‬أو للفحص‬
‫على أمل اكتساب الفهم العلمي‪.‬‬

‫في معظم األوقات‪ ،‬سنكون قادرين على تجاهل التفاصيل الدقيقة لكيفية اإلعالن عن المعلمات‬
‫والتالعب بها‪ ،‬باالعتماد على أطر التعلم العميق للقيام بالرفع الثقيل‪ .‬ومع ذلك‪ ،‬عندما نبتعد عن‬
‫البنى المكدسة بطبقات قياسية‪ ،‬سنحتاج أحيانًا إلى الدخوليف أعشاب إعالن المعلمات‬
‫ومعالجتها‪.‬يف هذا القسم‪ ،‬نغطي ما يلي‪:‬‬

‫الوصول إلى معلمات التصحيح ‪ debugging‬والتشخيصات ‪diagnostics‬‬ ‫•‬


‫والتصورات ‪.visualizations‬‬
‫مشاركة المعلمات ‪ Sharing parameters‬عبر مكونات النموذج المختلفة‪.‬‬ ‫•‬

‫نبدأ بالتركيز على ‪ MLP‬بطبقة واحدة مخفية‪.‬‬

‫‪import tensorflow as tf‬‬

‫[(‪net = tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Flatten(),‬‬
‫‪tf.keras.layers.Dense(4, activation=tf.nn.relu),‬‬
‫‪tf.keras.layers.Dense(1),‬‬
‫)]‬

‫))‪X = tf.random.uniform((2, 4‬‬


‫‪net(X).shape‬‬
‫)]‪TensorShape([2, 1‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪28‬‬

‫‪Parameter Access‬‬ ‫‪6.2.1‬‬


‫لنبدأ بكيفية الوصول إلى المعلمات من النماذج التي تعرفها بالفعل‪ .‬عندما يتم تعريف نموذج‬
‫عبر الفئة ‪ ،Sequential‬يمكننا أوالً الوصول إلى أي طبقة عن طريق فهرستهايف النموذج كما‬
‫لو كانت قائمة ‪ .list‬يتم وضع معلمات كل طبقة بشكل مالئميف جدولها‪ .‬يمكننا فحص معلمات‬
‫الطبقة الثانية المتصلة بالكامل على النحو التالي‪.‬‬

‫‪net.layers[2].weights‬‬
‫)‪[<tf.Variable 'dense_1/kernel:0' shape=(4, 1‬‬
‫=‪dtype=float32, numpy‬‬
‫‪array([[ 0.2706747],‬‬
‫‪[ 0.7514136],‬‬
‫‪[-0.7881366],‬‬
‫‪[-0.1292265]], dtype=float32)>,‬‬
‫‪<tf.Variable 'dense_1/bias:0' shape=(1,) dtype=float32,‬‬
‫]>)‪numpy=array([0.], dtype=float32‬‬
‫يمكننا أن نرى أن هذه الطبقة المتصلة بالكامل تحتوي على معلمتين‪ ،‬تقابل أوزان ‪ weights‬تلك‬
‫الطبقة وانحيازاتها ‪ ،biases‬على التوالي‪.‬‬

‫‪Targeted Parameters‬‬ ‫‪6.2.1.1‬‬


‫الحظ أنه يتم تمثيل كل معلمة كمثيل ‪ instance‬لفئة (كالس) المعلمة ‪ .parameter‬للقيام بأي‬
‫شيء مفيد مع المعلمات‪ ،‬نحتاج أوالً إلى الوصول إلى القيم العددية األساسية‪ .‬هناك عدة طرق‬
‫للقيام بذلك‪ .‬بعضها أبسط بينما البعض اآلخر أكثر عمومية‪ .‬يستخرج الكود التالي التحيز من‬
‫طبقة الشبكة العصبية الثانية‪ ،‬والتي تعرض مثيل فئة المعلمة‪ ،‬وتصل إلى قيمة هذه المعلمة بشكل‬
‫أكبر‪.‬‬

‫‪type(net.layers[2].weights[1]),‬‬
‫)]‪tf.convert_to_tensor(net.layers[2].weights[1‬‬
‫‪(tensorflow.python.ops.resource_variable_ops.ResourceVar‬‬
‫‪iable,‬‬
‫‪<tf.Tensor: shape=(1,), dtype=float32,‬‬
‫)>)‪numpy=array([0.], dtype=float32‬‬
‫‪All Parameters at Once‬‬ ‫‪6.2.1.2‬‬
‫عندما نحتاج إلى إجراء عمليات على جميع المعلمات‪ ،‬فإن الوصول إليها واحدًا تلو اآلخر يمكن‬
‫أن يصبح ممالً‪ .‬يمكن أن يصبح الموقف صعبًا بشكل خاص عندما نعمل مع وحدات أكثر تعقيدًا‬
‫(على سبيل المثال‪ ،‬الوحدات المتداخلة ‪ ،)nested modules‬نظرًا ألننا سنحتاج إلى التكرار‬
‫من خالل الشجرة بأكملها الستخراج معلمات كل وحدة فرعية‪ .‬أدناه نوضح الوصول إلى معلمات‬
‫جميع الطبقات‪.‬‬
‫‪29‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫)(‪net.get_weights‬‬
‫‪[array([[-0.25718492, -0.02684402, 0.38722616, -‬‬
‫‪0.21718812],‬‬
‫‪[ 0.8491538 , 0.2304619 , 0.37694377,‬‬
‫‪0.5665582 ],‬‬
‫‪[-0.4560371 , 0.7668019 , -0.52032065,‬‬
‫‪0.6611255 ],‬‬
‫‪[ 0.04601806, 0.5825514 , 0.7364692 ,‬‬
‫‪0.70636266]],‬‬
‫‪dtype=float32),‬‬
‫‪array([0., 0., 0., 0.], dtype=float32),‬‬
‫‪array([[ 0.2706747],‬‬
‫‪[ 0.7514136],‬‬
‫‪[-0.7881366],‬‬
‫‪[-0.1292265]], dtype=float32),‬‬
‫])‪array([0.], dtype=float32‬‬
‫‪Tied Parameters‬‬ ‫‪6.2.2‬‬
‫في كثير من األحيان‪ ،‬نريد مشاركة المعلمات عبر طبقات متعددة‪ .‬دعونا نرى كيف نفعل ذلك‬
‫بأناقة‪ .‬فيما يلي نخصص طبقة متصلة بالكامل ثم نستخدم معلماتها على وجه التحديد لتعيين‬
‫تلك الخاصة بطبقة أخرى‪ .‬نحتاج هنا إلى تشغيل االنتشار األمامية )‪net(X‬قبل الوصول إلى‬
‫المعلمات‪.‬‬

‫‪# tf.keras behaves a bit differently. It removes the‬‬


‫‪duplicate layer‬‬
‫‪# automatically‬‬
‫)‪shared = tf.keras.layers.Dense(4, activation=tf.nn.relu‬‬
‫[(‪net = tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Flatten(),‬‬
‫‪shared,‬‬
‫‪shared,‬‬
‫‪tf.keras.layers.Dense(1),‬‬
‫)]‬
‫)‪net(X‬‬
‫‪# Check whether the parameters are different‬‬
‫)‪print(len(net.layers) == 3‬‬
‫‪True‬‬

‫يوضح هذا المثال أن معلمات الطبقة الثانية والثالثة مرتبطة‪ .‬إنهما ليسا متساويين فقط‪ ،‬بل يتم‬
‫تمثيلهما بنفس الموتر الدقيق ‪ .exact tensor‬وبالتالي‪ ،‬إذا قمنا بتغيير أحد المعلمات‪ ،‬يتغير‬
‫اآلخر أيضًا‪ .‬قد تتساءل‪ ،‬عندما يتم ربط المعلمات‪ ،‬ماذا يحدث للتدرجات ‪gradients‬؟ نظرًا‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪30‬‬

‫ألن معلمات النموذج تحتوي على تدرجات‪ ،‬يتم إضافة تدرجات الطبقة المخفية الثانية والطبقة‬
‫المخفية الثالثة معًا أثناء النشر الخلفي ‪.backpropagation‬‬

‫‪6.2.3‬‬
‫لدينا عدة طرق للوصول إلى معلمات النموذج وربطها‪.‬‬

‫‪6.2.4‬‬
‫‪ .1‬استخدم نموذج ‪ NestMLP‬المحدديف القسم ‪ 6.1‬وقم بالوصول إلى معلمات الطبقات‬
‫المختلفة‪.‬‬
‫‪ .2‬أنشئ ‪ MLP‬يحتوي على طبقة معلمة مشتركة وقم بتدريبها‪ .‬أثناء عملية التدريب‪،‬‬
‫الحظ معلمات النموذج والتدرجات لكل طبقة‪.‬‬
‫‪ .3‬لماذا تعتبر مشاركة المعلمات فكرة جيدة؟‬

‫‪Parameter Initialization‬‬ ‫‪6.3‬‬


‫اآلن بعد أن عرفنا كيفية الوصول إلى المعلمات‪ ،‬دعنا نلقي نظرة على كيفية تهيئتها ‪initialize‬‬
‫بشكل صحيح‪ .‬ناقشنا الحاجة إلى التهيئة المناسبة ‪ proper initialization‬يف القسم ‪ .5.4‬يوفر‬
‫إطار عمل التعلم العميق عمليات تهيئة عشوائية ‪ random initializations‬افتراضية لطبقاته‪.‬‬
‫ومع ذلك‪ ،‬فإننا غالبًا ما نرغبيف تهيئة أوزاننا وفقًا لبروتوكوالت أخرى مختلفة‪ .‬يوفر إطار العمل‬
‫البروتوكوالت األكثر استخدامًا‪ ،‬ويسمح أيضًا بإنشاء مُهيئ مخصص ‪.custom initializer‬‬

‫بشكل افتراضي‪ ،‬يقوم ‪ Keras‬بتهيئة مصفوفات الوزن ‪ weight matrices‬بشكل موحد من‬
‫خالل الرسم من نطاق يتم حسابه وفقًا ألبعاد اإلدخال واإلخراج‪ ،‬ويتم تعيين جميع معلمات‬
‫التحيز على الصفر‪ .‬يوفر ‪ TensorFlow‬مجموعة متنوعة من طرق التهيئةيف كل من الوحدة‬
‫النمطية الجذر ‪ root‬ووحدة ‪.keras.initializers‬‬

‫‪import tensorflow as tf‬‬

‫[(‪net = tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Flatten(),‬‬
‫‪tf.keras.layers.Dense(4, activation=tf.nn.relu),‬‬
‫‪tf.keras.layers.Dense(1),‬‬
‫)]‬

‫))‪X = tf.random.uniform((2, 4‬‬


‫‪net(X).shape‬‬
‫)]‪TensorShape([2, 1‬‬
31 Builders’ Guide ‫ دليل البنائين‬:‫الفصل السادس‬

Built-in Initialization 6.3.1


‫ يقوم الكود أدناه بتهيئة جميع‬.built-in initializers ‫لنبدأ باالتصال بالمهيئات المدمجين‬
‫ بينما تم مسح معلمات‬،0.01 ‫معلمات الوزن كمتغيرات عشوائية غاوسية بانحراف معياري‬
.‫التحيز إلى الصفر‬

net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4, activation=tf.nn.relu,

kernel_initializer=tf.random_normal_initializer(mean=0,
stddev=0.01),
bias_initializer=tf.zeros_initializer()),
tf.keras.layers.Dense(1)])

net(X)
net.weights[0], net.weights[1]
(<tf.Variable 'dense_2/kernel:0' shape=(4, 4)
dtype=float32, numpy=
array([[-4.3637343e-03, 1.4685265e-02, 1.1814130e-02,
1.0973577e-02],
[ 4.1117594e-03, -1.4918787e-02, -2.7245909e-03,
2.2734334e-03],
[-2.3910873e-02, -2.1292072e-02, -1.7594380e-02,
2.9788772e-03],
[-2.9245612e-05, 1.7144383e-03, 2.0546305e-03,
1.0586854e-03]],
dtype=float32)>,
<tf.Variable 'dense_2/bias:0' shape=(4,) dtype=float32,
numpy=array([0., 0., 0., 0.], dtype=float32)>)
.)1 ،‫يمكننا أيضًا تهيئة جميع المعلمات إلى قيمة ثابتة معينة (على سبيل المثال‬

net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4, activation=tf.nn.relu,

kernel_initializer=tf.keras.initializers.Constant(1),
bias_initializer=tf.zeros_initializer()),
tf.keras.layers.Dense(1),
])
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 32

net(X)
net.weights[0], net.weights[1]
(<tf.Variable 'dense_4/kernel:0' shape=(4, 4)
dtype=float32, numpy=
array([[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.],
[1., 1., 1., 1.]], dtype=float32)>,
<tf.Variable 'dense_4/bias:0' shape=(4,) dtype=float32,
numpy=array([0., 0., 0., 0.], dtype=float32)>)
‫ نقوم أدناه‬،‫ على سبيل المثال‬.certain blocks ‫يمكننا أيضًا تطبيق مُهيِّئات مختلفة لكتل معينة‬
.42 ‫ وتهيئة الطبقة الثانية إلى قيمة ثابتة تبلغ‬Xavier ‫بتهيئة الطبقة األولى باستخدام مُهيئ‬

net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4,
activation=tf.nn.relu,

kernel_initializer=tf.keras.initializers.GlorotUniform()
),
tf.keras.layers.Dense(
1,
kernel_initializer=tf.keras.initializers.Constant(42)),
])

net(X)
print(net.layers[1].weights[0])
print(net.layers[2].weights[0])
<tf.Variable 'dense_6/kernel:0' shape=(4, 4)
dtype=float32, numpy=
array([[ 0.62105197, 0.0110271 , 0.77947575,
0.42430252],
[ 0.7728824 , -0.06041008, 0.7212722 ,
0.3408653 ],
[-0.23351735, -0.16163725, 0.8497241 , -
0.29418987],
[-0.52923286, -0.5558266 , -0.1514526 , -
0.73771775]],
dtype=float32)>
<tf.Variable 'dense_7/kernel:0' shape=(4, 1)
dtype=float32, numpy=
33 Builders’ Guide ‫ دليل البنائين‬:‫الفصل السادس‬

array([[42.],
[42.],
[42.],
[42.]], dtype=float32)>
Custom Initialization 6.3.1.1
‫يف‬.‫ ال يتم توفير طرق التهيئة التي نحتاجها بواسطة إطار عمل التعلم العميق‬،‫في بعض األحيان‬
:‫ نحدد مُهيئًا ألي معلمة 𝑤 وزن باستخدام التوزيع الغريب التالي‬،‫المثال أدناه‬
1
𝑈(5,10) with probability
4
1
𝑤∼{ 0 with probability
2
1
𝑈(−10, −5) with probability
4
‫__ التي تُرجع الموتر‬call__ ‫وننفذ دالة‬Initializer ‫ من‬subclass ‫هنا نحدد فئة فرعية‬
.‫المطلوب بالنظر إلى الشكل ونوع البيانات‬

class MyInit(tf.keras.initializers.Initializer):
def __call__(self, shape, dtype=None):
data=tf.random.uniform(shape, -10, 10,
dtype=dtype)
factor=(tf.abs(data) >= 5)
factor=tf.cast(factor, tf.float32)
return data * factor

net = tf.keras.models.Sequential([
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(
4,
activation=tf.nn.relu,
kernel_initializer=MyInit()),
tf.keras.layers.Dense(1),
])

net(X)
print(net.layers[1].weights[0])
<tf.Variable 'dense_8/kernel:0' shape=(4, 4)
dtype=float32, numpy=
array([[ 6.262211 , 0. , 0. , 7.670639 ],
[ 8.288603 , 8.044296 , 6.477192 , -0. ],
[-0. , 0. , -0. , -0. ],
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪34‬‬

‫‪[-0.‬‬ ‫‪, -0.‬‬ ‫‪, -7.4122763, -5.566807‬‬


‫>)‪]], dtype=float32‬‬
‫الحظ أنه لدينا دائمًا خيار تعيين المعلمات مباشرةً‪.‬‬

‫‪net.layers[1].weights[0][:].assign(net.layers[1].weights‬‬
‫)‪[0] + 1‬‬
‫)‪net.layers[1].weights[0][0, 0].assign(42‬‬
‫]‪net.layers[1].weights[0‬‬
‫)‪<tf.Variable 'dense_8/kernel:0' shape=(4, 4‬‬
‫=‪dtype=float32, numpy‬‬
‫‪array([[42.‬‬ ‫‪, 1.‬‬ ‫‪, 1.‬‬ ‫‪, 8.670639 ],‬‬
‫‪[ 9.288603 , 9.044296 , 7.477192 , 1.‬‬ ‫‪],‬‬
‫‪[ 1.‬‬ ‫‪, 1.‬‬ ‫‪, 1.‬‬ ‫‪, 1.‬‬ ‫‪],‬‬
‫‪[ 1.‬‬ ‫‪, 1.‬‬ ‫‪, -6.4122763, -4.566807‬‬
‫>)‪]], dtype=float32‬‬
‫‪6.3.2‬‬
‫يمكننا تهيئة المعلمات باستخدام مُهيِّئات مضمنة (مدمجة) ‪ built-in‬ومخصصة ‪.custom‬‬

‫‪6.3.3‬‬
‫ابحث عن الوثائق عبر اإلنترنت للحصول على المزيد من المهيئات المدمجة ‪built-in‬‬
‫‪.initializers‬‬

‫‪Lazy Initialization‬‬ ‫‪6.4‬‬


‫حتى اآلن‪ ،‬قد يبدو أننا أفلتنا من الوقوعيف اإلهماليف إنشاء شبكاتنا‪ .‬على وجه التحديد‪ ،‬قمنا‬
‫باألشياء التالية غير البديهية‪ ،‬والتي قد ال يبدو أنها يجب أن تعمل‪:‬‬

‫حددنا معماريات الشبكة دون تحديد أبعاد اإلدخال‪.‬‬ ‫•‬


‫أضفنا طبقات دون تحديد أبعاد اإلخراج للطبقة السابقة‪.‬‬ ‫•‬
‫حتى أننا "قمنا بتهيئة" هذه المعلمات قبل تقديم معلومات كافية لتحديد عدد المعلمات‬ ‫•‬
‫التي يجب أن تحتويها نماذجنا‪.‬‬

‫قد تتفاجأ من أن الكود الخاص بنا يعمل على اإلطالق‪ .‬بعد كل شيء‪ ،‬ال توجد طريقة يمكن‬
‫إلطار التعلم العميق أن يخبرنا بها عن أبعاد إدخال الشبكة‪ .‬الحيلة هنا هي أن إطار العمل يؤجل‬
‫‪ defer‬التهيئة ‪،initialization‬يف انتظار أول مرة نقوم فيها بتمرير البيانات عبر النموذج‪،‬‬
‫الستنتاج أحجام كل طبقة أثناء الطيران‪.‬‬

‫في وقت الحق‪ ،‬عند العمل مع الشبكات العصبية التالفيفية ‪ ،CNN‬ستصبح هذه التقنية أكثر‬
‫مالءمة ألن أبعاد اإلدخال (أي دقة الصورة) ستؤثر على أبعاد كل طبقة الحقة‪ .‬ومن ثم‪ ،‬فإن‬
‫‪35‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫القدرة على تعيين المعلمات دون الحاجة إلى معرفة‪،‬يف وقت كتابة الكود‪ ،‬ما هي األبعاد يمكن أن‬
‫يبسط إلى حد كبير مهمة تحديد النماذج وتعديلها الحقًا‪ .‬بعد ذلك‪ ،‬نتعمقيف آليات التهيئة‪.‬‬

‫للبدء‪ ،‬دعنا ننشئ مثيلًا لـ ‪.MLP‬‬

‫‪import tensorflow as tf‬‬

‫[(‪net = tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Dense(256, activation=tf.nn.relu),‬‬
‫‪tf.keras.layers.Dense(10),‬‬
‫)]‬
‫في هذه المرحلة‪ ،‬ال يمكن للشبكة معرفة أبعاد أوزان طبقة اإلدخال ‪input layer’s weights‬‬
‫ألن بُعد اإلدخال يظل غير معروف‪ .‬وبالتالي‪ ،‬لم يقم إطار العمل بعد بتهيئة أي معلمات‪ .‬نؤكد‬
‫بمحاولة الوصول إلى المعلمات أدناه‬

‫‪[net.layers[i].get_weights() for i in‬‬


‫]))‪range(len(net.layers‬‬
‫]][ ‪[[],‬‬
‫الحظ أن كل كائنات طبقة موجودة ولكن األوزان فارغة‪ .‬قد يؤدي استخدام‬
‫)(‪ net.get_weights‬إلى حدوث خطأ ألن األوزان لم تتم تهيئتها بعد‪.‬‬

‫بعد ذلك‪ ،‬دعنا نمرر البيانات عبر الشبكة لجعل إطار العمل يهيئ المعلمات أخيرًا‪.‬‬

‫))‪X = tf.random.uniform((2, 20‬‬


‫)‪net(X‬‬
‫])(‪[w.shape for w in net.get_weights‬‬
‫])‪[(20, 256), (256,), (256, 10), (10,‬‬
‫بمجرد أن نعرف أبعاد اإلدخال‪ ،20 ،‬يمكن إلطار العمل تحديد شكل مصفوفة وزن الطبقة األولى‬
‫عن طريق توصيل القيمة ‪ .20‬بعد التعرف على شكل الطبقة األولى‪ ،‬ينتقل اإلطار إلى الطبقة‬
‫الثانية‪ ،‬وهكذا من خالل الرسم البياني الحسابي حتى تعرف كل األشكال‪ .‬الحظ أنهيف هذه الحالة‪،‬‬
‫تتطلب الطبقة األولى فقط تهيئة كسولة ‪ ،lazy initialization‬ولكن يتم تهيئة إطار العمل‬
‫بالتسلسل ‪ .sequentially‬بمجرد معرفة جميع أشكال المعلمات‪ ،‬يمكن لإلطار أخيرًا تهيئة‬
‫المعلمات‪.‬‬

‫‪6.4.1‬‬
‫يمكن أن تكون التهيئة الكسولة مريحة‪ ،‬مما يسمح إلطار العمل باستنتاج أشكال‬ ‫•‬
‫المعلمات تلقائيًا‪ ،‬مما يجعل من السهل تعديل ال ُبنى والقضاء على مصدر واحد شائع‬
‫لألخطاء‪.‬‬
‫يمكننا تمرير البيانات عبر النموذج لجعل اإلطار يهيئ المعلمات أخيرًا‪.‬‬ ‫•‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪36‬‬

‫‪6.4.2‬‬
‫‪ .1‬ماذا يحدث إذا قمت بتحديد أبعاد اإلدخال للطبقة األولى وليس للطبقات الالحقة؟‬
‫هل تحصل على تهيئة فورية ‪immediate initialization‬؟‬
‫‪ .2‬ماذا يحدث إذا قمت بتحديد أبعاد غير متطابقة ‪mismatching dimensions‬؟‬
‫‪ .3‬ماذا يجب أن تفعل إذا كان لديك مدخالت ذات أبعاد متفاوتة ‪varying‬‬
‫‪dimensionality‬؟ تلميح‪ :‬انظر إلى ربط المعلمة ‪.parameter tying‬‬

‫‪Custom Layers‬‬ ‫‪6.5‬‬


‫أحد العوامل الكامنة وراء نجاح التعلم العميق هو توافر مجموعة واسعة من الطبقات التي يمكن‬
‫تكوينها بطرق إبداعية لتصميم بنى مناسبة لمجموعة متنوعة من المهام‪ .‬على سبيل المثال‪ ،‬ابتكر‬
‫الباحثون طبقات خصيصًا للتعامل مع الصور والنص والتكرار عبر البيانات المتسلسلة وأداء‬
‫البرمجة الديناميكية‪ .‬عاجالً أم آجالً‪ ،‬ستواجه أو تخترع طبقة غير موجودة بعديف إطار التعلم‬
‫العميق‪.‬يف هذه الحاالت‪ ،‬يجب عليك إنشاء طبقة مخصصة ‪.custom layer‬يف هذا القسم‪،‬‬
‫نوضح لك كيف‪.‬‬

‫‪Layers without Parameters‬‬ ‫‪6.5.1‬‬


‫للبدء‪ ،‬نقوم ببناء طبقة مخصصة ال تحتوي على أي معلمات خاصة بها‪ .‬يجب أن يبدو هذا مألوفًا‬
‫إذا كنت تتذكر مقدمتنا للوحدةيف القسم ‪ .6.1‬فئة ‪ CenteredLayer‬التالية تطرح ببساطة‬
‫المتوسط من مدخالتها‪ .‬إلنشائه‪ ،‬نحتاج ببساطة إلى الوراثة من فئة الطبقة األساسية وتنفيذ دالة‬
‫االنتشار األمامي‪.‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪class CenteredLayer(tf.keras.Model):‬‬
‫‪def __init__(self):‬‬
‫)(__‪super().__init‬‬

‫‪def call(self, inputs):‬‬


‫)‪return inputs - tf.reduce_mean(inputs‬‬
‫دعنا نتحقق من أن طبقتنا تعمل على النحو المنشود عن طريق تغذية بعض البيانات من خاللها‪.‬‬

‫)(‪layer = CenteredLayer‬‬
‫))]‪layer(tf.constant([1.0, 2, 3, 4, 5‬‬
‫‪<tf.Tensor: shape=(5,), dtype=float32, numpy=array([-2.,‬‬
‫>)‪-1., 0., 1., 2.], dtype=float32‬‬
‫‪37‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫يمكننا اآلن دمج ‪ incorporate‬طبقتنا كمكونيف بناء نماذج أكثر تعقيدًا‪.‬‬

‫‪net = tf.keras.Sequential([tf.keras.layers.Dense(128),‬‬
‫)])(‪CenteredLayer‬‬
‫كتحقق إضافي من الصحة‪ ،‬يمكننا إرسال بيانات عشوائية عبر الشبكة والتحقق من أن المتوسط‬
‫هويف الواقع ‪ .0‬نظرًا ألننا نتعامل مع أرقام الفاصلة العائمة ‪ ،floating point numbers‬فقد ال‬
‫نزال نرى عددًا صغيرًا جدًا غير صفري بسبب التكميم ‪.quantization‬‬

‫)))‪Y = net(tf.random.uniform((4, 8‬‬


‫)‪tf.reduce_mean(Y‬‬
‫‪<tf.Tensor: shape=(), dtype=float32, numpy=-4.656613e-‬‬
‫>‪10‬‬
‫‪Layers with Parameters‬‬ ‫‪6.5.2‬‬
‫اآلن بعد أن عرفنا كيفية تحديد الطبقات البسيطة‪ ،‬دعنا ننتقل إلى تحديد الطبقات باستخدام‬
‫المعلمات التي يمكن تعديلها من خالل التدريب‪ .‬يمكننا استخدام دوال مدمجة إلنشاء معلمات‬
‫توفر بعض الدوال األساسية‪ .‬على وجه الخصوص‪ ،‬تحكم الوصول والتهيئة والمشاركة والحفظ‬
‫وتحميل معلمات النموذج‪ .‬بهذه الطريقة‪ ،‬من بين الفوائد األخرى‪ ،‬لن نحتاج إلى كتابة إجراءات‬
‫تسلسل مخصصة لكل طبقة مخصصة‪.‬‬

‫اآلن دعونا ننفذ نسختنا الخاصة من الطبقة المتصلة بالكامل ‪ .fully connected layer‬تذكر‬
‫أن هذه الطبقة تتطلب معلمتين‪ ،‬أحدهما يمثل الوزن واآلخر يمثل التحيز‪.‬يف هذا التنفيذ‪ ،‬نختار‬
‫دالة تنشيط ‪ ReLU‬كإعداد افتراضي‪ .‬تتطلب هذه الطبقة وسيطتي إدخال‪in_units :‬‬
‫و‪ ،units‬والتي تشير إلى عدد المدخالت والمخرجات‪ ،‬على التوالي‪.‬‬

‫‪class MyDense(tf.keras.Model):‬‬
‫‪def __init__(self, units):‬‬
‫)(__‪super().__init‬‬
‫‪self.units = units‬‬

‫‪def build(self, X_shape):‬‬


‫‪self.weight = self.add_weight(name='weight',‬‬
‫‪shape=[X_shape[-1], self.units],‬‬
‫))(‪initializer=tf.random_normal_initializer‬‬
‫(‪self.bias = self.add_weight‬‬
‫‪name='bias', shape=[self.units],‬‬
‫))(‪initializer=tf.zeros_initializer‬‬

‫‪def call(self, X):‬‬


‫‪linear = tf.matmul(X, self.weight) + self.bias‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪38‬‬

‫)‪return tf.nn.relu(linear‬‬
‫بعد ذلك‪ ،‬نقوم بإنشاء مثيل لفئة ‪MyDense‬والوصول إلى معلمات النموذج الخاصة بها‪.‬‬

‫)‪dense = MyDense(3‬‬
‫)))‪dense(tf.random.uniform((2, 5‬‬
‫)(‪dense.get_weights‬‬
‫‪[array([[-0.02223266, -0.04409523, 0.01749811],‬‬
‫‪[ 0.04932142, -0.07135182, 0.08249469],‬‬
‫‪[ 0.05460888, 0.01363679, 0.0342483 ],‬‬
‫‪[-0.02898769, -0.03092524, -0.02166725],‬‬
‫‪[-0.05692595, -0.03148399, 0.05532912]],‬‬
‫‪dtype=float32),‬‬
‫])‪array([0., 0., 0.], dtype=float32‬‬
‫يمكننا إجراء حسابات االنتشار األمامي ‪ forward propagation‬مباشرة باستخدام طبقات‬
‫مخصصة ‪.custom layers‬‬

‫)))‪dense(tf.random.uniform((2, 5‬‬
‫=‪<tf.Tensor: shape=(2, 3), dtype=float32, numpy‬‬
‫‪array([[0.01219213, 0.‬‬ ‫‪, 0.12613392],‬‬
‫‪[0.‬‬ ‫‪, 0.‬‬ ‫‪, 0.02558431]],‬‬
‫>)‪dtype=float32‬‬
‫يمكننا أيضًا إنشاء نماذج باستخدام طبقات مخصصة‪ .‬بمجرد أن نحصل على ذلك‪ ،‬يمكننا‬
‫استخدامه تمامًا مثل الطبقة المضمنة المتصلة بالكامل‪.‬‬

‫‪net = tf.keras.models.Sequential([MyDense(8),‬‬
‫)])‪MyDense(1‬‬
‫)))‪net(tf.random.uniform((2, 64‬‬
‫=‪<tf.Tensor: shape=(2, 1), dtype=float32, numpy‬‬
‫‪array([[0.00192496],‬‬
‫‪[0.‬‬ ‫>)‪]], dtype=float32‬‬
‫‪6.5.3‬‬
‫يمكننا تصميم طبقات مخصصة عبر فئة الطبقة األساسية‪ .‬يتيح لنا ذلك تحديد طبقات‬ ‫•‬
‫جديدة مرنة تتصرف بشكل مختلف عن أي طبقات موجودةيف المكتبة‪.‬‬
‫بمجرد تحديدها‪ ،‬يمكن استدعاء الطبقات المخصصةيف سياقات وبنيات عشوائية‪.‬‬ ‫•‬
‫يمكن أن تحتوي الطبقات على معلمات محلية ‪ ،local parameters‬والتي يمكن‬ ‫•‬
‫إنشاؤها من خالل الدوال المضمنة ‪.built-in functions‬‬
‫‪39‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫‪6.5.4‬‬
‫‪ .1‬صمم طبقة تأخذ مدخالً وتحسب تقليل الموتر ‪ ،tensor reduction‬أي أنها ترجع‬
‫𝑗‪.𝑦𝑘 = ∑𝑖,‬‬ ‫𝑗𝑥 𝑖𝑥 𝑘𝑗𝑖𝑊‬
‫‪ .2‬صمم طبقة تُرجع النصف المتصدر ‪ leading half‬من معامالت فورييه ‪Fourier‬‬
‫‪ coefficients‬للبيانات‪.‬‬

‫‪File I/O‬‬ ‫‪6.6‬‬


‫ناقشنا حتى اآلن كيفية معالجة البيانات وكيفية بناء نماذج التعلم العميق وتدريبها واختبارها‪ .‬ومع‬
‫ذلك‪،‬يف مرحلة ما‪ ،‬نأمل أن نكون سعداء بدرجة كافية بالنماذج التي تم تعلمها والتي سنرغبيف ‬
‫حفظ النتائج الستخدامها الحقًايف سياقات مختلفة (ربما حتى لعمل تنبؤاتيف النشر)‪ .‬باإلضافة‬
‫إلى ذلك‪ ،‬عند إجراء عملية تدريب طويلة‪ ،‬فإن أفضل الممارسات هي حفظ النتائج الوسيطة‬
‫بشكل دوري (‪ ) checkpointing‬للتأكد من أننا ال نفقد عدة أيام من العمليات الحسابية إذا كنا‬
‫نتحرك عبر سلك الطاقة الخاص بخادمنا‪ .‬وبالتالي فقد حان الوقت لمعرفة كيفية تحميل وتخزين‬
‫متجهات الوزن الفردية والنماذج بأكملها‪ .‬هذا القسم يعالج كال المسألتين‪.‬‬

‫‪Loading and Saving Tensors‬‬ ‫‪6.6.1‬‬


‫بالنسبة إلى الموترات الفردية ‪ ،individual tensors‬يمكننا مباشرة استدعاء دوال التحميل‬
‫‪load‬والحفظ ‪ save‬لقراءتها وكتابتها على التوالي‪ .‬تتطلب كلتا الدالتين توفير اسم‪ ،‬ويتطلب‬
‫الحفظ حفظ المتغير كمدخل‪.‬‬

‫‪import numpy as np‬‬


‫‪import tensorflow as tf‬‬

‫)‪x = tf.range(4‬‬
‫)‪np.save('x-file.npy', x‬‬
‫يمكننا اآلن قراءة البيانات من الملف المخزن مرة أخرىيف الذاكرة‪.‬‬

‫)‪x2 = np.load('x-file.npy', allow_pickle=True‬‬


‫‪x2‬‬
‫)‪array([0, 1, 2, 3], dtype=int32‬‬
‫يمكننا تخزين قائمة الموترات وقراءتها مرة أخرىيف الذاكرة‪.‬‬

‫)‪y = tf.zeros(4‬‬
‫)]‪np.save('xy-files.npy', [x, y‬‬
‫)‪x2, y2 = np.load('xy-files.npy', allow_pickle=True‬‬
‫)‪(x2, y2‬‬
‫))]‪(array([0., 1., 2., 3.]), array([0., 0., 0., 0.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪40‬‬

‫يمكننا حتى كتابة وقراءة قاموس يقوم بالتخطيط من السالسل ‪ strings‬إلى الموترات ‪.tensors‬‬
‫هذا مناسب عندما نريد قراءة أو كتابة جميع األوزانيف النموذج‪.‬‬

‫}‪mydict = {'x': x, 'y': y‬‬


‫)‪np.save('mydict.npy', mydict‬‬
‫)‪mydict2 = np.load('mydict.npy', allow_pickle=True‬‬
‫‪mydict2‬‬
‫‪array({'x': <tf.Tensor: shape=(4,), dtype=int32,‬‬
‫‪numpy=array([0, 1, 2, 3], dtype=int32)>, 'y':‬‬
‫‪<tf.Tensor: shape=(4,), dtype=float32, numpy=array([0.,‬‬
‫‪0., 0., 0.], dtype=float32)>},‬‬
‫‪Loading and Saving Model‬‬ ‫‪6.6.2‬‬
‫‪Parameters‬‬
‫يعد حفظ متجهات الوزن الفردية (أو الموترات األخرى) أمرًا مفيدًا‪ ،‬ولكنه يصبح ممالً للغاية إذا‬
‫أردنا حفظ (وتحميل الحقًا) نموذجًا كامالً‪ .‬بعد كل شيء‪ ،‬قد يكون لدينا مئات من مجموعات‬
‫المعلمات متناثرةيف جميع األنحاء‪ .‬لهذا السبب‪ ،‬يوفر إطار عمل التعلم العميق دوال مدمجة‬
‫لتحميل وح فظ الشبكات بأكملها‪ .‬من التفاصيل المهمة التي يجب مالحظتها أن هذا يحفظ‬
‫معلمات النموذج وليس النموذج بأكمله‪ .‬على سبيل المثال‪ ،‬إذا كان لدينا ‪ MLP‬ثالثي الطبقات‪،‬‬
‫فنحن بحاجة إلى تحديد البنية بشكل منفصل‪ .‬والسببيف ذلك هو أن النماذج نفسها يمكن أن‬
‫تحتوي على رمز تعسفي ‪ ،arbitrary code‬وبالتالي ال يمكن إجراء تسلسل لها بشكل طبيعي‪.‬‬
‫وبالتالي‪ ،‬من أجل إعادة النموذج إلى وضعه السابق‪ ،‬نحتاج إلى إنشاء ال ُبنيةيف التعليمات البرمجية‬
‫ثم تحميل المعلمات من القرص‪ .‬لنبدأ بـ ‪ MLP‬المألوف لدينا‪.‬‬

‫‪class MLP(tf.keras.Model):‬‬
‫‪def __init__(self):‬‬
‫)(__‪super().__init‬‬
‫)(‪self.flatten = tf.keras.layers.Flatten‬‬
‫‪self.hidden = tf.keras.layers.Dense(units=256,‬‬
‫)‪activation=tf.nn.relu‬‬
‫)‪self.out = tf.keras.layers.Dense(units=10‬‬

‫‪def call(self, inputs):‬‬


‫)‪x = self.flatten(inputs‬‬
‫)‪x = self.hidden(x‬‬
‫)‪return self.out(x‬‬

‫)(‪net = MLP‬‬
‫))‪X = tf.random.uniform((2, 20‬‬
‫‪41‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫)‪Y = net(X‬‬
‫بعد ذلك‪ ،‬نقوم بتخزين معلمات النموذج كملف باسم "‪"mlp.params‬‬

‫)'‪net.save_weights('mlp.params‬‬
‫الستعادة النموذج‪ ،‬نقوم بإنشاء نسخة طبق األصل من نموذج ‪ MLP‬األصلي‪ .‬بدالً من التهيئة‬
‫العشوائية لمعلمات النموذج‪ ،‬نقرأ المعلمات المخزنةيف الملف مباشرةً‪.‬‬

‫)(‪clone = MLP‬‬
‫)'‪clone.load_weights('mlp.params‬‬
‫‪<tensorflow.python.training.tracking.util.CheckpointLoad‬‬
‫>‪Status at 0x7fe7e6f9fdc0‬‬
‫نظرًا ألن كال المثالين لهما نفس معلمات النموذج‪ ،‬يجب أن تكون النتيجة الحسابية لنفس‬
‫اإلدخال ‪ X‬هي نفسها‪ .‬دعونا نتحقق من هذا‪.‬‬

‫)‪Y_clone = clone(X‬‬
‫‪Y_clone == Y‬‬
‫=‪<tf.Tensor: shape=(2, 10), dtype=bool, numpy‬‬
‫‪array([[ True, True, True, True, True, True,‬‬ ‫‪True,‬‬
‫‪True, True,‬‬
‫‪True],‬‬
‫‪[ True, True, True, True, True, True,‬‬ ‫‪True,‬‬
‫‪True, True,‬‬
‫>)]]‪True‬‬
‫‪6.6.3‬‬
‫يمكن استخدام دوال الحفظ ‪ save‬والتحميل ‪ load‬لتنفيذ إدخال ‪ /‬إخراج الملف‬ ‫•‬
‫‪ ile I/O‬لكائنات الموتر‪.‬‬
‫يمكننا حفظ وتحميل مجموعات كاملة من المعلمات لشبكة عبر قاموس المعلمات‬ ‫•‬
‫‪.parameter dictionary‬‬
‫يجب أن يتم حفظ البنيةيف الكود وليسيف المعلمات‪.‬‬ ‫•‬

‫‪6.6.4‬‬
‫‪ .1‬حتى لو لم تكن هناك حاجة لنشر نماذج مدربة على جهاز مختلف‪ ،‬فما هي الفوائد‬
‫العملية لتخزين معلمات النموذج؟‬
‫‪ .2‬افترض أننا نريد إعادة استخدام أجزاء فقط من الشبكة ليتم دمجهايف شبكة ذات بنية‬
‫مختلفة‪ .‬كيف يمكنك استخدام‪ ،‬لنقل أول طبقتين من شبكة سابقةيف شبكة جديدة؟‬
‫‪ .3‬كيف ستشرعيف حفظ بُنية الشبكة والمعلمات؟ ما هي القيود التي ستفرضها على‬
‫المعمارية؟‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪42‬‬

‫‪GPUs‬‬ ‫‪6.7‬‬
‫في القسم ‪ ،1.5‬ناقشنا النمو السريع للحسابات على مدى العقدين الماضيين‪ .‬باختصار‪ ،‬زاد أداء‬
‫وحدة معالجة الرسومات ‪ GPU‬بمعدل ‪ 1000‬عامل كل عقد منذ عام ‪ .2000‬وهذا يوفر فرصًا‬
‫رائعة ولكنه يشير أيضًا إلى الحاجة الملحة لتوفير مثل هذا األداء‪.‬‬

‫في هذا القسم‪ ،‬نبدأيف مناقشة كيفية تسخير هذا األداء الحسابي لبحثك‪ .‬أوالً باستخدام وحدات‬
‫معالجة رسومات واحدة وفي وقت الحق‪ ،‬كيفية استخدام وحدات معالجة رسومات متعددة‬
‫وخوادم متعددة (مع وحدات معالجة رسومات متعددة ‪.)multiple GPUs‬‬

‫على وجه التحديد‪ ،‬سنناقش كيفية استخدام وحدة معالجة رسومات ‪ NVIDIA‬واحدة إلجراء‬
‫العمليات الحسابية‪ .‬أوالً‪ ،‬تأكد من تثبيت ‪ NVIDIA GPU‬واحد على األقل‪ .‬بعد ذلك‪ ،‬قم‬
‫بتنزيل برنامج تعريف ‪ NVIDIA‬و‪ CUDA‬واتبع التعليمات لتعيين المسار المناسب‪ .‬بمجرد‬
‫اكتمال هذه االستعدادات‪ ،‬يمكن استخدام األمر ‪ nvidia-smi‬لعرض معلومات بطاقة‬
‫الرسومات‪.‬‬

‫‪!nvidia-smi‬‬
‫‪Mon Aug 29 23:47:02 2022‬‬
‫‪+-------------------------------------------------------‬‬
‫‪----------------------+‬‬
‫‪| NVIDIA-SMI 460.106.00‬‬ ‫‪Driver Version: 460.106.00‬‬
‫‪CUDA Version: 11.2‬‬ ‫|‬
‫‪|-------------------------------+----------------------‬‬
‫‪+----------------------+‬‬
‫‪| GPU Name‬‬ ‫‪Persistence-M| Bus-Id‬‬ ‫| ‪Disp.A‬‬
‫| ‪Volatile Uncorr. ECC‬‬
‫|‪| Fan Temp Perf Pwr:Usage/Cap‬‬ ‫| ‪Memory-Usage‬‬
‫| ‪GPU-Util Compute M.‬‬
‫|‬ ‫|‬ ‫|‬
‫| ‪MIG M.‬‬
‫‪|===============================+======================+‬‬
‫|======================‬
‫|‬ ‫| ‪0 Tesla V100-SXM2... Off | 00000000:00:1B.0 Off‬‬
‫| ‪0‬‬
‫‪| N/A‬‬ ‫‪48C‬‬ ‫‪P0‬‬ ‫| ‪52W / 300W‬‬ ‫| ‪1760MiB / 16160MiB‬‬
‫‪0%‬‬ ‫| ‪Default‬‬
‫|‬ ‫|‬ ‫|‬
‫| ‪N/A‬‬
‫‪+-------------------------------+----------------------‬‬
‫‪+----------------------+‬‬
‫‪43‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫|‬ ‫| ‪1 Tesla V100-SXM2... Off | 00000000:00:1C.0 Off‬‬


‫| ‪0‬‬
‫‪| N/A‬‬ ‫‪58C‬‬ ‫‪P0‬‬ ‫| ‪66W / 300W‬‬ ‫| ‪3MiB / 16160MiB‬‬
‫‪0%‬‬ ‫| ‪Default‬‬
‫|‬ ‫|‬ ‫|‬
‫| ‪N/A‬‬
‫‪+-------------------------------+----------------------‬‬
‫‪+----------------------+‬‬
‫|‬ ‫| ‪2 Tesla V100-SXM2... Off | 00000000:00:1D.0 Off‬‬
‫| ‪0‬‬
‫‪| N/A‬‬ ‫‪39C‬‬ ‫‪P0‬‬ ‫| ‪37W / 300W‬‬ ‫| ‪3MiB / 16160MiB‬‬
‫‪0%‬‬ ‫| ‪Default‬‬
‫|‬ ‫|‬ ‫|‬
‫| ‪N/A‬‬
‫‪+-------------------------------+----------------------‬‬
‫‪+----------------------+‬‬
‫|‬ ‫| ‪3 Tesla V100-SXM2... Off | 00000000:00:1E.0 Off‬‬
‫| ‪0‬‬
‫‪| N/A‬‬ ‫‪37C‬‬ ‫‪P0‬‬ ‫| ‪38W / 300W‬‬ ‫| ‪3MiB / 16160MiB‬‬
‫‪0%‬‬ ‫| ‪Default‬‬
‫|‬ ‫|‬ ‫|‬
‫| ‪N/A‬‬
‫‪+-------------------------------+----------------------‬‬
‫‪+----------------------+‬‬

‫‪+-------------------------------------------------------‬‬
‫‪----------------------+‬‬
‫‪| Processes:‬‬
‫|‬
‫‪| GPU‬‬ ‫‪GI‬‬ ‫‪CI‬‬ ‫‪PID‬‬ ‫‪Type‬‬ ‫‪Process name‬‬
‫| ‪GPU Memory‬‬
‫|‬ ‫‪ID‬‬ ‫‪ID‬‬
‫‪Usage‬‬ ‫|‬
‫=======================================================|‬
‫|======================‬
‫‪+-------------------------------------------------------‬‬
‫‪----------------------+‬‬
‫لتشغيل البرامج الموجودةيف هذا القسم‪ ،‬تحتاج إلى وحدتي ‪ GPU‬على األقل‪ .‬الحظ أن هذا قد‬
‫يكون باهظًا بالنسبة لمعظم أجهزة الكمبيوتر المكتبية ولكنه متاح بسهولةيف السحابة ‪ ،cloud‬على‬
‫سبيل المثال‪ ،‬باستخدام مثيالت ‪ AWS EC2‬متعددة وحدات معالجة الرسومات‪ .‬ال تتطلب‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 44

‫ بدالً من‬.multiple GPUs ‫جميع األقسام األخرى تقريبًا وحدات معالجة رسومات متعددة‬
.‫ هذا لتوضيح كيفية تدفق البيانات بين األجهزة المختلفة‬،‫ذلك‬

Computing Devices 6.7.1


‫ ووحدات معالجة الرسومات‬CPU ‫ مثل وحدات المعالجة المركزية‬،‫يمكننا تحديد األجهزة‬
‫ يتم إنشاء الموتراتيف‬،‫ بشكل افتراضي‬.calculation ‫ والحساب‬storage ‫ للتخزين‬،GPU
.‫الذاكرة الرئيسية ثم استخدام وحدة المعالجة المركزية لحسابها‬

import tensorflow as tf
from d2l import tensorflow as d2l

def cpu(): #@save


return tf.device('/CPU:0')

def gpu(i=0): #@save


return tf.device(f'/GPU:{i}')

cpu(), gpu(), gpu(1)


(<tensorflow.python.eager.context._EagerDeviceContext at
0x7f5138482040>,
<tensorflow.python.eager.context._EagerDeviceContext at
0x7f5138559b00>,
<tensorflow.python.eager.context._EagerDeviceContext at
0x7f5139bdd540>)
.‫يمكننا االستعالم عن عدد وحدات معالجة الرسومات المتاحة‬

def num_gpus(): #@save


return
len(tf.config.experimental.list_physical_devices('GPU'))

num_gpus()
2
‫ تسمحان لنا بتشغيل التعليمات البرمجية‬convenient functions ‫اآلن نحدد دالتي مالئمة‬
.‫حتى لو لم تكن وحدات معالجة الرسومات المطلوبة موجودة‬

def try_gpu(i=0): #@save


"""Return gpu(i) if exists, otherwise return
cpu()."""
if num_gpus() >= i + 1:
return gpu(i)
return cpu()
‫‪45‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫‪def try_all_gpus(): #@save‬‬


‫‪"""Return all available GPUs, or [cpu(),] if no GPU‬‬
‫"""‪exists.‬‬
‫]))(‪return [gpu(i) for i in range(num_gpus‬‬

‫)(‪try_gpu(), try_gpu(10), try_all_gpus‬‬


‫‪(<tensorflow.python.eager.context._EagerDeviceContext at‬‬
‫‪0x7f5138500240>,‬‬
‫‪<tensorflow.python.eager.context._EagerDeviceContext at‬‬
‫‪0x7f51381f92c0>,‬‬
‫‪[<tensorflow.python.eager.context._EagerDeviceContext‬‬
‫‪at 0x7f51381f9180>,‬‬
‫‪<tensorflow.python.eager.context._EagerDeviceContext‬‬
‫)]>‪at 0x7f51381f93c0‬‬
‫‪Tensors and GPUs‬‬ ‫‪6.7.2‬‬
‫بشكل افتراضي‪ ،‬يتم إنشاء الموترات على وحدة المعالجة المركزية ‪ .CPU‬يمكننا االستعالم عن‬
‫الجهاز الذي يوجد فيه الموتر‪.‬‬

‫)]‪x = tf.constant([1, 2, 3‬‬


‫‪x.device‬‬
‫'‪'/job:localhost/replica:0/task:0/device:GPU:0‬‬
‫من المهم مالحظة أنه كلما أردنا العمل بشروط متعددة‪ ،‬يجب أن يكونوا على نفس الجهاز‪ .‬على‬
‫سبيل المثال‪ ،‬إذا جمعنا اثنين من الموترات‪ ،‬فسنحتاج إلى التأكد من أن كال الوسيطتين تعيشان‬
‫على نفس الجهاز ‪ -‬وإال فلن يعرف إطار العمل مكان تخزين النتيجة أو حتى كيفية تحديد مكان‬
‫إجراء الحساب‪.‬‬

‫‪Storage on the GPU‬‬ ‫‪6.7.2.1‬‬


‫هناك عدة طرق لتخزين موتر على وحدة معالجة الرسومات ‪ .GPU‬على سبيل المثال‪ ،‬يمكننا‬
‫تحديد جهاز تخزين عند إنشاء موتر‪ .‬بعد ذلك‪ ،‬نقوم بإنشاء متغير موتر ‪X‬يف وحدة معالجة‬
‫الرسومات األولى‪ .‬يستهلك الموتر الذي تم إنشاؤه على وحدة معالجة الرسومات ذاكرة وحدة‬
‫معالجة الرسومات هذه فقط‪ .‬يمكننا استخدام األمر ‪ nvidia-smi‬لعرض استخدام ذاكرة‬
‫وحدة معالجة الرسومات‪ .‬بشكل عام‪ ،‬نحتاج إلى التأكد من عدم إنشاء بيانات تتجاوز حد ذاكرة‬
‫وحدة معالجة الرسومات‪.‬‬

‫‪with try_gpu():‬‬
‫))‪X = tf.ones((2, 3‬‬
‫‪X‬‬
‫=‪<tf.Tensor: shape=(2, 3), dtype=float32, numpy‬‬
‫‪array([[1., 1., 1.],‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪46‬‬

‫>)‪[1., 1., 1.]], dtype=float32‬‬


‫بافتراض أن لديك وحدتي ‪ GPU‬على األقل‪ ،‬فإن الكود التالي سينشئ موترًا عشوائيًا على وحدة‬
‫معالجة الرسومات الثانية‪.‬‬

‫‪with try_gpu(1):‬‬
‫))‪Y = tf.random.uniform((2, 3‬‬
‫‪Y‬‬
‫=‪<tf.Tensor: shape=(2, 3), dtype=float32, numpy‬‬
‫‪array([[0.87347054, 0.4167322 , 0.06983936],‬‬
‫‪[0.37522686, 0.3176515 , 0.2823031 ]],‬‬
‫>)‪dtype=float32‬‬
‫‪Copying‬‬ ‫‪6.7.2.2‬‬
‫إذا أردنا حساب ‪ ،X + Y‬فنحن بحاجة إلى تحديد مكان إجراء هذه العملية‪ .‬على سبيل المثال‪،‬‬
‫كما هو موضحيف الشكل ‪ ،6.7.1‬يمكننا نقل ‪ X‬إلى وحدة معالجة الرسومات الثانية وإجراء‬
‫العملية هناك‪ .‬ال تضف ‪ X‬و‪ Y‬ببساطة‪ ،‬ألن هذا سيؤدي إلى استثناء‪ .‬لن يعرف محرك وقت‬
‫التشغيل ما يجب فعله‪ :‬ال يمكنه العثور على البيانات على نفس الجهاز ويفشل‪ .‬نظرًا ألن ‪Y‬‬
‫تعيش على وحدة معالجة الرسومات الثانية‪ ،‬فنحن بحاجة إلى نقل ‪ X‬إلى هناك قبل أن نتمكن‬
‫من إضافة االثنين‪.‬‬

‫شكل ‪ 6.7.1‬انسخ البيانات إلجراء عملية على نفس الجهاز‪.‬‬

‫‪with try_gpu(1):‬‬
‫‪Z = X‬‬
‫)‪print(X‬‬
‫)‪print(Z‬‬
‫(‪tf.Tensor‬‬
‫]‪[[1. 1. 1.‬‬
‫)‪[1. 1. 1.]], shape=(2, 3), dtype=float32‬‬
‫(‪tf.Tensor‬‬
‫]‪[[1. 1. 1.‬‬
‫‪47‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫)‪[1. 1. 1.]], shape=(2, 3), dtype=float32‬‬


‫اآلن بعد أن أصبحت البيانات على نفس ‪( GPU‬كالهما ‪ Z‬و ‪ ،)Y‬يمكننا جمعها‪.‬‬

‫‪Y + Z‬‬
‫=‪<tf.Tensor: shape=(2, 3), dtype=float32, numpy‬‬
‫‪array([[1.8734705, 1.4167322, 1.0698394],‬‬
‫‪[1.3752269, 1.3176515, 1.2823031]],‬‬
‫>)‪dtype=float32‬‬
‫تخيل أن المتغير ‪ Z‬الخاص بك موجود بالفعليف وحدة معالجة الرسومات الثانية‪ .‬ماذا يحدث‬
‫إذا استمرينايف االتصال بـ ‪ Z2 = Z‬ضمن نطاق الجهاز نفسه؟ سيعود ‪ Z‬بدالً من عمل نسخة‬
‫وتخصيص ذاكرة جديدة‪.‬‬

‫‪with try_gpu(1):‬‬
‫‪Z2 = Z‬‬
‫‪Z2 is Z‬‬
‫‪True‬‬
‫‪Side Notes‬‬ ‫‪6.7.2.3‬‬
‫يستخدم الناس وحدات معالجة الرسومات للقيام بالتعلم اآللي ألنهم يتوقعون أن تكون سريعة‪.‬‬
‫لكن نقل المتغيرات بين األجهزة بطيء‪ .‬لذلك نريدك أن تكون متأكدًا بنسبة ‪ ٪100‬أنك تريد أن‬
‫تفعل شيئًا بطيئًا قبل أن نسمح لك بفعله‪ .‬إذا قام إطار عمل التعلم العميق بالنسخ تلقائيًا دون‬
‫تعطل‪ ،‬فقد ال تدرك أنك كتبت بعض التعليمات البرمجية البطيئة‪.‬‬

‫أيضًا‪ ،‬يعد نقل البيانات بين األجهزة (وحدة المعالجة المركزية ووحدات معالجة الرسومات‬
‫واألجهزة األخرى) شيئًا أبطأ بكثير من الحساب‪ .‬كما أنه يجعل الموازاة أكثر صعوبة‪ ،‬حيث يتعين‬
‫علينا انتظار إرسال البيانات (أو باألحرى استالمها) قبل أن نتمكن من متابعة المزيد من العمليات‪.‬‬
‫هذا هو السببيف ضرورة توخي الحذر الشديديف عمليات النسخ‪ .‬كقاعدة عامة‪ ،‬العديد من‬
‫العمليات الصغيرة أسوأ بكثير من عملية واحدة كبيرة‪ .‬عالوة على ذلك‪ ،‬فإن العديد من العمليات‬
‫في وقت واحد أفضل بكثير من العديد من العمليات الفردية التي تتخللها التعليمات البرمجية إال‬
‫إذا كنت تعرف ما تفعله‪ .‬هذا هو الحال ألن مثل هذه العمليات يمكن أن تمنع إذا كان على أحد‬
‫األجهزة انتظار اآلخر قبل أن يتمكن من القيام بشيء آخر‪ .‬إنه يشبه إلى حد ما طلب قهوتكيف ‬
‫قائمة انتظار بدالً من طلبها مسبقًا عبر الهاتف واكتشاف أنها جاهزة عندما تكون جاهزًا‪.‬‬

‫أخيرًا‪ ،‬عندما نطبع الموترات أو نحول الموترات إلى تنسيق ‪ ،NumPy‬إذا لم تكن البياناتيف ‬
‫الذاكرة الرئيسية‪ ،‬فسيقوم اإلطار بنسخها إلى الذاكرة الرئيسية أوالً‪ ،‬مما يؤدي إلى زيادة نقل‬
‫البيانات‪ .‬واألسوأ من ذلك‪ ،‬أنه يخضع اآلن لقفل المفسر العالمي ‪global interpreter‬‬
‫المخيف الذي يجعل كل شيء ينتظر بايثون حتى يكتمل‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪48‬‬

‫‪Neural Networks‬‬ ‫‪6.7.3‬‬


‫‪and GPUs‬‬
‫وبالمثل‪ ،‬يمكن لنموذج الشبكة العصبية تحديد األجهزة‪ .‬الكود التالي يضع معلمات النموذج على‬
‫‪.GPU‬‬

‫)(‪strategy = tf.distribute.MirroredStrategy‬‬
‫‪with strategy.scope():‬‬
‫[(‪net = tf.keras.models.Sequential‬‬
‫)])‪tf.keras.layers.Dense(1‬‬
‫‪INFO:tensorflow:Using MirroredStrategy with devices‬‬
‫‪('/job:localhost/replica:0/task:0/device:GPU:0',‬‬
‫)'‪'/job:localhost/replica:0/task:0/device:GPU:1‬‬
‫سنرى العديد من األمثلة حول كيفية تشغيل النماذج على وحدات معالجة الرسوماتيف الفصول‬
‫التالية‪ ،‬وذلك ألنها ستصبح إلى حد ما أكثر كثافة من الناحية الحسابية‪.‬‬

‫عندما يكون اإلدخال موترًا على وحدة معالجة الرسومات‪ ،‬فإن النموذج سيحسب النتيجة على‬
‫نفس وحدة معالجة الرسومات‪.‬‬

‫)‪net(X‬‬
‫=‪<tf.Tensor: shape=(2, 1), dtype=float32, numpy‬‬
‫‪array([[0.59118944],‬‬
‫>)‪[0.59118944]], dtype=float32‬‬
‫دعنا نؤكد أن معلمات النموذج مخزنة على نفس وحدة معالجة الرسومات‪.‬‬

‫‪net.layers[0].weights[0].device,‬‬
‫‪net.layers[0].weights[1].device‬‬
‫‪('/job:localhost/replica:0/task:0/device:GPU:0',‬‬
‫)'‪'/job:localhost/replica:0/task:0/device:GPU:0‬‬
‫دع المدرب ‪ trainer‬يدعم ‪.GPU‬‬

‫باختصار‪ ،‬طالما أن جميع البيانات والمعلمات موجودة على نفس الجهاز‪ ،‬يمكننا تعلم النماذج‬
‫بكفاءة‪ .‬سنرىيف الفصول التالية عدة أمثلة من هذا القبيل‪.‬‬

‫‪6.7.4‬‬
‫يمكننا تحديد أجهزة للتخزين والحساب‪ ،‬مثل وحدة المعالجة المركزية أو وحدة‬ ‫•‬
‫معالجة الرسومات‪ .‬بشكل افتراضي‪ ،‬يتم إنشاء البياناتيف الذاكرة الرئيسية ثم تستخدم‬
‫وحدة المعالجة المركزية إلجراء العمليات الحسابية‪.‬‬
‫يتطلب إطار عمل التعلم العميق أن تكون جميع بيانات اإلدخال للحساب على نفس‬ ‫•‬
‫الجهاز‪ ،‬سواء كانت وحدة المعالجة المركزية أو نفس وحدة معالجة الرسومات‪.‬‬
‫‪49‬‬ ‫الفصل السادس‪ :‬دليل البنائين ‪Builders’ Guide‬‬

‫يمكنك أن تفقد أداءً ملحوظًا عن طريق نقل البيانات دون عناية‪ .‬الخطأ المعتاد هو كما‬ ‫•‬
‫يلي‪ :‬حساب الخسارة (الخطأ) لكل دفعة صغيرة ‪ minibatch‬على وحدة معالجة‬
‫تسجيلهايف ‬ ‫(أو‬ ‫األوامر‬ ‫سطر‬ ‫على‬ ‫بها‬ ‫المستخدم‬ ‫وإبالغ‬ ‫الرسومات‬
‫‪ )NumPy ndarray‬سيؤدي إلى تشغيل قفل مترجم عام ‪global interpreter‬‬
‫‪ lock‬يوقف جميع وحدات معالجة الرسومات‪ .‬من األفضل بكثير تخصيص ذاكرة‬
‫للتسجيل داخل وحدة معالجة الرسومات ونقل السجالت الكبيرة فقط‪.‬‬

‫‪6.7.5‬‬
‫‪ .1‬جرب مهمة حسابية أكبر‪ ،‬مثل ضرب المصفوفات الكبيرة‪ ،‬والحظ الفرقيف السرعة‬
‫بين وحدة المعالجة المركزية ووحدة معالجة الرسومات‪ .‬ماذا عن مهمة بكمية صغيرة‬
‫من الحسابات؟‬
‫‪ .2‬كيف يجب أن نقرأ ونكتب معلمات النموذج على وحدة معالجة الرسومات؟‬
‫‪ .3‬قم بقياس الوقت المستغرق لحساب ‪ 1000‬مصفوفة من ضرب المصفوفات‬
‫‪ 100 × 100‬وتسجيل معيار ‪ Frobenius‬لمصفوفة اإلخراج نتيجة واحدةيف كل مرة‬
‫مقابل االحتفاظ بسجليف وحدة معالجة الرسومات ونقل النتيجة النهائية فقط‪.‬‬
‫‪ .4‬قم بقياس الوقت المستغرق إلجراء ضرب المصفوفة‪-‬المصفوفة على وحدتي ‪GPU‬‬
‫في نفس الوقت مقابل التسلسل على وحدة معالجة رسومات واحدة‪ .‬تلميح‪ :‬يجب أن‬
‫ترى تحجيمًا خطيًا ‪ linear scaling‬تقريبًا‪.‬‬
‫الشبكات العصبية‬
‫االلتفافية‬ ‫‪7‬‬
‫‪51‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪Convolutional Neural‬‬ ‫‪7‬‬


‫‪Networks‬‬
‫يتم تمثيل بيانات الصورة كشبكة ثنائية األبعاد من البكسل‪ ،‬سواء كانت أحادية اللون أو ملونة‪.‬‬
‫وفقًا لذلك‪ ،‬يتوافق كل بكسل مع قيمة عددية واحدة أو عدة قيم رقمية على التوالي‪ .‬حتى اآلن‬
‫تجاهلنا هذه ال ُبنية الغنية وعاملناها كمتجهات لألرقام من خالل تسطيح ‪ flattening‬الصور‪،‬‬
‫بغض النظر عن العالقة المكانية بين وحدات البكسل‪ .‬كان هذا النهج غير المرضي للغاية ضروريًا‬
‫لتغذية المتجهات أحادية البعد الناتجة من خالل ‪ MLP‬متصلة بالكامل‪.‬‬

‫نظرًا ألن هذه الشبكات ثابتةيف ترتيب الميزات‪ ،‬يمكننا الحصول على نتائج مماثلة بغض النظر‬
‫عما إذا كنا نحتفظ بترتيب يتوافق مع ال ُبنية المكانية للبكسل أو إذا قمنا بتغيير أعمدة مصفوفة‬
‫التصميم الخاصة بنا قبل مالءمة ‪ fitting‬معلمات ‪ .MLP‬على نحو مفضل‪ ،‬سنستفيد من معرفتنا‬
‫السابقة بأن وحدات البكسل القريبة ترتبط عادةً ببعضها البعض‪ ،‬لبناء نماذج فعالة للتعلم من‬
‫بيانات الصورة‪.‬‬

‫يقدم هذا الفصل الشبكات العصبية التالفيفية )‪ ،)1995 ،LeCun et al.( ،(CNN‬وهي عائلة‬
‫قوية من الشبكات العصبية المصممة لهذا الغرض تحديدًا‪ .‬أصبحت ال ُبنى القائمة على ‪CNN‬‬
‫موجودةيف كل مكان اآلنيف مجال الرؤية الحاسوبية‪ .‬على سبيل المثال‪،‬يف مجموعة ‪،Imagnet‬‬
‫(‪ ،)2009 ،.Deng et al‬كان استخدام الشبكات العصبية التالفيفية‪ ،‬باختصار ‪ Convnets‬هو‬
‫الذي وفر تحسينات كبيرةيف األداء (‪.)2012 ،Krizhevsky et al.‬‬

‫شبكات ‪ CNN‬الحديثة‪ ،‬كما يطلق عليها بالعامية‪ ،‬تدين بتصميمها إلى اإللهام من علم األحياء‬
‫‪ ،biology‬ونظرية المجموعة ‪ ،group theory‬وجرعة صحية من الترقيع التجريبي‬
‫‪ .experimental tinkering‬باإلضافة إلى كفاءة العينة ‪sample efficiency‬يف تحقيق نماذج‬
‫دقيقة ‪ ،achieving accurate models‬تميل شبكات ‪ CNN‬إلى أن تكون فعالة من الناحية‬
‫الحسابية‪ ،‬وذلك ألنها تتطلب معلمات أقل من ال ُبنى المتصلة تمامًا وألن االلتفافات‬
‫‪ convolutions‬سهلة الموازاة عبر نوى وحدة معالجة الرسومات (‪.)2014 ،Chetlur et al.‬‬
‫وبالتالي‪ ،‬غالبًا ما يطبق الممارسون شبكات ‪ CNN‬كلما أمكن ذلك‪ ،‬وقد برزوا بشكل متزايد‬
‫كمنافسين موثوق بهم حتىيف المهام ذات الهيكل التسلسلي أحادي البعد‪ ،‬مثل الصوت‬
‫(‪ ،)2014 ،Abdel-Hamid et al.‬النص (‪ ،)2014 ،Kalchbrenner et al.‬وتحليل‬
‫السالسل الزمنية ‪ ،)1995 ،LeCun et al.( time series analysis‬حيث يتم استخدام‬
‫الشبكات العصبية المتكررة (‪ recurrent neural networks )RNN‬بشكل تقليدي‪ .‬كما أن‬
‫بعض التعديالت الذكية لشبكات ‪ CNN‬قد جعلتها تؤثر على البيانات المهيكلة بالرسوم البيانية‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪52‬‬

‫‪ )2016 ،Kipf and Welling( graph-structured data‬وفي أنظمة التوصية‬


‫‪.recommender systems‬‬

‫أوالً‪ ،‬سوف نتعمق أكثريف دوافع الشبكات العصبية التالفيفية‪ .‬ويلي ذلك جولةيف العمليات‬
‫األساسية التي تشكل العمود الفقري لجميع الشبكات التالفيفية‪ .‬وتشمل هذه الطبقات التالفيفية‬
‫نفسها ‪ ،convolutional layers‬والتفاصيل الدقيقة بمايف ذلك الحشو ‪ padding‬والخطوة‬
‫‪ ،stride‬وطبقات التجميع ‪ pooling layers‬المستخدمة لتجميع المعلومات عبر المناطق‬
‫المكانية المجاورة‪ ،‬واستخدام قنوات متعددةيف كل طبقة‪ ،‬ومناقشة دقيقة لهيكل ال ُبنى الحديثة‪.‬‬
‫سنختتم الفصل بمثال عملي كامل لـ ‪ ،LeNet‬أول شبكة تالفيفية تم نشرها بنجاح‪ ،‬قبل وقت‬
‫طويل من ظهور التعلم العميق الحديث‪.‬يف الفصل التالي‪ ،‬سوف نتعمقيف التطبيقات الكاملة‬
‫لبعض أبنية ‪ CNN‬الشائعة والحديثة نسبيًا والتي تمثل تصميماتها معظم التقنيات المستخدمة‬
‫بشكل شائع من قبل الممارسين المعاصرين‪.‬‬

‫‪From Fully‬‬ ‫‪7.1‬‬


‫‪Connected Layers to Convolutions‬‬
‫حتى يومنا هذا‪ ،‬تظل النماذج التي ناقشناها حتى اآلن خيارات مناسبة عندما نتعامل مع البيانات‬
‫المجدولة ‪ .tabular data‬نعني بالجدول أن البيانات تتكون من صفوف تتوافق مع األمثلة‬
‫واألعمدة المقابلة للميزات‪ .‬باستخدام البيانات المجدولة‪ ،‬قد نتوقع أن األنماط التي نسعى إليها‬
‫قد تتضمن تفاعالت بين الميزات‪ ،‬لكننا ال نفترض أي بُنية مسبقًا تتعلق بكيفية تفاعل الميزات‪.‬‬

‫في بعض األحيان‪ ،‬نفتقر حقًا إلى المعرفة لتوجيه بناء ال ُبنى الحِرَفية‪.‬يف هذه الحاالت‪ ،‬قد يكون‬
‫‪ MLP‬هو أفضل ما يمكننا القيام به‪ .‬ومع ذلك‪ ،‬بالنسبة للبيانات اإلدراكية عالية األبعاد ‪high-‬‬
‫‪ ،dimensional perceptual data‬يمكن أن تنمو هذه الشبكات التي تفتقر إلى ال ُبنية بشكل‬
‫غير عملي‪.‬‬

‫على سبيل المثال‪ ،‬دعنا نعود إلى مثالنا الجاري للتمييز بين القطط والكالب‪ .‬لنفترض أننا نقوم‬
‫بعمل شامليف جمع البيانات‪ ،‬حيث نجمع مجموعة بيانات مشروحة من صور فوتوغرافية بدقة‬
‫واحدة ميغا بكسل‪ .‬هذا يعني أن كل مدخليف الشبكة له مليون بعد‪ .‬حتى التخفيض الشديد إلى‬
‫ألف بُعد مخفي سيتطلب طبقة متصلة بالكامل تتميز بالمعلمات ‪ .106 × 103 = 109‬ما لم‬
‫يكن لدينا الكثير من وحدات معالجة الرسومات ‪ ،GPU‬وموهبة التحسين الموزع‪ ،‬وقدر غير‬
‫عادي من الصبر‪ ،‬فقد يصبح تعلم معلمات هذه الشبكة غير ممكن‪.‬‬

‫قد يعترض القارئ الحريص على هذه الحجة على أساس أن دقة واحدة ميغا بكسل قد ال تكون‬
‫ضرورية‪ .‬ومع ذلك‪،‬يف حين أننا قد نكون قادرين على التخلص من مائة ألف بكسل‪ ،‬فإن الطبقة‬
‫‪53‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫المخفية التي يبلغ حجمها ‪ 1000‬بكسل تقلل بشكل كبير من عدد الوحدات المخفية التي يتطلبها‬
‫تعلم التمثيل الجيد للصور‪ ،‬لذلك سيظل النظام العملي يتطلب مليارات من المعلمات‪ .‬عالوة‬
‫على ذلك‪ ،‬قد يتطلب تعلم المصنف من خالل مالءمة العديد من المعلمات تجميع مجموعة‬
‫بيانات هائلة‪ .‬ومع ذلك‪ ،‬أصبح بإمكان كل من البشر وأجهزة الكمبيوتر اليوم التمييز بين القطط‬
‫والكالب جيدًا‪ ،‬األمر الذي يتعارض على ما يبدو مع هذه البديهيات‪ .‬وذلك ألن الصور تظهر بُنية‬
‫غنية يمكن أن يستغلها البشر ونماذج التعلم اآللي على حد سواء‪ .‬الشبكات العصبية التالفيفية‬
‫(‪ ) CNN‬هي إحدى الطرق اإلبداعية التي تبناها التعلم اآللي الستغالل بعض الهياكل المعروفة‬
‫في الصور الطبيعية‪.‬‬

‫قد يعترض القارئ الحريص على هذه الحجة على أساس أن دقة واحدة ميغا بكسل قد ال تكون‬
‫ضرورية‪ .‬ومع ذلك‪،‬يف حين أننا قد نكون قادرين على التخلص من مائة ألف بكسل‪ ،‬فإن الطبقة‬
‫المخفية التي يبلغ حجمها ‪ 1000‬بكسل تقلل بشكل كبير من عدد الوحدات المخفية التي يتطلبها‬
‫تعلم التمثيل الجيد للصور‪ ،‬لذلك سيظل النظام العملي يتطلب مليارات من المعلمات‪ .‬عالوة‬
‫على ذلك‪ ،‬قد يتطلب تعلم المصنف من خالل مالءمة العديد من المعلمات تجميع مجموعة‬
‫بيانات هائلة‪ .‬ومع ذلك‪ ،‬أصبح بإمكان كل من البشر وأجهزة الكمبيوتر اليوم التمييز بين القطط‬
‫والكالب جيدًا‪ ،‬األمر الذي يتعارض على ما يبدو مع هذه البديهيات‪ .‬وذلك ألن الصور تظهر بُنية‬
‫غنية يمكن أن يستغلها البشر ونماذج التعلم اآللي على حد سواء‪ .‬الشبكات العصبية التالفيفية‬
‫(‪ ) CNN‬هي إحدى الطرق اإلبداعية التي تبناها التعلم اآللي الستغالل بعض الهياكل المعروفة‬
‫في الصور الطبيعية‪.‬‬

‫‪Invariance‬‬ ‫‪7.1.1‬‬
‫تخيل أننا نريد اكتشاف كائنيف صورة ما‪ .‬يبدو من المعقول أنه أيا كانت الطريقة التي نستخدمها‬
‫للتعرف على األشياء ال ينبغي أن تهتم بشكل مفرط بالموقع الدقيق للكائنيف الصورة‪ .‬من الناحية‬
‫المثالية‪ ،‬يجب أن يستغل نظامنا هذه المعرفة‪ .‬وعادة ال تطير الخنازير وال تسبح الطائرات عادة‪.‬‬
‫ومع ذلك‪ ،‬ال يزال يتعين علينا التعرف على الخنزير الذي ظهريف أعلى الصورة‪ .‬يمكننا استلهام‬
‫بعض اإللهام هنا من لعبة األطفال "أين والدو ‪( "Where’s Waldo‬الموضحةيف الشكل ‪.)7.1.1‬‬
‫تتكون اللعبة من عدد من المشاهد الفوضوية المليئة باألنشطة‪ .‬يظهر والدويف مكان مايف كل منهما‪،‬‬
‫وعادة ما يتربصيف مكان غير متوقع‪ .‬هدف القارئ هو تحديد مكانه‪ .‬على الرغم من مظهره‬
‫المميز‪ ،‬قد يكون هذا صعبًا بشكل كبير‪ ،‬بسبب العدد الكبير من المشتتات‪ .‬ومع ذلك‪ ،‬ال يعتمد‬
‫شكل والدو على مكان وجود والدو‪ .‬يمكننا مسح الصورة باستخدام كاشف والدو ‪Waldo‬‬
‫‪ detector‬الذي يمكنه تعيين درجة لكل رقعة ‪ ،patch‬مما يشير إلى احتمالية احتواء التصحيح‬
‫على والدو‪.‬يف الواقع‪ ،‬تعتمد العديد من خوارزميات اكتشاف الكائنات وتجزئتها على هذا النهج‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪54‬‬

‫(‪ .)2015 ،Long et al.‬تنظم شبكات ‪ CNN‬فكرة الثبات المكاني ‪spatial invariance‬‬
‫هذه‪ ،‬وتستغلها لتعلم تمثيالت ‪ representations‬مفيدة بمعلمات أقل‪.‬‬

‫الشكل ‪ 7.1.1‬صورة للعبة "‪."Where’s Waldo‬‬

‫يمكننا اآلن جعل هذه البديهيات أكثر واقعية من خالل تعداد بعض الرغبات لتوجيه تصميمنا‬
‫لبُنية شبكة عصبية مناسبة للرؤية الحاسوبية ‪:computer vision‬‬

‫‪ .1‬في الطبقات األولى‪ ،‬يجب أن تستجيب شبكتنا بشكل مشابه لنفس الرقعة ‪ ،‬بغض النظر‬
‫عن مكان ظهوره في الصورة‪ .‬يسمى هذا المبدأ بثبات الترجمة ‪translation‬‬
‫‪( invariance‬أو تساوي الترجمة ‪.)translation equivariance‬‬
‫‪ .2‬يجب أن تركز الطبقات األولى للشبكة على المناطق المحلية ‪ ،local regions‬دون‬
‫اعتبار لمحتويات الصورة في المناطق البعيدة‪ .‬هذا هو مبدأ المكان‪ .‬في النهاية ‪ ،‬يمكن‬
‫تجميع هذه التمثيالت المحلية ‪ local representations‬لعمل تنبؤات على مستوى‬
‫الصورة بأكملها‪.‬‬
‫‪ .3‬أثناء تقدمنا‪ ،‬يجب أن تكون الطبقات األعمق قادرة على التقاط ميزات أطول مدى‬
‫‪longer-range features‬للصورة ‪ ،‬بطريقة مشابهة للرؤية ذات المستوى األعلى في‬
‫الطبيعة‪.‬‬

‫دعونا نرى كيف يترجم هذا إلى رياضيات‪.‬‬


‫‪55‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪Constraining the MLP MLP‬‬ ‫‪7.1.2‬‬


‫للبدء‪ ،‬يمكننا اعتبار ‪ MLP‬مع صور ثنائية األبعاد 𝐗 كمدخالت وتمثيالتها المخفية الفورية 𝐇‬
‫ممثلة بشكل مشابه كمصفوفات (هما موترات ثنائية األبعاديف الكود)‪ ،‬حيث 𝐗 و 𝐇 لهما نفس‬
‫الشكل‪ .‬نحن اآلن نتصور ليس فقط المدخالت ولكن أيضًا التمثيالت الخفية على أنها تمتلك‬
‫بنية مكانية ‪.spatial structure‬‬

‫ليكن 𝑗‪ [𝐗]𝑖,‬و 𝑗‪ [𝐇]𝑖,‬يدالن على البكسليف الموقع )𝑗 ‪ (𝑖,‬يف صورة اإلدخال ‪input image‬‬
‫والتمثيل المخفي ‪ ،hidden representation‬على التوالي‪ .‬وبالتالي‪ ،‬لكي تتلقى كل وحدة من‬
‫الوحدات المخفية مدخالت من كل بكسل من وحدات البكسل المدخلة‪ ،‬سننتقل من استخدام‬
‫مصفوفات الوزن ‪( weight matrices‬كما فعلنا سابقًايف ‪ )MLPs‬لتمثيل معلماتنا كموترات‬
‫للوزن من الدرجة الرابعة 𝖶‪ .‬لنفترض أن 𝐔 يحتوي على تحيزات‪ ،‬فيمكننا التعبير رسميًا عن‬
‫الطبقة المتصلة بالكامل كـ‬

‫𝑗‪[𝐇]𝑖,‬‬ ‫∑ ‪= [𝐔]𝑖,𝑗 +‬‬ ‫∑‬ ‫𝑙‪[𝖶]𝑖,𝑗,𝑘,𝑙 [𝐗]𝑘,‬‬


‫𝑘‬ ‫𝑙‬

‫∑ ‪= [𝐔]𝑖,𝑗 +‬‬ ‫∑‬ ‫‪[𝖵]𝑖,𝑗,𝑎,𝑏 [𝐗]𝑖+𝑎,𝑗+𝑏 .‬‬


‫𝑎‬ ‫𝑏‬

‫يعتبر التبديل من 𝖶 إلى 𝖵 تجميليًا تمامًايف الوقت الحالي نظرًا لوجود تطابق واحد إلى واحد بين‬
‫المعامالتيف كال الموترات من الدرجة الرابعة‪ .‬نحن ببساطة نعيد فهرسة الرموز المنخفضة )𝑙 ‪(𝑘,‬‬
‫مثل ذلك 𝑎 ‪ 𝑘 = 𝑖 +‬و 𝑏 ‪ .𝑙 = 𝑗 +‬بعبارة أخرى‪ ،‬وضعنا 𝑏‪.[𝖵]𝑖,𝑗,𝑎,𝑏 = [𝖶]𝑖,𝑗,𝑖+𝑎,𝑗+‬‬
‫المؤشرات 𝑎 و𝑏 تتخطى كل من اإلزاحات ‪ offsets‬اإليجابية والسلبية‪ ،‬وتغطي الصورة بأكملها‪.‬‬
‫بالنسبة إلى أي موقع (𝑗 ‪)𝑖 ،‬يف التمثيل المخفي 𝑗‪ ، [𝐇]𝑖,‬نحسب قيمته عن طريق جمع أكثر من‬
‫بكسليف 𝑥 ‪ ،‬وتوسيطها )𝑗 ‪ ، (𝑖,‬واخذ االوزان لها بواسطة 𝑏‪ .[𝖵]𝑖,𝑗,𝑎,‬قبل أن نواصل العمل‪ ،‬دعنا‬
‫نفكريف العدد اإلجمالي للمعلمات المطلوبة لطبقة واحدة ‪single layer‬يف هذه المعلمات‪ :‬يتم‬
‫تعيين صورة ‪ 1( 1000 × 1000‬ميغا بكسل) إلى تمثيل مخفي ‪ .1000 × 1000‬يتطلب هذا‬
‫معلمات ‪ ، 1012‬تتجاوز بكثير ما يمكن ألجهزة الكمبيوتر التعامل معه حاليًا‪.‬‬

‫‪Translation Invariance‬‬ ‫‪7.1.2.1‬‬


‫اآلن دعونا نستدعي المبدأ األول الذي تم وضعه أعاله‪ :‬ثبات الترجمة (‪،Zhang and others‬‬
‫‪ .)1988‬هذا يعني أن التحوليف المدخالت 𝐗 يجب أن يؤدي ببساطة إلى تحوليف التمثيل الخفي‬
‫𝐇‪ .‬هذا ممكن فقط إذا 𝖵 و 𝐔 ال تعتمدان على )𝑗 ‪ (𝑖,‬بالفعل‪ .‬على هذا النحو‪ ،‬لدينا = 𝑏‪[𝖵]𝑖,𝑗,𝑎,‬‬
‫𝑏‪ [𝐕]𝑎,‬و𝐔 هو ثابت‪ ،‬على سبيل المثال 𝑢‪ .‬نتيجة لذلك‪ ،‬يمكننا تبسيط تعريف 𝐇‪:‬‬

‫𝑎∑ ‪[𝐇]𝑖,𝑗 = 𝑢 +‬‬ ‫𝑏∑‬ ‫‪[𝐕]𝑎,𝑏 [𝐗]𝑖+𝑎,𝑗+𝑏 .‬‬ ‫(‪)7.1.2‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪56‬‬

‫هذا هو االلتواء ‪ !convolution‬نحن نأخذ االوزان بشكل فعال وحدات البكسليف ‪(𝑖 + 𝑎, 𝑗 +‬‬
‫)𝑏 بالقرب من الموقع )𝑗 ‪ (𝑖,‬باستخدام المعامالت 𝑏‪ [𝐕]𝑎,‬للحصول على القيمة 𝑗‪ .[𝐇]𝑖,‬الحظ‬
‫أن 𝑏‪[𝐕]𝑎,‬يحتاج إلى عدد أقل من المعامالت من 𝑏‪ [𝖵]𝑖,𝑗,𝑎,‬ألنه لم يعد يعتمد على الموقع داخل‬
‫الصورة‪ .‬وبالتالي‪ ،‬لم يعد عدد المعلمات المطلوبة ‪1012‬ولكن أكثر معقولية هو ‪ :1012‬ال يزال‬
‫لدينا االعتماد على )‪ .𝑎, 𝑏 ∈ (−1000,1000‬باختصار‪ ،‬لقد أحرزنا تقدمًا كبيرًا‪ .‬الشبكات‬
‫العصبية ذات التأخير الزمني )‪ Time-delay neural networks (TDNNs‬هي بعض‬
‫األمثلة األولى الستغالل هذه الفكرة (‪.)1989 ،Waibel et al.‬‬

‫‪Locality‬‬ ‫‪7.1.2.2‬‬

‫اآلن دعونا نستدعي المبدأ الثاني‪ :‬المحلية ‪ .Locality‬كما تم تحفيزنا أعاله‪ ،‬نعتقد أنه ال ينبغي‬
‫علينا أن ننظر بعيدًا جدًا عن الموقع )𝑗 ‪ (𝑖,‬من أجل جمع المعلومات ذات الصلة لتقييم ما يجري‬
‫في 𝑗‪ .[𝐇]𝑖,‬هذا يعني أنه خارج نطاق ما ‪ ، |𝑎| > Δ‬أو ‪ |𝑏| > Δ‬يجب علينا ضبط = 𝑏‪[𝐕]𝑎,‬‬
‫‪ .0‬بالتساوي‪ ،‬يمكننا إعادة كتابة 𝑗‪ [𝐇]𝑖,‬كـ‬

‫‪[𝐇]𝑖,𝑗 = 𝑢 + ∑Δ𝑎=−Δ‬‬ ‫‪∑Δ𝑏=−Δ‬‬ ‫‪[𝐕]𝑎,𝑏 [𝐗]𝑖+𝑎,𝑗+𝑏 .‬‬ ‫(‪)7.1.3‬‬

‫يؤدي هذا إلى تقليل عدد المعلمات من ‪ 4 ⋅ 106‬إلى ‪ ، 4Δ2‬حيث يكون عادةً أصغر من ‪.10‬‬
‫على هذا النحو‪ ،‬قمنا بتقليل عدد المعلمات بمقدار ‪ 4‬أوامر أخرى من حيث الحجم‪ .‬الحظ أن‬
‫(‪ ،)7.1.3‬باختصار‪ ،‬هي ما يسمى بالطبقة التالفيفية ‪ .convolutional layer‬الشبكات‬
‫العصبية التالفيفية (‪ ) CNN‬هي عائلة خاصة من الشبكات العصبية التي تحتوي على طبقات‬
‫تالفيفية‪.‬يف مجتمع أبحاث التعلم العميق‪ 𝐕،‬يُشار إلى نواة االلتفاف ‪,convolution kernel‬‬
‫أو عامل التصفية ‪ ،filter‬أو ببساطة أوزان الطبقة ‪ layer’s weights‬التي تُعد معلمات قابلة‬
‫للتعلم‪.‬‬

‫بينمايف السابق‪ ،‬ربما كنا قد طلبنا باليين من المعلمات لتمثيل طبقة واحدة فقطيف شبكة معالجة‬
‫الصور‪ ،‬فنحن نحتاج اآلن عادةً إلى بضع مئات فقط‪ ،‬دون تغيير أبعاد المدخالت أو التمثيالت‬
‫المخفية‪ .‬الثمن المدفوع لهذا التخفيض الكبيريف المعلمات هو أن ميزاتنا أصبحت اآلن ترجمة‬
‫ثابتة ‪ translation invariant‬وأن طبقتنا يمكنها فقط دمج المعلومات المحلية‪ ،‬عند تحديد‬
‫قيمة كل تنشيط مخفي‪ .‬كل التعلم يعتمد على فرض التحيز االستقرائي ‪ .inductive bias‬عندما‬
‫يتفق هذا التحيز مع الواقع‪ ،‬نحصل على نماذج ذات كفاءةيف العينة تُعمم جيدًا على البيانات غير‬
‫المرئية‪ .‬لكن بالطبع‪ ،‬إذا كانت هذه التحيزات ال تتفق مع الواقع‪ ،‬على سبيل المثال‪ ،‬إذا تبين أن‬
‫الصور ليست ثابتةيف الترجمة‪ ،‬فقد تكافح نماذجنا حتى لتالئم بيانات التدريب الخاصة بنا‪.‬‬
‫‪57‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫يقودنا هذا االنخفاض الدراماتيكي ‪dramatic reduction‬يف المعلمات إلى آخر رغباتنا‪ ،‬أي أن‬
‫الطبقات العميقة يجب أن تمثل جوانب أكبر وأكثر تعقيدًا للصورة‪ .‬يمكن تحقيق ذلك عن طريق‬
‫ادخال ‪ interleaving‬الطبقات الالخطية والطبقات التالفيفية بشكل متكرر‪.‬‬

‫‪Convolutions‬‬ ‫‪7.1.3‬‬

‫دعونا نراجع بإيجاز سبب تسمية (‪ )7.1.3‬بااللتفاف ‪.convolution‬يف الرياضيات‪ ،‬يتم تعريف‬
‫االلتفاف بين دالتين (‪ ،)1973 ،Rudin‬على سبيل المثال ‪ 𝑓, 𝑔: ℝ𝑑 → ℝ‬كاالتي‪:‬‬

‫‪(𝑓 ∗ 𝑔)(𝐱) = ∫ 𝑓(𝐳)𝑔(𝐱 − 𝐳)𝑑𝐳.‬‬ ‫(‪)7.1.4‬‬

‫وهذا يعني أننا نقيس التداخل ‪ overlap‬بين 𝑓 و𝑔 متى يتم "قلب ‪ "flipped‬إحدى الدوال‬
‫وإزاحتها "‪ " shifted‬بواسطة 𝐱‪ .‬عندما يكون لدينا كائنات منفصلة ‪ ،discrete objects‬يتحول‬
‫التكامل إلى مجموع‪ .‬على سبيل المثال‪ ،‬بالنسبة إلى المتجهات من مجموعة متجهات األبعاد‬
‫الالنهائية التي يمكن جمعها مربعة مع مؤشر يعمل فوق ‪ ،ℤ‬نحصل على التعريف التالي‪:‬‬

‫‪(𝑓 ∗ 𝑔)(𝑖) = ∑𝑎 𝑓(𝑎)𝑔(𝑖 − 𝑎).‬‬ ‫(‪)7.1.5‬‬

‫بالنسبة إلى الموترات ثنائية األبعاد‪ ،‬لدينا مجموع مقابل مع مؤشرات )𝑏 ‪ (𝑎,‬لـ 𝑓 و‪(𝑖 − 𝑎, 𝑗 −‬‬
‫)𝑏 لـ 𝑔‪ ،‬على التوالي‪:‬‬

‫‪(𝑓 ∗ 𝑔)(𝑖, 𝑗) = ∑ ∑𝑏 𝑓(𝑎, 𝑏)𝑔(𝑖 − 𝑎, 𝑗 − 𝑏).‬‬ ‫(‪)7.1.6‬‬


‫𝑎‬

‫يبدو هذا مشابهًا لـ (‪ ،)7.1.3‬مع اختالف رئيسي واحد‪ .‬بدالً من استخدام )𝑏 ‪،(𝑖 + 𝑎, 𝑗 +‬‬
‫نستخدم االختالف ‪ difference‬بدالً من ذلك‪ .‬الحظ‪ ،‬مع ذلك‪ ،‬أن هذا التمييز ‪distinction‬‬
‫هويف الغالب تجميلي حيث يمكننا دائمًا مطابقة التدوين بين (‪ )7.1.3‬و (‪ .)7.1.6‬يصف تعريفنا‬
‫األصلييف (‪ )7.1.3‬بشكل أكثر مالءمة االرتباط المتبادل ‪ .cross-correlation‬سنعود إلى هذا‬
‫في القسم التالي‪.‬‬

‫‪Channels‬‬ ‫‪7.1.4‬‬

‫بالعودة إلى كاشف والدو ‪ ،Waldo detector‬دعونا نرى كيف يبدو هذا‪ .‬تلتقط الطبقة التالفيفية‬
‫نوافذ ذات حجم معين وتزن شدة وفقًا للفلتر 𝖵 ‪ ،‬كما هو موضحيف الشكل ‪ .7.1.2‬قد نهدف إلى‬
‫تعلم نموذج بحيث حيثما تكون "‪ "waldoness‬هي األعلى‪ ،‬يجب أن نجد ذروةيف تمثيالت‬
‫الطبقة المخفية‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪58‬‬

‫الشكل ‪ 7.1.2‬كشف والدو‪.‬‬

‫هناك مشكلة واحدة فقطيف هذا النهج‪ .‬حتى اآلن‪ ،‬تجاهلنا بسعادة أن الصور تتكون من ‪ 3‬قنوات‪:‬‬
‫األحمر واألخضر واألزرق‪ .‬باختصار‪ ،‬الصور ليست كائنات ثنائية األبعاد بل هي موترات من‬
‫الدرجة الثالثة‪ ،‬تتميز باالرتفاع والعرض والقناة‪ ،‬على سبيل المثال‪ ،‬مع شكل × ‪1024 × 1024‬‬
‫‪ 3‬بكسل‪.‬يف حين أن أول محورين يتعلقان بالعالقات المكانية ‪ ،spatial relationships‬يمكن‬
‫اعتبار الثالث على أنه تعيين تمثيل متعدد األبعاد لكل موقع بكسل‪ .‬وبالتالي نقوم بفهرسة 𝖷 كـ‬
‫𝑘‪ .[𝖷]𝑖,𝑗,‬يجب أن يتكيف الفلتر التالفيفي ‪ convolutional filter‬وفقًا لذلك‪ .‬بدال من‬
‫𝑏‪ ،[𝐕]𝑎,‬لدينا اآلن 𝑐‪.[𝖵]𝑎,𝑏,‬‬

‫عالوة على ذلك‪ ،‬كما أن مدخالتنا تتكون من موتر من الدرجة الثالثة‪ ،‬فقد تبين أنها فكرة جيدة‬
‫لصياغة تمثيالتنا المخفية بالمثل كموترات من الدرجة الثالثة 𝖧‪ .‬بعبارة أخرى‪ ،‬بدالً من مجرد‬
‫وجود تمثيل مخفي واحد يتوافق مع كل موقع مكاني‪ ،‬نريد متجهًا كامالً للتمثيالت المخفية‬
‫المقابلة لكل موقع مكاني‪ .‬يمكننا التفكيريف التمثيالت المخفية على أنها تتألف من عدد من‬
‫الشبكات ثنائية األبعاد المكدسة فوق بعضها البعض‪ .‬كما هو الحاليف المدخالت‪ ،‬تسمى هذه‬
‫أحيانًا القنوات ‪ .channels‬يطلق عليها أيضًا أحيانًا خرائط المعالم ‪ ،feature maps‬حيث يوفر‬
‫كل منها مجموعة مكانية من المعالم المكتسبة للطبقة التالية‪ .‬بشكل بديهي‪ ،‬قد تتخيل أنهيف ‬
‫الطبقات السفلية األقرب إلى المدخالت‪ ،‬يمكن أن تصبح بعض القنوات متخصصة للتعرف على‬
‫الحواف ‪ edges‬بينما يمكن لآلخرين التعرف على األنسجة ‪.textures‬‬

‫لدعم قنوات متعددةيف كل من المدخالت (𝖷) والتمثيالت المخفية (𝖧)‪ ،‬يمكننا إضافة إحداثي‬
‫رابع إلى 𝖵‪ .[𝖵]𝑎,𝑏,𝑐,𝑑 :‬نجمع كل شيء معًا لدينا‪:‬‬
‫‪59‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪[𝖧]𝑖,𝑗,𝑑 = ∑Δ𝑎=−Δ‬‬ ‫‪∑Δ𝑏=−Δ‬‬ ‫𝑐∑‬ ‫‪[𝖵]𝑎,𝑏,𝑐,𝑑 [𝖷]𝑖+𝑎,𝑗+𝑏,𝑐 ,‬‬ ‫(‪)7.1.6‬‬

‫حيث 𝑑 فهرسة قنوات اإلخراجيف التمثيالت المخفية 𝖧‪ .‬ستستمر الطبقة التالفيفية الالحقةيف ‬
‫أخذ موتر من الدرجة الثالثة 𝖧‪ ،‬كمدخل‪ .‬لكونها أكثر عمومية‪ )7.1.7( ،‬هو تعريف الطبقة‬
‫التالفيفية لقنوات متعددة‪ ،‬حيث تكون النواة ‪ kernel‬أو فلتر الطبقة‪.‬‬

‫ال يزال هناك العديد من العمليات التي نحتاج إلى معالجتها‪ .‬على سبيل المثال‪ ،‬نحتاج إلى معرفة‬
‫كيفية دمج جميع التمثيالت المخفيةيف ناتج واحد‪ ،‬على سبيل المثال‪ ،‬ما إذا كان هناك والدو‬
‫‪ Waldo‬يف أي مكانيف الصورة‪ .‬نحتاج أيضًا إلى تحديد كيفية حساب األشياء بكفاءة‪ ،‬وكيفية‬
‫الجمع بين طبقات متعددة‪ ،‬ودوال التنشيط المناسبة‪ ،‬وكيفية اتخاذ خيارات تصميم معقولة‬
‫إلنتاج شبكات فعالةيف الممارسة‪ .‬ننتقل إلى هذه القضايايف بقية الفصل‪.‬‬

‫‪7.1.5‬‬

‫في هذا القسم اشتقنا بُ نية الشبكات العصبية التالفيفية من المبادئ األولى‪.‬يف حين أنه من غير‬
‫الواضح ما إذا كان هذا هو ما أدى إلى اختراع شبكات ‪ ،CNN‬فمن المرضي معرفة أنها الخيار‬
‫الصحيح عند تطبيق مبادئ معقولة لكيفية عمل معالجة الصور وخوارزميات الرؤية الحاسوبية‪،‬‬
‫على األقل عند المستويات األدنى‪ .‬على وجه الخصوص‪ ،‬يشير ثبات الترجمة ‪translation‬‬
‫‪invariance‬يف الصور إلى أنه سيتم التعامل مع جميع بقع الصورة بنفس الطريقة‪ .‬تعني المنطقة‬
‫المحلية ‪ Locality‬أنه سيتم استخدام جوار صغير فقط من وحدات البكسل لحساب التمثيالت‬
‫المخفية المقابلة‪ .‬بعض اإلشارات المبكرة لشبكات ‪ CNN‬هييف شكل ‪Neocognitron‬‬
‫(‪.)1982 ،Fukushima‬‬

‫المبدأ الثاني الذي واجهناهيف تفكيرنا هو كيفية تقليل عدد المعلماتيف فئة دالة دون الحد من‬
‫قوتها التعبيرية‪ ،‬على األقل‪ ،‬عندما تصمد افتراضات معينةيف النموذج‪ .‬لقد رأينا انخفاضًا كبيرًايف ‬
‫التعقيد نتيجة لهذا التقييد‪ ،‬وتحويل المشكالت غير القابلة للتنفيذ من الناحية الحسابية‬
‫واإلحصائية إلى نماذج يمكن تتبعها‪.‬‬

‫سمحت لنا إضافة القنوات ‪ channels‬بإعادة بعض التعقيد الذي فقد بسبب القيود المفروضة‬
‫على النواة التالفيفية ‪ convolutional kernel‬من خالل المحلية وثبات الترجمة‪ .‬الحظ أن‬
‫القنوات هي إضافة طبيعية إلى حد ما تتجاوز األحمر واألخضر واألزرق‪ .‬العديد من صور األقمار‬
‫الصناعية‪ ،‬خاصة للزراعة واألرصاد الجوية‪ ،‬لديها عشرات إلى مئات القنوات‪ ،‬وتولد صورًا فائقة‬
‫الطيف بدالً من ذلك‪ .‬يقدمون بيانات حول العديد من األطوال الموجية المختلفة‪ .‬فيما يلي سوف‬
‫نرى كيفية استخدام التالفيف بشكل فعال لمعالجة أبعاد الصور التي تعمل عليها‪ ،‬وكيفية االنتقال‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪60‬‬

‫من التمثيل القائم على الموقع ‪ location-based‬إلى التمثيل القائم على القناة ‪channel-‬‬
‫‪ based‬وكيفية التعامل مع عدد كبير من الفئات بكفاءة‪.‬‬

‫‪7.1.6‬‬

‫‪ .1‬افترض أن حجم نواة االلتفاف ‪ convolution kernel‬هو ‪ .Δ = 0‬أظهر أنه في هذه‬


‫الحالة ‪ ،‬تنفذ نواة االلتفاف ‪ MLP‬بشكل مستقل لكل مجموعة من القنوات‪ .‬هذا يؤدي‬
‫إلى الشبكة في معماريات الشبكة (لين وآخرون ‪.)2013 ،‬‬
‫‪ .2‬غالبًا ما يتم تمثيل البيانات الصوتية على أنها تسلسل أحادي البعد ‪one-‬‬
‫‪.dimensional sequence‬‬
‫‪ .1‬متى قد ترغب في فرض المحلية وثبات الترجمة ‪translation /locality‬‬
‫‪ invariance‬على الصوت؟‬
‫‪ .2‬اشتق عمليات االلتفاف للصوت‪.‬‬
‫‪ .3‬هل يمكنك معالجة الصوت باستخدام نفس أدوات الرؤية الحاسوبية؟ تلميح‪:‬‬
‫استخدم المخطط الطيفي ‪.spectrogram‬‬
‫‪ .3‬لماذا قد ال يكون ثبات الترجمة فكرة جيدة بعد كل شيء؟ اعط مثاال‪.‬‬
‫‪ .4‬هل تعتقد أن الطبقات التالفيفية قد تكون قابلة للتطبيق أيضًا على البيانات النصية؟ ما‬
‫هي المشاكل التي قد تواجهها مع اللغة؟‬
‫‪ .5‬ماذا يحدث مع التالفيف عندما يكون الكائن في حدود الصورة‪.‬‬
‫‪ .6‬إثبت أن االلتفاف متماثل ‪ ،symmetric‬أي 𝑓 ∗ 𝑔 = 𝑔 ∗ 𝑓‪.‬‬
‫‪𝑓∗𝑔=ℱ‬‬ ‫‪−1‬‬
‫‪ .7‬إثبت نظرية االلتفاف ‪ ،convolution theorem‬أي ⋅ ]𝑓[‪[ℱ‬‬
‫]]𝑔[‪ .ℱ‬هل يمكنك استخدامه لتسريع التالفيف؟‬

‫‪Convolutions for Images‬‬ ‫‪7.2‬‬


‫اآلن بعد أن فهمنا كيفية عمل الطبقات التالفيفية ‪ convolutional layers‬من الناحية النظرية‪،‬‬
‫نحن مستعدون لنرى كيف تعمليف الممارسة العملية‪ .‬بناءً على دافعنا للشبكات العصبية التالفيفية‬
‫‪CNN‬باعتبارها بنيات فعالة الستكشاف ال ُبنيةيف بيانات الصورة‪ ،‬فإننا نتمسك بالصور كمثال‬
‫قيد التشغيل‪.‬‬

‫‪The Cross-Correlation Operation‬‬ ‫‪7.2.1‬‬

‫تذكر أن الطبقات التالفيفية ‪ convolutional layers‬هي تسمية خاطئة بالمعنى الدقيق للكلمة‪،‬‬
‫ألن العمليات التي تعبر عنها توصف بدقة أكبر على أنها ارتباطات متبادلة ‪.cross-correlations‬‬
‫بناءً على أوصافنا للطبقات التالفيفيةيف القسم ‪،7.1‬يف مثل هذه الطبقة‪ ،‬يتم دمج موتر اإلدخال‬
‫‪61‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪ input tensor‬وموتّر النواة ‪ kernel tensor‬إلنتاج موتر ناتج ‪ output tensor‬من خالل‬
‫عملية االرتباط المتبادل ‪.cross-correlation‬‬

‫دعنا نتجاهل القنوات ‪ channels‬يف الوقت الحالي ونرى كيف يعمل ذلك مع البيانات ثنائية‬
‫األبعاد والتمثيالت المخفية‪.‬يف الشكل ‪ ،7.2.1‬المدخالت عبارة عن موتر ثنائي األبعاد بارتفاع‬
‫‪ 3‬وعرض ‪ .3‬ونضع عالمة على شكل موتر كالتالي ‪ 3 × 3‬أو (‪ .)3،3‬ارتفاع وعرض النواة‬
‫كالهما ‪ .2‬شكل نافذة النواة ‪( kernel window‬أو نافذة االلتفاف ‪convolution‬‬
‫‪ )window‬يُعطى بارتفاع وعرض النواة (هنا ‪.)2 × 2‬‬

‫الشكل ‪ 7.2.1‬عملية االرتباط المتبادل ثنائية األبعاد ‪Two-dimensional cross-‬‬


‫‪ .correlation operation‬األجزاء المظللة هي أول عنصر إخراج باإلضافة إلى عناصر موتر‬
‫اإلدخال والنواة المستخدمة لحساب اإلخراج‪. 0 × 0 + 1 × 1 + 3 × 2 + 4 × 3 = 19:‬‬

‫في عملية االرتباط المتبادل ثنائية األبعاد‪ ،‬نبدأ مع نافذة االلتفاف الموضوعةيف الزاوية اليسرى‬
‫العليا من موتر اإلدخال ونزلقها عبر موتر اإلدخال‪ ،‬من اليسار إلى اليمين ومن أعلى إلى أسفل‪.‬‬
‫عندما تنزلق نافذة االلتفاف إلى موضع معين‪ ،‬يتم ضرب مستشعر اإلدخال الفرعي الموجوديف ‬
‫تلك النافذة وموتّر النواة بطريقة عنصرية ‪ elementwise‬ويتم تلخيص الموتر الناتج إلنتاج قيمة‬
‫عددية واحدة‪ .‬تعطي هذه النتيجة قيمة موتر اإلخراجيف الموقع المقابل‪ .‬هنا‪ ،‬موتر اإلخراج له‬
‫ارتفاع ‪ 2‬وعرض ‪ 2‬ويتم اشتقاق العناصر األربعة من عملية االرتباط المتبادل ثنائية األبعاد‪:‬‬
‫‪0 × 0 + 1 × 1 + 3 × 2 + 4 × 3 = 19,‬‬
‫‪1 × 0 + 2 × 1 + 4 × 2 + 5 × 3 = 25,‬‬
‫‪3 × 0 + 4 × 1 + 6 × 2 + 7 × 3 = 37,‬‬
‫‪4 × 0 + 5 × 1 + 7 × 2 + 8 × 3 = 43.‬‬
‫الحظ أنه على طول كل محور‪ ،‬يكون حجم اإلخراج أصغر قليالً من حجم اإلدخال‪ .‬نظرًا ألن‬
‫النواة تحتوي على عرض وارتفاع أكبر من واحد‪ ،‬يمكننا فقط حساب االرتباط المتبادل للمواقع‬
‫التي تتالءم فيها النواة بالكامل مع الصورة‪ ،‬ويعطى حجم اإلخراج من خالل حجم اإلدخال‬
‫𝑤𝑛 × ‪ 𝑛ℎ‬مطروحًا منه حجم نواة االلتفاف 𝑤𝑘 × ‪ 𝑘ℎ‬عبر‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪62‬‬

‫‪(𝑛ℎ − 𝑘ℎ + 1) × (𝑛𝑤 − 𝑘𝑤 + 1).‬‬


‫هذا هو الحال ألننا نحتاج إلى مساحة كافية "لنقل ‪ "shift‬نواة االلتفاف ‪convolution kernel‬‬
‫عبر الصورة‪ .‬سنرى الحقًا كيفية الحفاظ على الحجم دون تغيير عن طريق حشو ‪padding‬‬
‫الصورة بأصفار حول حدودها بحيث يكون هناك مساحة كافية إلزاحة النواة‪ .‬بعد ذلك‪ ،‬نقوم‬
‫بتنفيذ هذه العمليةيف دالة ‪ ،corr2d‬التي تقبل موتر اإلدخال ‪ X‬وموتّر النواة ‪ K‬وتعيد موتر‬
‫اإلخراج ‪.Y‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪def corr2d(X, K): #@save‬‬


‫"""‪"""Compute 2D cross-correlation.‬‬
‫‪h, w = K.shape‬‬
‫‪Y = tf.Variable(tf.zeros((X.shape[0] - h + 1,‬‬
‫)))‪X.shape[1] - w + 1‬‬
‫‪for i in range(Y.shape[0]):‬‬
‫‪for j in range(Y.shape[1]):‬‬
‫(‪Y[i, j].assign(tf.reduce_sum‬‬
‫))‪X[i: i + h, j: j + w] * K‬‬
‫‪return Y‬‬
‫يمكننا إنشاء موتر اإلدخال ‪ X‬وموتر النواة ‪ K‬من الشكل ‪ 7.2.1‬للتحقق من صحة إخراج التنفيذ‬
‫أعاله لعملية االرتباط المتبادل ثنائية األبعاد‪.‬‬

‫‪X = tf.constant([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0,‬‬


‫)]]‪7.0, 8.0‬‬
‫)]]‪K = tf.constant([[0.0, 1.0], [2.0, 3.0‬‬
‫)‪corr2d(X, K‬‬
‫‪<tf.Variable 'Variable:0' shape=(2, 2) dtype=float32,‬‬
‫=‪numpy‬‬
‫‪array([[19., 25.],‬‬
‫>)‪[37., 43.]], dtype=float32‬‬
‫‪Convolutional Layers‬‬ ‫‪7.2.2‬‬

‫تربط الطبقة التالفيفية ‪ Convolutional Layer‬بين المدخالت والنواة وتضيف تحيزًا قياسيًا‬
‫إلنتاج مخرجات‪ .‬المعلمتان للطبقة التالفيفية هما النواة ‪ kernel‬والتحيز القياسي ‪.scalar bias‬‬
‫عند تدريب النماذج على أساس الطبقات التالفيفية‪ ،‬نقوم عادةً بتهيئة النواة بشكل عشوائي‪ ،‬تمامًا‬
‫كما نفعل مع طبقة متصلة بالكامل ‪.fully connected layer‬‬
‫‪63‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫نحن اآلن جاهزون لتنفيذ طبقة تالفيفية ثنائية األبعاد بناءً على دالة ‪corr2d‬المحددة أعاله‪.‬يف ‬
‫طريقة المُنشئ __‪ ،__init‬نعلن الوزن ‪ weight‬والتحيز ‪ bias‬كمعاملين للنموذج‪ .‬تستدعي‬
‫دالة االنتشار األمامي الدالة ‪corr2d‬وتضيف التحيز‪.‬‬

‫‪class Conv2D(tf.keras.layers.Layer):‬‬
‫‪def __init__(self):‬‬
‫)(__‪super().__init‬‬

‫‪def build(self, kernel_size):‬‬


‫)(‪initializer = tf.random_normal_initializer‬‬
‫‪self.weight = self.add_weight(name='w',‬‬
‫‪shape=kernel_size,‬‬

‫)‪initializer=initializer‬‬
‫‪self.bias = self.add_weight(name='b', shape=(1,‬‬
‫‪),‬‬

‫)‪initializer=initializer‬‬

‫‪def call(self, inputs):‬‬


‫‪return corr2d(inputs, self.weight) + self.bias‬‬
‫في االلتفاف 𝑤 × ‪ ℎ‬أو نواة االلتفاف 𝑤 × ‪ ،ℎ‬يكون ارتفاع وعرض نواة االلتفاف ‪ ℎ‬و 𝑤‪ ،‬على‬
‫التوالي‪ .‬نشير أيضًا إلى الطبقة التالفيفية ذات النواة االلتفافية 𝑤 × ‪ ℎ‬باعتبارها طبقة تالفيفية‬
‫𝑤 × ‪.ℎ‬‬

‫‪Object Edge Detection in Images‬‬ ‫‪7.2.3‬‬

‫دعنا نتوقف لحظة لتحليل تطبيق بسيط لطبقة تالفيفية‪ :‬اكتشاف حافة كائنيف صورة من خالل‬
‫إيجاد موقع تغيير البكسل‪ .‬أوالً‪ ،‬نقوم ببناء "صورة" لـ ‪ 6 × 8‬بكسل‪ .‬األعمدة األربعة الوسطى‬
‫سوداء (‪ )0‬والباقي بيضاء (‪.)1‬‬

‫)))‪X = tf.Variable(tf.ones((6, 8‬‬


‫))‪X[:, 2:6].assign(tf.zeros(X[:, 2:6].shape‬‬
‫‪X‬‬
‫‪<tf.Variable 'Variable:0' shape=(6, 8) dtype=float32,‬‬
‫=‪numpy‬‬
‫‪array([[1., 1., 0., 0., 0., 0., 1., 1.],‬‬
‫‪[1., 1., 0., 0., 0., 0., 1., 1.],‬‬
‫‪[1., 1., 0., 0., 0., 0., 1., 1.],‬‬
‫‪[1., 1., 0., 0., 0., 0., 1., 1.],‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪64‬‬

‫‪[1., 1., 0., 0., 0., 0., 1., 1.],‬‬


‫‪[1., 1., 0., 0., 0., 0., 1., 1.]],‬‬
‫>)‪dtype=float32‬‬
‫بعد ذلك‪ ،‬نقوم ببناء ‪ kernel K‬بارتفاع ‪ 1‬وعرض ‪ .2‬عندما نجري عملية االرتباط التبادلي مع‬
‫اإلدخال‪ ،‬إذا كانت العناصر المتجاورة ‪ adjacent elements‬أفقيًا هي نفسها‪ ،‬يكون الناتج ‪.0‬‬
‫خالف ذلك‪ ،‬يكون الناتج غير صفري‪ .‬الحظ أن هذه النواة هي حالة خاصة لمشغل الفروق‬
‫المحدودة‪.‬يف الموقع )𝑗 ‪ ،(𝑖,‬يحسب 𝑗‪ ،𝑥𝑖,𝑗 − 𝑥(𝑖+1),‬أي أنه يحسب الفرق بين قيم وحدات‬
‫البكسل المتجاورة أفقيًا‪ .‬هذا تقريب متقطع للمشتق األوليف االتجاه األفقي‪ .‬بعد كل شيء‪ ،‬من‬
‫)𝑗‪𝑓(𝑖,𝑗)−𝑓(𝑖+𝜖,‬‬
‫𝑚𝑖𝑙 = )𝑗 ‪ .−𝜕𝑖 𝑓(𝑖,‬دعونا نرى كيف يعمل هذايف ‬ ‫أجل دالة )𝑗 ‪ 𝑓(𝑖,‬مشتقها‬
‫‪𝜖→0‬‬ ‫𝜖‬
‫الممارسة‪.‬‬

‫)]]‪K = tf.constant([[1.0, -1.0‬‬


‫نحن على استعداد إلجراء عملية االرتباط المتبادل مع الوسيطات ‪( X‬المدخالت الخاصة بنا)‬
‫و‪( K‬النواة الخاصة بنا)‪ .‬كما ترى‪ ،‬نكتشف ‪ 1‬للحافة من األبيض إلى األسود و ‪ -1‬للحافة من‬
‫األسود إلى األبيض‪ .‬جميع النواتج األخرى تأخذ القيمة ‪.0‬‬

‫)‪Y = corr2d(X, K‬‬


‫‪Y‬‬
‫)‪<tf.Variable 'Variable:0' shape=(6, 7‬‬ ‫‪dtype=float32,‬‬
‫=‪numpy‬‬
‫‪array([[ 0., 1., 0., 0., 0., -1.,‬‬ ‫‪0.],‬‬
‫‪[ 0., 1., 0., 0., 0., -1.,‬‬ ‫‪0.],‬‬
‫‪[ 0., 1., 0., 0., 0., -1.,‬‬ ‫‪0.],‬‬
‫‪[ 0., 1., 0., 0., 0., -1.,‬‬ ‫‪0.],‬‬
‫‪[ 0., 1., 0., 0., 0., -1.,‬‬ ‫‪0.],‬‬
‫‪[ 0., 1., 0., 0., 0., -1.,‬‬ ‫‪0.]],‬‬
‫>)‪dtype=float32‬‬
‫يمكننا اآلن تطبيق النواة على الصورة المنقولة ‪ .transposed image‬كما هو متوقع‪ ،‬فإنه يتالشى‪.‬‬
‫يكتشف النواة ‪ K‬الحواف الرأسية ‪ vertical edges‬فقط‪.‬‬

‫)‪corr2d(tf.transpose(X), K‬‬
‫‪<tf.Variable 'Variable:0' shape=(8, 5) dtype=float32,‬‬
‫=‪numpy‬‬
‫‪array([[0., 0., 0., 0., 0.],‬‬
‫‪[0., 0., 0., 0., 0.],‬‬
‫‪[0., 0., 0., 0., 0.],‬‬
‫‪[0., 0., 0., 0., 0.],‬‬
‫‪[0., 0., 0., 0., 0.],‬‬
‫‪65‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪[0., 0., 0., 0., 0.],‬‬


‫‪[0., 0., 0., 0., 0.],‬‬
‫>)‪[0., 0., 0., 0., 0.]], dtype=float32‬‬
‫‪Learning a Kernel‬‬ ‫‪7.2.4‬‬

‫يُعد تصميم كاشف الحواف باالختالفات المحدودة ]‪ [1, -1‬أمرًا رائعًا إذا علمنا أن هذا هو‬
‫بالضبط ما نبحث عنه‪ .‬ومع ذلك‪ ،‬عندما ننظر إلى نوى أكبر‪ ،‬ونأخذيف االعتبار طبقات التالفيف‬
‫المتتالية‪ ،‬فقد يكون من المستحيل التحديد الدقيق لما يجب أن يفعله كل فلتر يدويًا‪.‬‬

‫اآلن دعونا نرى ما إذا كان بإمكاننا تعلم النواة التي ولدت ‪ Y‬من ‪ X‬من خالل النظر إلى أزواج‬
‫اإلدخال واإلخراج فقط‪ .‬نقوم أوالً ببناء طبقة تالفيفية وتهيئة نواتها كموتّر عشوائي‪ .‬بعد ذلك‪،‬يف ‬
‫كل تكرار‪ ،‬سنستخدم الخطأ التربيعي لمقارنة ‪ Y‬بإخراج الطبقة التالفيفية‪ .‬يمكننا بعد ذلك‬
‫حساب التدرج لتحديث النواة‪ .‬من أجل البساطة‪ ،‬فيما يلي نستخدم الكالس المدمج للطبقات‬
‫التالفيفية ثنائية األبعاد ونتجاهل التحيز‪.‬‬

‫‪# Construct a two-dimensional convolutional layer with 1‬‬


‫‪output channel and a‬‬
‫‪# kernel of shape (1, 2). For the sake of simplicity, we‬‬
‫‪ignore the bias here‬‬
‫‪conv2d = tf.keras.layers.Conv2D(1, (1, 2),‬‬
‫)‪use_bias=False‬‬

‫‪# The two-dimensional convolutional layer uses four-‬‬


‫‪dimensional input and‬‬
‫‪# output in the format of (example, height, width,‬‬
‫‪channel), where the batch‬‬
‫‪# size (number of examples in the batch) and the number‬‬
‫‪of channels are both 1‬‬
‫))‪X = tf.reshape(X, (1, 6, 8, 1‬‬
‫))‪Y = tf.reshape(Y, (1, 6, 7, 1‬‬
‫‪lr = 3e-2 # Learning rate‬‬

‫)‪Y_hat = conv2d(X‬‬
‫‪for i in range(10):‬‬
‫)‪with tf.GradientTape(watch_accessed_variables=False‬‬
‫‪as g:‬‬
‫)]‪g.watch(conv2d.weights[0‬‬
‫)‪Y_hat = conv2d(X‬‬
‫‪l = (abs(Y_hat - Y)) ** 2‬‬
‫‪# Update the kernel‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪66‬‬

‫‪update = tf.multiply(lr, g.gradient(l,‬‬


‫))]‪conv2d.weights[0‬‬
‫)(‪weights = conv2d.get_weights‬‬
‫‪weights[0] = conv2d.weights[0] - update‬‬
‫)‪conv2d.set_weights(weights‬‬
‫‪if (i + 1) % 2 == 0:‬‬
‫‪print(f'epoch {i + 1}, loss‬‬
‫)'}‪{tf.reduce_sum(l):.3f‬‬
‫‪epoch 2, loss 1.306‬‬
‫‪epoch 4, loss 0.400‬‬
‫‪epoch 6, loss 0.141‬‬
‫‪epoch 8, loss 0.054‬‬
‫‪epoch 10, loss 0.022‬‬
‫الحظ أن الخطأ قد انخفض إلى قيمة صغيرة بعد ‪ 10‬تكرارات‪ .‬اآلن سوف نلقي نظرة على موتر‬
‫النواة الذي تعلمناه‪.‬‬

‫))‪tf.reshape(conv2d.get_weights()[0], (1, 2‬‬


‫[[(‪<tf.Tensor: shape=(1, 2), dtype=float32, numpy=array‬‬
‫>)‪1.0111188 , -0.98112327]], dtype=float32‬‬

‫في الواقع‪ ،‬موتر النواة المكتسبة قريب بشكل ملحوظ من موتر النواة ‪ K‬الذي حددناه سابقًا‪.‬‬

‫‪Cross-Correlation and Convolution‬‬ ‫‪7.2.5‬‬

‫تذكر مالحظتنا من القسم ‪ 7.1‬من المراسالت بين االرتباط المتبادل ‪cross-correlation‬‬


‫وعمليات االلتفاف ‪ .convolution operations‬دعنا هنا نواصل النظريف الطبقات التالفيفية‬
‫ثنائية األبعاد‪ .‬ماذا لو قامت هذه الطبقات بإجراء عمليات التفاف صارمة ‪strict convolution‬‬
‫‪ operation‬كما هو محدديف (‪ )7.1.6‬بدالً من االرتباطات المتقاطعة؟ من أجل الحصول على‬
‫ناتج عملية االلتفاف الصارمة‪ ،‬نحتاج فقط إلى قلب موتر النواة ثنائي األبعاد أفقيًا وعموديًا‪ ،‬ثم‬
‫إجراء عملية االرتباط المتبادل مع موتر اإلدخال‪.‬‬

‫من الجدير بالذكر أنه نظرًا ألن النوى يتم تعلمها من البياناتيف التعلم العميق‪ ،‬فإن مخرجات‬
‫الطبقات التالفيفية تظل غير متأثرة بغض النظر عن أن هذه الطبقات تؤدي إما عمليات االلتفاف‬
‫الصارمة أو عمليات االرتباط المتبادل‪.‬‬

‫لتوضيح ذلك‪ ،‬افترض أن الطبقة التالفيفية تقوم بعمل ارتباط متبادل وتتعرف على النواةيف الشكل‬
‫‪ ،7.2.1‬والتي يشار إليها هنا بالمصفوفة 𝐊‪ .‬بافتراض أن الشروط األخرى تظل دون تغيير‪ ،‬عندما‬
‫تقوم هذه الطبقة بإجراء التفاف صارم ‪ strict convolution‬بدالً من ذلك‪ ،‬فإن النواة المتعلمة‬
‫‪ 𝐊 ′ learned kernel‬ستكون كما 𝐊 بعد قلبها أفقيًا وعموديًا‪ .‬وهذا يعني أنه عندما تقوم الطبقة‬
‫‪67‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫التالفيفية بإجراء التفاف صارم للمدخالتيف الشكل ‪ ،7.2.1‬وسيتم الحصول على نفس الخرج‬
‫‪𝐊 ′‬في الشكل ‪( 7.2.1‬االرتباط المتبادل للمدخل و 𝐊)‪.‬‬

‫‪Feature Map and Receptive Field‬‬ ‫‪7.2.6‬‬

‫كما هو موضحيف القسم ‪ ،7.1.4‬يُطلق أحيانًا على ناتج الطبقة التالفيفيةيف الشكل ‪ 7.2.1‬اسم‬
‫خريطة المعالم ‪ ،feature map‬حيث يمكن اعتبارها التمثيالت المتعلمة ‪learned‬‬
‫‪( representations‬السمات)يف األبعاد المكانية ‪( spatial dimensions‬مثل العرض‬
‫واالرتفاع) إلى الطبقة الالحقة‪.‬يف شبكات ‪ ،CNN‬بالنسبة ألي عنصريف طبقة ما‪ ،‬يشير مجالها‬
‫التأثيري ‪ receptive field‬إلى جميع العناصر (من جميع الطبقات السابقة) التي قد تؤثر على‬
‫حساب 𝑥 أثناء االنتشار األمامي‪ .‬الحظ أن حقل التأثير قد يكون أكبر من الحجم الفعلي لإلدخال‪.‬‬

‫دعونا نواصل استخدام الشكل ‪ 7.2.1‬لشرح مجال التأثير‪ .‬بالنظر إلى نواة االلتفاف ‪ ،2 × 2‬فإن‬
‫مجال التأثير لعنصر اإلخراج المظلل (للقيمة ‪ )19‬هو العناصر األربعةيف الجزء المظلل من‬
‫المدخالت‪ .‬دعنا اآلن نشير إلى المخرجات ‪ 2 × 2‬على 𝐘 وهي أعمق ‪ CNN‬مع طبقة تالفيفية‬
‫إضافية ‪ 2 × 2‬تأخذ 𝐘 كمدخالتها‪ ،‬وتخرج عنصرًا واحدًا 𝑧‪.‬يف هذه الحالة‪ ،‬يشتمل حقل التأثير‬
‫لـ 𝑧 على 𝐘 لجميع العناصر األربعة لـ 𝐘‪ ،‬بينما يشتمل حقل التأثير على اإلدخال على جميع‬
‫عناصر اإلدخال التسعة‪ .‬وبالتالي‪ ،‬عندما يحتاج أي عنصريف خريطة المعالم إلى مجال تأثير أكبر‬
‫الكتشاف ميزات اإلدخال عبر منطقة أوسع‪ ،‬يمكننا بناء شبكة أعمق‪.‬‬

‫تستمد حقول التأثير اسمها من الفسيولوجيا العصبية ‪.neurophysiology‬يف سلسلة من‬


‫التجارب (‪Hubel and ،1962 ،Hubel and Wiesel ،1959 ،Hubel and Wiesel‬‬
‫‪ )1968 ،Wiesel‬على مجموعة من الحيوانات والمحفزات ‪ stimuli‬المختلفة‪ ،‬استكشف‬
‫‪ Hubel and Wiesel‬استجابة ما يسمى القشرة البصرية ‪ visual cortex‬على المحفزات‬
‫المذكورة‪ .‬بشكل عام‪ ،‬وجدوا أن المستويات األدنى تستجيب للحواف واألشكال ذات الصلة‪.‬يف ‬
‫وقت الحق‪ ،‬أوضح فيلد (‪ )1987‬هذا التأثير على الصور الطبيعية مع ما ال يمكن تسميته إال‬
‫النوى التالفيفية ‪ .convolutional kernels‬نعيد طبع رقم رئيسييف الشكل ‪ 7.2.2‬لتوضيح‬
‫أوجه التشابه المذهلة‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪68‬‬

‫الشكل ‪ 7.2.2‬الشكل والتعليق مأخوذ من ‪ :)1987( Field‬مثال على الترميز بست قنوات‬
‫مختلفة‪( .‬يسار) أمثلة على ستة أنواع من أجهزة االستشعار المرتبطة بكل قناة‪( .‬يمين) التفاف‬
‫للصورةيف (األوسط) مع ستة أجهزة استشعار موضحةيف (يسار)‪ .‬يتم تحديد استجابة أجهزة‬
‫االستشعار الفردية عن طريق أخذ عينات من هذه الصور التي تمت تصفيتها على مسافة‬
‫تتناسب مع حجم المستشعر (موضح بالنقاط)‪ .‬يوضح هذا الرسم البياني استجابة المستشعرات‬
‫المتماثلة فقط‪.‬‬

‫كما اتضح‪ ،‬فإن هذه العالقة تنطبق حتى على الميزات المحسوبة بواسطة طبقات أعمق من‬
‫الشبكات المدربة على مهام تصنيف الصور‪ ،‬كما هو موضح على سبيل المثال‪،‬يف ‪Kuzovkin‬‬
‫‪ .)2018( .et al‬يكفي القول‪ ،‬لقد أثبتت التالفيف أنها أداة قوية بشكل ال يصدق للرؤية‬
‫الحاسوبية‪ ،‬سواءيف علم األحياء أويف الكود‪ .‬على هذا النحو‪ ،‬ليس من المستغرب (بعد فوات‬
‫األوان) أنهم بشروا بالنجاح األخيريف التعلم العميق‪.‬‬

‫‪7.2.7‬‬

‫الحساب األساسي المطلوب للطبقة التالفيفية هو عملية االرتباط المتبادل ‪cross-‬‬


‫‪ .correlation‬لقد رأينا أن حلقة ‪ for-loop‬البسيطة المتداخلة هي كل ما هو مطلوب لحساب‬
‫قيمتها‪ .‬إذا كان لدينا مدخالت متعددة وقنوات إخراج متعددة‪ ،‬فإننا نقوم بإجراء عملية مصفوفة‪-‬‬
‫مصفوفة بين القنوات‪ .‬كما يمكن أن نرى‪ ،‬فإن الحساب مباشر‪ ،‬واألهم من ذلك أنه محلي للغاية‪.‬‬
‫يوفر هذا تحسينًا كبيرًا لألجهزة والعديد من النتائج الحديثةيف الرؤية الحاسوبية ممكنة فقط بسبب‬
‫ذلك‪ .‬بعد كل شيء‪ ،‬هذا يعني أن مصممي الشرائح يمكنهم االستثماريف الحساب السريع بدالً‬
‫‪69‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫من الذاكرة‪ ،‬عندما يتعلق األمر بتحسين التالفيف‪.‬يف حين أن هذا قد ال يؤدي إلى تصميمات‬
‫مثالية للتطبيقات األخرى‪ ،‬إال أنه يفتح الباب أمام الرؤية الحاسوبيةيف كل مكان وبأسعار معقولة‪.‬‬

‫من حيث التالفيف نفسها‪ ،‬يمكن استخدامها ألغراض عديدة مثل اكتشاف الحواف والخطوط‪،‬‬
‫أو تعتيم الصور ‪ ،blur images‬أو شحذها ‪ .sharpen‬واألهم من ذلك‪ ،‬ليس من الضروري أن‬
‫يخترع اإلحصائي (أو المهندس) الفالتر المناسبة‪ .‬بدالً من ذلك‪ ،‬يمكننا ببساطة تعلمها من‬
‫البيانات‪ .‬يحل هذا محل االستدالل الهندسي المميز باإلحصاءات القائمة على األدلة‪ .‬أخيرًا‪ ،‬ومن‬
‫دواعي سرورنا أن هذه المرشحات ليست مفيدة فقط لبناء شبكات عميقة ولكنها تتوافق أيضًا مع‬
‫الحقول المستقبلة وخرائط الميزاتيف الدماغ‪ .‬وهذا يمنحنا الثقة بأننا نسير على الطريق الصحيح‪.‬‬

‫‪7.2.8‬‬

‫‪ .1‬أنشئ صورة ‪ X‬ذات حواف قطرية ‪.diagonal edges‬‬


‫‪ .1‬ماذا يحدث إذا قمت بتطبيق النواة ‪ K‬في هذا القسم عليها؟‬
‫‪ .2‬ماذا يحدث إذا غيرت موضع ‪X‬؟‬
‫‪ .3‬ماذا يحدث إذا قمت بتغيير موضع ‪K‬؟‬
‫‪ .2‬صمم بعض النوى ‪ kernels‬يدويًا‪.‬‬
‫‪ .1‬بالنظر إلى متجه اتجاهي ) ‪ ،𝐯 = (𝑣1 , 𝑣2‬قم باشتقاق نواة الكتشاف الحواف‬
‫والتي تكتشف الحواف المتعامدة إلى 𝐯‪ ،‬أي ‪ ،‬الحواف في االتجاه ) ‪.(𝑣2 , −𝑣1‬‬
‫‪ .2‬اشتق عامل الفروقات المحدودة ‪ finite difference operator‬للمشتق الثاني‪.‬‬
‫ما هو الحد األدنى لحجم النواة التالفيفية المرتبطة بها؟ ما هي الهياكليف الصور‬
‫التي تستجيب لها بشدة؟‬
‫‪ .3‬كيف تصمم نواة ضبابية(معتمة) ‪blur kernel‬؟ لماذا قد ترغبيف استخدام مثل‬
‫هذه النواة؟‬
‫‪ .4‬ما هو الحد األدنى لحجم النواة للحصول على مشتق من الرتبة 𝑑؟‬
‫‪ .3‬عندما تحاول العثور تلقائيًا على التدرج ‪ gradient‬لكالس ‪Conv2D‬التي أنشأناها‪،‬‬
‫ما نوع رسالة الخطأ التي تراها؟‬
‫‪ .4‬كيف تمثل عملية االرتباط المتبادل كضرب مصفوفة عن طريق تغيير موترات اإلدخال‬
‫والنواة؟‬

‫‪Padding and Stride‬‬ ‫‪7.3‬‬


‫استدعي مثال االلتفافيف الشكل ‪ .7.2.1‬كان لكل من المدخالت ارتفاع وعرض ‪ 3‬وكان ارتفاع‬
‫وعرض نواة االلتفاف ‪ ،2‬مما أدى إلى تمثيل إخراج بأبعاد ‪ .2 × 2‬بافتراض أن شكل اإلدخال‬
‫هو 𝑤𝑛 × ‪𝑛ℎ‬وشكل نواة االلتفاف 𝑤𝑘 × ‪ ،𝑘ℎ‬سيكون شكل اإلخراج ‪(𝑛ℎ − 𝑘ℎ +‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪70‬‬

‫)‪ :1) × (𝑛𝑤 − 𝑘𝑤 + 1‬يمكننا فقط تحويل ‪ shift‬نواة االلتفاف حتى اآلن حتى نفاد وحدات‬
‫البكسل لتطبيق االلتفاف عليها‪.‬‬

‫فيما يلي سوف نستكشف عددًا من التقنيات‪ ،‬بمايف ذلك الحشو والتالفيف المتدرجة ‪strided‬‬
‫‪ ،convolutions‬التي توفر مزيدًا من التحكميف حجم اإلخراج‪ .‬كدافع‪ ،‬الحظ أنه نظرًا ألن النوى‬
‫عمومًا لها عرض وارتفاع أكبر من ‪ ،1‬بعد تطبيق العديد من التالفيف المتتالية‪ ،‬فإننا نميل إلى‬
‫الوصول إلى مخرجات أصغر بكثير من مدخالتنا‪ .‬إذا بدأنا بصورة بكسل ‪ ،240 × 240‬فإن‬
‫‪10‬طبقات ‪5 × 5‬تالفيفية تقلل الصورة إلى بكسل ‪ ،200 × 200‬وتقطع ‪ 30%‬من الصورة‬
‫وتزيل أي معلومات مثيرة لالهتمام حول حدود الصورة األصلية‪ .‬الحشو ‪ Padding‬هو األداة‬
‫األكثر شيوعًا للتعامل مع هذه المشكلة‪.‬يف حاالت أخرى‪ ،‬قد نرغبيف تقليل األبعاد بشكل كبير‪،‬‬
‫على سبيل المثال‪ ،‬إذا وجدنا أن دقة اإلدخال األصلية غير عملية‪ .‬التالفيف المتوترة ‪Strided‬‬
‫‪ convolutions‬هي تقنية شائعة يمكن أن تساعديف هذه الحاالت‪.‬‬

‫‪Padding‬‬ ‫‪7.3.1‬‬

‫كما هو موضح أعاله‪ ،‬فإن إحدى المشكالت الصعبة عند تطبيق الطبقات التالفيفية هي أننا نميل‬
‫إلى فقد وحدات البكسليف محيط صورتنا‪ .‬ضعيف اعتبارك الشكل ‪ 7.3.1‬الذي يصور استخدام‬
‫البكسل كدالة لحجم نواة االلتفاف والموضع داخل الصورة‪ .‬نادرًا ما يتم استخدام البكسليف ‬
‫الزوايا على اإلطالق‪.‬‬

‫الشكل ‪ 7.3.1‬استخدام البكسل لتالفيف ذات الحجم ‪ ،1 × 1‬و‪ 3 × 3‬على التوالي‪.‬‬

‫نظرًا ألننا عادةً ما نستخدم نوى صغيرة ‪ ،small kernels‬ألي التفاف معين‪ ،‬فقد نفقد عددًا قليالً‬
‫فقط من وحدات البكسل‪ ،‬لكن هذا يمكن أن يضيف ألننا نطبق العديد من الطبقات التالفيفية‬
‫المتعاقبة‪ .‬يتمثل أحد الحلول المباشرة لهذه المشكلةيف إضافة وحدات بكسل إضافية من الحشو‬
‫حول حدود صورة اإلدخال لدينا‪ ،‬وبالتالي زيادة الحجم الفعال للصورة‪ .‬عادة‪ ،‬نقوم بتعيين قيم‬
‫وحدات البكسل اإلضافية على صفر‪.‬يف الشكل ‪ ،7.3.2‬نقوم بتعبئة (حشو) أحد المدخالت‬
‫‪ ،3 × 3‬وزيادة حجمه إلى ‪ .5 × 5‬ثم يزيد الناتج المقابل إلى مصفوفة ‪ .4 × 4‬األجزاء المظللة‬
‫‪71‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫هي أول عنصر إخراج باإلضافة إلى عناصر موتر اإلدخال والنواة المستخدمة لحساب اإلخراج‪:‬‬
‫‪.0 × 0 + 0 × 1 + 0 × 2 + 0 × 3 = 0‬‬

‫الشكل ‪ 7.3.2‬االرتباط المتبادل ثنائي األبعاد مع الحشو‪.‬‬

‫بشكل عام‪ ،‬إذا أضفنا إجمالي صفوف الحشو ‪( 𝑝ℎ‬نصفها تقريبًايف األعلى ونصفيف األسفل)‬
‫ومجموعًا من أعمدة الحشو 𝑤𝑝 (نصفها تقريبًا على اليسار ونصفها على اليمين)‪ ،‬فسيكون شكل‬
‫اإلخراج‬

‫‪(𝑛ℎ − 𝑘ℎ + 𝑝ℎ + 1) × (𝑛𝑤 − 𝑘𝑤 + 𝑝𝑤 + 1).‬‬


‫هذا يعني أن ارتفاع الناتج وعرضه سيزدادان بمقدار ‪ 𝑝ℎ‬و 𝑤𝑝 على التوالي‪.‬‬

‫في كثير من الحاالت‪ ،‬نريد أن نضبط ‪ 𝑝ℎ = 𝑘ℎ − 1‬و‪ 𝑝𝑤 = 𝑘𝑤 − 1‬نعطي المدخالت‬


‫والمخرجات بنفس االرتفاع والعرض‪ .‬سيسهل هذا التنبؤ بشكل اإلخراج لكل طبقة عند إنشاء‬
‫الشبكة‪ .‬بافتراض أن ‪ 𝑘ℎ‬فردي هنا‪ ،‬سنعبئ الصفوف ‪ 𝑝ℎ /2‬على جانبي االرتفاع‪ .‬إذا كان ‪𝑘ℎ‬‬
‫زوجي‪ ،‬فإن أحد االحتماالت هو حشو الصفوف ⌉‪⌈𝑝ℎ /2‬يف الجزء العلوي من اإلدخال والصفوف‬
‫⌋‪ ⌊𝑝ℎ /2‬يف األسفل‪ .‬سنبطئ جانبي العرض بنفس الطريقة‪.‬‬

‫تستخدم شبكات ‪ CNN‬نواة التفاف ذات قيم عرض وعرض فردية‪ ،‬مثل ‪ 1‬أو ‪ 3‬أو ‪ 5‬أو ‪.7‬‬
‫اختيار أحجام نواة فردية له فائدة أنه يمكننا الحفاظ على األبعاد أثناء الحشو بنفس عدد الصفوف‬
‫في األعلى واألسفل‪ ،‬ونفس عدد األعمدة على اليسار واليمين‪.‬‬

‫عالوة على ذلك‪ ،‬فإن هذه الممارسة المتمثلةيف استخدام نوى فردية وحشو للحفاظ على األبعاد‬
‫بدقة تقدم فائدة كتابية‪ .‬بالنسبة ألي موتر ثنائي األبعاد ‪ ، X‬عندما يكون حجم النواة فرديًا ويكون‬
‫عدد صفوف وأعمدة الحشو متماثلًايف جميع الجوانب‪ ،‬مما ينتج عنه مخرجات بنفس ارتفاع‬
‫وعرض المدخالت ‪ ،‬فنحن نعلم أن الناتج ]‪ Y[i, j‬يتم حسابه من خالل االرتباط المتبادل‬
‫بين المدخالت ونواة االلتفاف مع النافذة المتمركزة على ]‪.X[i, j‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 72

‫ بكسل من‬1 ‫ ونطبق‬3 ‫ قمنا بإنشاء طبقة تالفيفية ثنائية األبعاد بارتفاع وعرض‬،‫في المثال التالي‬
‫ نجد أن ارتفاع وعرض المخرج يساوي‬،8 ‫ بإدخال ارتفاع وعرض‬.‫الحشو على جميع الجوانب‬
.‫ أيضًا‬8

import tensorflow as tf

# We define a helper function to calculate convolutions.


It initializes
# the convolutional layer weights and performs
corresponding dimensionality
# elevations and reductions on the input and output.
def comp_conv2d(conv2d, X):
# (1, 1) indicates that batch size and the number of
channels are both 1
X = tf.reshape(X, (1, ) + X.shape + (1, ))
Y = conv2d(X)
# Strip the first two dimensions: examples and
channels
return tf.reshape(Y, Y.shape[1:3])
# 1 row and column is padded on either side, so a total
of 2 rows or columns are added
conv2d = tf.keras.layers.Conv2D(1, kernel_size=3,
padding='same')
X = tf.random.uniform(shape=(8, 8))
comp_conv2d(conv2d, X).shape
TensorShape([8, 8])

‫ يمكننا أن نجعل الناتج والمدخل لهما نفس االرتفاع‬،‫عندما يختلف ارتفاع وعرض نواة االلتفاف‬
.‫والعرض عن طريق تعيين أرقام حشو مختلفة لالرتفاع والعرض‬

# We use a convolution kernel with height 5 and width 3.


The padding on
# either side of the height and width are 2 and 1,
respectively.
conv2d = tf.keras.layers.Conv2D(1, kernel_size=(5, 3),
padding='same')
comp_conv2d(conv2d, X).shape
TensorShape([8, 8])
‫‪73‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪Stride‬‬ ‫‪7.3.2‬‬

‫عند حساب االرتباط التبادلي ‪ ،cross-correlation‬نبدأ بنافذة االلتفافيف الزاوية العلوية‬


‫اليسرى من موتر اإلدخال‪ ،‬ثم نمرره على جميع المواقع ألسفل وإلى اليمين‪.‬يف األمثلة السابقة‪،‬‬
‫تخلفنا عن تحريك عنصر واحديف كل مرة‪ .‬ومع ذلك‪،‬يف بعض األحيان‪ ،‬إما من أجل الكفاءة‬
‫الحسابية أو ألننا نرغبيف االختزال ‪ ،downsample‬فإننا ننقل نافذتنا أكثر من عنصر واحديف ‬
‫كل مرة‪ ،‬متخطين المواقع الوسيطة‪ .‬هذا مفيد بشكل خاص إذا كانت نواة االلتفاف كبيرة ألنها‬
‫تلتقط مساحة كبيرة من الصورة األساسية‪.‬‬

‫نشير إلى عدد الصفوف واألعمدة التي يتم اجتيازهايف كل شريحة كخطوة ‪ .stride‬حتى اآلن‪،‬‬
‫استخدمنا عدد الخطوات ‪ ،1‬لكل من الطول والعرض‪.‬يف بعض األحيان‪ ،‬قد نرغبيف اتخاذ خطوة‬
‫أكبر‪ .‬يوضح الشكل ‪ 7.3.3‬عملية االرتباط المتبادل ثنائية األبعاد بخطوة ‪ 3‬عموديًا و‪ 2‬أفقيًا‪.‬‬
‫األجزاء المظللة هي عناصر اإلخراج باإلضافة إلى عناصر موتر المدخالت والنواة المستخدمة‬
‫لحساب اإلخراج‪0 × 0 + 6 × 1 + 0 ×،0 × 0 + 0 × 1 + 1 × 2 + 2 × 3 = 8 :‬‬
‫‪ . 2 + 0 × 3 = 6‬يمكننا أن نرى أنه عند إنشاء العنصر الثاني من العمود األول‪ ،‬تنزلق نافذة‬
‫االلتفاف إلى أسفل ثالثة صفوف‪ .‬تنقل نافذة االلتفاف عمودين إلى اليمين عند إنشاء العنصر‬
‫الثاني من الصف األول‪ .‬عندما تستمر نافذة االلتفافيف تحريك عمودين إلى اليمين على اإلدخال‪،‬‬
‫ال يوجد إخراج ألن عنصر اإلدخال ال يمكن أن يمأل النافذة (إال إذا أضفنا عمودًا آخر من الحشو)‪.‬‬

‫الشكل ‪ 7.3.3‬االرتباط المتبادل مع خطوات ‪ 3‬و‪ 2‬لالرتفاع والعرض‪ ،‬على التوالي‪.‬‬

‫بشكل عام‪ ،‬عندما تكون خطوة االرتفاع ‪ 𝑠ℎ‬وخطوة العرض 𝑤𝑠‪ ،‬يكون شكل اإلخراج‬

‫‪⌊(𝑛ℎ − 𝑘ℎ + 𝑝ℎ + 𝑠ℎ )/𝑠ℎ ⌋ × ⌊(𝑛𝑤 − 𝑘𝑤 + 𝑝𝑤 + 𝑠𝑤 )/𝑠𝑤 ⌋.‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪74‬‬

‫إذا قمنا بتعيين ‪ 𝑝ℎ = 𝑘ℎ − 1‬ثم ‪ ،𝑝𝑤 = 𝑘𝑤 − 1‬فيمكن تبسيط شكل اإلخراج إلى ‪⌊(𝑛ℎ +‬‬
‫⌋ 𝑤𝑠‪ .𝑠ℎ − 1)/𝑠ℎ ⌋ × ⌊(𝑛𝑤 + 𝑠𝑤 − 1)/‬للمضي قدمًا‪ ،‬إذا كان ارتفاع اإلدخال وعرضه‬
‫قابلين للقسمة على خطوات االرتفاع والعرض‪ ،‬فسيكون شكل اإلخراج ‪(𝑛ℎ /𝑠ℎ ) × (𝑛𝑤 /‬‬
‫) 𝑤𝑠‪.‬‬

‫أدناه‪ ،‬قمنا بتعيين الخطوات على كل من االرتفاع والعرض على ‪ ،2‬وبالتالي خفض ارتفاع‬
‫المدخالت وعرضها إلى النصف‪.‬‬

‫‪conv2d = tf.keras.layers.Conv2D(1, kernel_size=3,‬‬


‫)‪padding='same', strides=2‬‬
‫‪comp_conv2d(conv2d, X).shape‬‬
‫)]‪TensorShape([4, 4‬‬

‫لنلق نظرة على مثال أكثر تعقيدًا بعض الشيء‪.‬‬

‫‪conv2d = tf.keras.layers.Conv2D(1, kernel_size=(3,5),‬‬


‫‪padding='valid',‬‬
‫))‪strides=(3, 4‬‬
‫‪comp_conv2d(conv2d, X).shape‬‬
‫)]‪TensorShape([2, 1‬‬

‫‪7.3.3‬‬

‫يمكن أن يؤدي الحشو ‪ Padding‬إلى زيادة ارتفاع وعرض اإلخراج‪ .‬غالبًا ما يستخدم هذا إلعطاء‬
‫اإلخراج نفس االرتفاع والعرض مثل المدخالت لتجنب االنكماش ‪ shrinkage‬غير المرغوب‬
‫فيه لإلخراج‪ .‬عالوة على ذلك‪ ،‬فإنه يضمن استخدام جميع وحدات البكسل بشكل متكرر‪ .‬عادةً‬
‫ما نختار حشوة متماثلة ‪ symmetric padding‬على جانبي ارتفاع المدخالت وعرضها‪.‬يف هذه‬
‫الحالة نشير إلى الحشو ) 𝑤𝑝 ‪ .(𝑝ℎ ,‬األكثر شيوعًا التي نضعها 𝑤𝑝 = ‪ ، 𝑝ℎ‬وفي هذه الحالة نذكر‬
‫ببساطة أننا نختار الحشو 𝑝‪.‬‬

‫اتفاقية مماثلة تنطبق على الخطوات‪ .‬عندما تتطابق الخطوة األفقية ‪ 𝑠ℎ‬والخطوة العمودية 𝑤𝑠‪،‬‬
‫نتحدث ببساطة عن الخطوة 𝑠‪ .‬يمكن أن تقلل الخطوة من دقة اإلخراج‪ ،‬على سبيل المثال تقليل‬
‫ارتفاع وعرض اإلخراج إلى 𝑛‪ 1/‬من ارتفاع وعرض المدخالت لـ ‪ .𝑛 > 1‬بشكل افتراضي‪،‬‬
‫تكون المساحة المتروكة ‪ 0‬والخطوة ‪.1‬‬

‫حتى اآلن كل الحشو الذي ناقشناه ببساطة الصور الممتدة مع األصفار‪ .‬هذا له فائدة حسابية كبيرة‬
‫ألنه من السهل تحقيقه‪ .‬عالوة على ذلك‪ ،‬يمكن تصميم المشغلين لالستفادة من هذه الحشوة‬
‫ضمنيًا دون الحاجة إلى تخصيص ذاكرة إضافية‪.‬يف الوقت نفسه‪ ،‬يسمح لشبكات ‪ CNN‬بتشفير‬
‫معلومات الموقع الضمنية داخل الصورة‪ ،‬وذلك ببساطة عن طريق التعرف على مكان وجود‬
‫‪75‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫"المسافة البيضاء ‪ ."whitespace‬هناك العديد من البدائل ‪ alternatives‬للحشو الصفري‪.‬‬


‫(‪ ) 2020 ،Alsallakh et al.‬يقدم نظرة عامة شاملة للبدائل (وإن لم يكن هناك حالة واضحة‬
‫الستخدام حشوات غير صفرية ما لم تحدث القطع األثرية ‪.)unless artifacts occur‬‬

‫‪7.3.4‬‬

‫‪ .1‬بالنظر إلى مثال الكود األخير في هذا القسم مع حجم النواة والحشو والخطوة ‪ ،‬احسب‬
‫شكل اإلخراج للتحقق مما إذا كان متوافقًا مع النتيجة التجريبية‪.‬‬
‫‪ .2‬بالنسبة لإلشارات الصوتية ‪ ،audio signals‬ما الذي يتوافق مع الخطوة ‪2‬؟‬
‫‪ .3‬قم بتنفيذ حشوة متطابقة ‪ ،mirror padding‬أي الحشو حيث يتم عكس قيم الحدود‬
‫ببساطة لتوسيع الموترات‪.‬‬
‫‪ .4‬ما هي الفوائد الحسابية ‪ computational benefits‬لخطوة أكبر من ‪1‬؟‬
‫‪ .5‬ما الفوائد اإلحصائية ‪ statistical benefits‬لخطوة أكبر من ‪1‬؟‬
‫‪1‬‬
‫‪ .6‬كيف ستنفذ خطوة من ‪ 2‬؟ مع ماذا يتوافق؟ متى يكون هذا مفيدا؟‬

‫‪Multiple Input and‬‬ ‫‪7.4‬‬


‫‪Multiple Output Channels‬‬
‫بينما وصفنا القنوات المتعددة ‪ multiple channels‬التي تتكون منها كل صورة (على سبيل‬
‫المثال‪ ،‬تحتوي الصور الملونة على قنوات ‪ RGB‬القياسية لإلشارة إلى مقدار األحمر واألخضر‬
‫واألزرق) والطبقات التالفيفية لقنوات متعددةيف القسم ‪ ،7.1.4‬حتى اآلن‪ ،‬قمنا بتبسيط كل أمثلتنا‬
‫العددية من خالل العمل بمدخل واحد فقط وقناة إخراج واحدة‪ .‬سمح لنا هذا بالتفكيريف ‬
‫مدخالتنا‪ ،‬ونواة االلتفاف‪ ،‬والمخرجات على أنها موترات ثنائية األبعاد‪.‬‬

‫عندما نضيف قنوات إلى المزيج‪ ،‬تصبح كل من مدخالتنا والتمثيالت المخفية موترات ثالثية‬
‫األبعاد‪ .‬على سبيل المثال‪ ،‬كل صورة إدخال ‪ RGB‬لها شكل 𝑤 × ‪ .3 × ℎ‬نشير إلى هذا‬
‫المحور‪ ،‬بحجم ‪ ،3‬كبعد القناة‪ .‬إن فكرة القنوات قديمة قدم شبكات ‪ CNN‬نفسها‪ .‬على سبيل‬
‫المثال‪ ،‬يستخدمها ‪.)1995,. LeCun et al(،LeNet5.‬يف هذا القسم‪ ،‬سوف نلقي نظرة أعمق‬
‫على نواة االلتفاف ذات المدخالت المتعددة وقنوات اإلخراج المتعددة‪.‬‬

‫‪Multiple Input Channels‬‬ ‫‪7.4.1‬‬

‫عندما تحتوي بيانات اإلدخال على قنوات متعددة ‪ ،multiple channels‬نحتاج إلى إنشاء نواة‬
‫التفاف بنفس عدد قنوات اإلدخال مثل بيانات اإلدخال‪ ،‬بحيث يمكنها إجراء ارتباط متبادل مع‬
‫بيانات اإلدخال‪ .‬بافتراض أن عدد القنوات لبيانات اإلدخال هو 𝑖𝑐‪ ،‬يجب أيضًا أن يكون عدد‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪76‬‬

‫قنوات اإلدخال لنواة االلتفاف 𝑖𝑐‪ .‬إذا كان شكل نافذة نواة االلتفاف لدينا هو 𝑤𝑘 × ‪ ،𝑘ℎ‬عندما‬
‫‪ ، 𝑐𝑖 = 1‬يمكننا التفكيريف نواة االلتواء على أنها مجرد موتر ثنائي األبعاد للشكل 𝑤𝑘 × ‪.𝑘ℎ‬‬

‫ومع ذلك‪ ،‬عندما ‪ 𝑐𝑖 > 1‬نحتاج إلى نواة تحتوي على موتر الشكل 𝑤𝑘 × ‪ 𝑘ℎ‬لكل قناة إدخال‪.‬‬
‫يؤدي ربط هذه الموترات معًا إلى إنتاج نواة التفاف للشكل 𝑤𝑘 × ‪ .𝑐𝑖 × 𝑘ℎ‬نظرًا ألن لكل من‬
‫نواة اإلدخال وااللتفاف لديها 𝑖𝑐 قنوات‪ ،‬يمكننا إجراء عملية االرتباط المتبادل على موتر ثنائي‬
‫األبعاد لإلدخال والموتر ثنائي األبعاد لنواة االلتفاف لكل قناة‪ ،‬مع إضافة نتائج 𝑖𝑐 معًا (التجميع‬
‫عبر القنوات) إلنتاج موتر ثنائي األبعاد‪ .‬هذا هو نتيجة االرتباط المتبادل ثنائي األبعاد بين إدخال‬
‫متعدد القنوات ونواة التفاف متعددة المدخالت‪.‬‬

‫يقدم الشكل ‪ 7.4.1‬مثاالً على الترابط الثنائي األبعاد مع قناتي االدخال‪ .‬األجزاء المظللة هي أول‬
‫عنصر إخراج باإلضافة إلى عناصر موتر اإلدخال والنواة المستخدمة لحساب اإلخراج‪(1 × 1 +:‬‬
‫‪.2 × 2 + 4 × 3 + 5 × 4) + (0 × 0 + 1 × 1 + 3 × 2 + 4 × 3) = 56‬‬

‫الشكل ‪ 7.4.1‬حساب االرتباط المتبادل مع قناتي إدخال‪.‬‬

‫للتأكد من أننا نفهم حقًا ما يجري هنا‪ ،‬يمكننا تنفيذ عمليات االرتباط المتبادل مع قنوات اإلدخال‬
‫المتعددة بأنفسنا‪ .‬الحظ أن كل ما نقوم به هو إجراء عملية االرتباط المتبادل لكل قناة ثم جمع‬
‫النتائج‪.‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪def corr2d_multi_in(X, K):‬‬


‫‪# Iterate through the 0th dimension (channel) of K‬‬
‫‪first, then add them up‬‬
‫‪77‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪return tf.reduce_sum([d2l.corr2d(x, k) for x, k in‬‬


‫)‪zip(X, K)], axis=0‬‬
‫يمكننا إنشاء موتر اإلدخال ‪ X‬وموتر النواة ‪ K‬المطابق للقيم الواردةيف الشكل ‪ 7.4.1‬للتحقق من‬
‫صحة خرج عملية االرتباط المتبادل‪.‬‬

‫‪X = tf.constant([[[0.0, 1.0, 2.0], [3.0, 4.0, 5.0],‬‬


‫‪[6.0, 7.0, 8.0]],‬‬
‫‪[[1.0, 2.0, 3.0], [4.0, 5.0, 6.0], [7.0,‬‬
‫)]]]‪8.0, 9.0‬‬
‫‪K = tf.constant([[[0.0, 1.0], [2.0, 3.0]], [[1.0, 2.0],‬‬
‫)]]]‪[3.0, 4.0‬‬

‫)‪corr2d_multi_in(X, K‬‬
‫=‪<tf.Tensor: shape=(2, 2), dtype=float32, numpy‬‬
‫‪array([[ 56., 72.],‬‬
‫>)‪[104., 120.]], dtype=float32‬‬
‫‪Multiple Output Channels‬‬ ‫‪7.4.2‬‬
‫بغض النظر عن عدد قنوات اإلدخال‪ ،‬فقد انتهى بنا المطاف دائمًا بقناة إخراج واحدة‪ .‬ومع ذلك‪،‬‬
‫كما ناقشنايف القسم ‪ ،7.1.4‬فقد تبين أنه من الضروري وجود قنوات متعددةيف كل طبقة‪.‬يف أكثر‬
‫هياكل الشبكات العصبية شيوعًا‪ ،‬نقوم بالفعل بزيادة بُعد القناة أثناء تعمقنايف الشبكة العصبية‪،‬‬
‫وعادةً ما يتم االختزال لموازنة الدقة المكانية للحصول على عمق أكبر للقناة‪ .‬حدسيًا‪ ،‬يمكنك‬
‫التفكيريف كل قناة على أنها تستجيب لمجموعة مختلفة من الميزات‪ .‬الواقع أكثر تعقيدًا من هذا‬
‫بقليل‪ .‬قد يشير التفسير الساذج إلى أن التمثيالت يتم تعلمها بشكل مستقل لكل بكسل أو لكل‬
‫قناة‪ .‬بدالً من ذلك‪ ،‬يتم تحسين القنوات لتكون مفيدة بشكل مشترك‪ .‬هذا يعني أنه بدالً من تعيين‬
‫قناة واحدة لكاشف الحافة‪ ،‬فقد يعني ذلك ببساطة أن بعض االتجاهيف مساحة القناة يتوافق مع‬
‫اكتشاف الحواف‪.‬‬

‫قم باإلشارة إلى 𝑖𝑐 و 𝑜𝑐 عدد قنوات اإلدخال واإلخراج‪ ،‬على التوالي‪ ،‬وليكن ‪ 𝑘ℎ‬و 𝑤𝑘 ارتفاع‬
‫النواة وعرضها‪ .‬للحصول على مخرجات مع قنوات متعددة‪ ،‬يمكننا إنشاء موتر نواة للشكل لكل‬
‫قناة إخراج‪ .‬نجمعها على بُعد قناة اإلخراج‪ ،‬بحيث يكون شكل نواة االلتفاف‬
‫𝑤𝑘 × ‪.𝑐𝑜 × 𝑐𝑖 × 𝑘ℎ‬يف عمليات االرتباط المتبادل‪ ،‬يتم حساب النتيجة على كل قناة إخراج من‬
‫نواة االلتفاف المقابلة لقناة اإلخراج هذه وتأخذ المدخالت من جميع القنواتيف موتر اإلدخال‪.‬‬

‫نقوم بتنفيذ دالة االرتباط المتبادل ‪ cross-correlation function‬لحساب ناتج قنوات متعددة‬
‫كما هو موضح أدناه‪.‬‬

‫‪def corr2d_multi_in_out(X, K):‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪78‬‬

‫‪# Iterate through the 0th dimension of `K`, and each‬‬


‫‪time, perform‬‬
‫‪# cross-correlation operations with input `X`. All‬‬
‫‪of the results are‬‬
‫‪# stacked together‬‬
‫‪return tf.stack([corr2d_multi_in(X, k) for k in K],‬‬
‫)‪0‬‬
‫نقوم ببناء نواة التفاف عادية مع ‪ 3‬قنوات إخراج من خالل تسلسل موتر النواة لـ ‪ K‬مع ‪K+1‬‬
‫و‪.K+2‬‬

‫)‪K = tf.stack((K, K + 1, K + 2), 0‬‬


‫‪K.shape‬‬
‫)]‪TensorShape([3, 2, 2, 2‬‬

‫أدناه‪ ،‬نقوم بإجراء عمليات االرتباط المتبادل على موتر اإلدخال ‪ X‬مع موتر النواة ‪ .K‬اآلن يحتوي‬
‫اإلخراج على ‪ 3‬قنوات‪ .‬تتوافق نتيجة القناة األولى مع نتيجة موتر اإلدخال السابق ‪ X‬والقناة‬
‫متعددة المدخالت‪ ،‬نواة قناة اإلخراج األحادي‪.‬‬

‫)‪corr2d_multi_in_out(X, K‬‬
‫=‪<tf.Tensor: shape=(3, 2, 2), dtype=float32, numpy‬‬
‫‪array([[[ 56., 72.],‬‬
‫‪[104., 120.]],‬‬

‫‪[[ 76., 100.],‬‬


‫‪[148., 172.]],‬‬

‫‪[[ 96., 128.],‬‬


‫>)‪[192., 224.]]], dtype=float32‬‬
‫𝟏 × 𝟏 𝟏 × 𝟏 ‪Convolutional Layer‬‬ ‫‪7.4.3‬‬
‫في البداية‪ ،‬ال يبدو أن االلتفاف ‪ ، 1 × 1‬أي ‪ ،𝑘ℎ = 𝑘𝑤 = 1‬له معنى كبير‪ .‬بعد كل شيء‪،‬‬
‫االلتفاف يربط بين وحدات البكسل المجاورة‪ .‬من الواضح أن االلتفاف ‪ 1 × 1‬ال يفعل ذلك‪.‬‬
‫ومع ذلك‪ ،‬فهي عمليات شائعة يتم تضمينها أحيانًايف تصميمات الشبكات العميقة المعقدة ( ‪Lin‬‬
‫‪ )2017 ،Szegedy et al. ،2013 ،et al.‬دعنا نرى بشيء من التفصيل ما تفعله بالفعل‪.‬‬

‫نظرًا الستخدام الحد األدنى من النافذة‪ ،‬يفقد االلتفاف ‪ 1 × 1‬قدرة الطبقات التالفيفية األكبر‬
‫على التعرف ع لى األنماط المكونة من تفاعالت بين العناصر المجاورةيف أبعاد االرتفاع والعرض‪.‬‬
‫الحساب الوحيد لاللتفاف ‪ 1 × 1‬يحدث على بُعد القناة ‪.channel dimension‬‬
‫‪79‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫يوضح الشكل ‪ 7.4.2‬حساب االرتباط المتبادل باستخدام نواة االلتفاف ‪ 1 × 1‬مع ‪ 3‬قنوات‬
‫إدخال وقناتين إخراج‪ .‬الحظ أن المدخالت والمخرجات لها نفس االرتفاع والعرض‪ .‬يتم اشتقاق‬
‫كل عنصريف اإلخراج من مجموعة خطية من العناصريف نفس الموضعيف صورة اإلدخال‪ .‬يمكنك‬
‫التفكيريف الطبقة التالفيفية ‪ 1 × 1‬على أنها تشكل طبقة متصلة بالكامل مطبقةيف كل موقع بكسل‬
‫فردي لتحويل قيم اإلدخال المقابلة 𝑖𝑐 إلى قيم إخراج 𝑜𝑐‪ .‬نظرًا ألن هذه ال تزال طبقة تالفيفية‪،‬‬
‫يتم ربط األوزان عبر موقع البكسل‪ .‬وبالتالي فإن الطبقة التالفيفية ‪ 1 × 1‬تتطلب أوزانًا (باإلضافة‬
‫إلى التحيز)‪ .‬الحظ أيضًا أن الطبقات التالفيفية تتبعها عادةً الالخطية‪ .‬هذا يضمن أن التالفيف‬
‫‪ 1 × 1‬ال يمكن ببساطة طيهايف تالفيف أخرى‪.‬‬

‫الشكل ‪ 7.4.2‬يستخدم حساب االرتباط التبادلي نواة االلتفاف ‪ 1 × 1‬مع ‪ 3‬قنوات إدخال‬
‫وقناتي إخراج‪ .‬المدخالت والمخرجات لها نفس االرتفاع والعرض‪.‬‬

‫دعنا نتحقق مما إذا كان هذا يعمليف الممارسة العملية‪ :‬نقوم بتنفيذ التفاف ‪ 1 × 1‬باستخدام‬
‫طبقة متصلة بالكامل‪ .‬الشيء الوحيد هو أننا نحتاج إلى إجراء بعض التعديالت على شكل البيانات‬
‫قبل وبعد عملية ضرب المصفوفة‪.‬‬

‫‪def corr2d_multi_in_out_1x1(X, K):‬‬


‫‪c_i, h, w = X.shape‬‬
‫]‪c_o = K.shape[0‬‬
‫))‪X = tf.reshape(X, (c_i, h * w‬‬
‫))‪K = tf.reshape(K, (c_o, c_i‬‬
‫‪# Matrix multiplication in the fully connected layer‬‬
‫)‪Y = tf.matmul(K, X‬‬
‫))‪return tf.reshape(Y, (c_o, h, w‬‬
‫عند إجراء عمليات التالفيف ‪ ،1 × 1‬تكون الدالة المذكورة أعاله مكافئة لدالة االرتباط المتبادل‬
‫التي تم تنفيذها مسبقًا ‪ .corr2d_multi_in_out‬دعنا نتحقق من ذلك ببعض نماذج‬
‫البيانات‪.‬‬

‫)‪X = tf.random.normal((3, 3, 3), 0, 1‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪80‬‬

‫)‪K = tf.random.normal((2, 3, 1, 1), 0, 1‬‬

‫)‪Y1 = corr2d_multi_in_out_1x1(X, K‬‬


‫)‪Y2 = corr2d_multi_in_out(X, K‬‬
‫‪assert float(tf.reduce_sum(tf.abs(Y1 - Y2))) < 1e-6‬‬
‫‪7.4.4‬‬
‫تسمح لنا القنوات بدمج أفضل مايف كال العالمين‪ MLPs :‬التي تسمح بالتالفيفات غير الخطية‬
‫والتالفيفات التي تسمح بالتحليل المحلي ‪ localized analysis‬للميزات‪ .‬على وجه الخصوص‪،‬‬
‫تسمح القنوات لشبكة ‪ CNN‬بالتفكير باستخدام ميزات متعددة‪ ،‬مثل أجهزة الكشف عن‬
‫الحواف والشكليف نفس الوقت‪ .‬كما أنها توفر مفاضلة عملية بين التخفيض الكبير للمعامل‬
‫الناشئ عن ثبات الترجمة والمحلية‪ ،‬والحاجة إلى نماذج معبرة ومتنوعةيف الرؤية الحاسوبية‪.‬‬

‫الحظ‪ ،‬مع ذلك‪ ،‬أن هذه المرونة لها ثمن‪ .‬بالنظر إلى صورة مع حجم)𝑤 × ‪ ،(ℎ‬فإن تكلفة‬
‫حساب االلتفاف 𝑘 × 𝑘 هي ) ‪ .𝒪(ℎ ⋅ 𝑤 ⋅ 𝑘 2‬بالنسبة 𝑖𝑐 و 𝑜𝑐 قنوات اإلدخال واإلخراج على‬
‫التوالي‪ ،‬يزداد هذا إلى ) 𝑜𝑐 ⋅ 𝑖𝑐 ⋅ ‪ .𝒪(ℎ ⋅ 𝑤 ⋅ 𝑘 2‬بالنسبة لصورة ‪ 256 × 256‬بكسل التي‬
‫تحتوي على نواة ‪ 5 × 5‬و‪ 128‬قنوات إدخال وإخراج على التوالي‪ ،‬فإن هذا يصل إلى أكثر من‬
‫‪53‬مليار عملية (نحسب المضاعفات واإلضافات بشكل منفصل)‪.‬يف وقت الحق سنواجه‬
‫استراتيجيات فعالة لخفض التكلفة‪ ،‬على سبيل المثال‪ ،‬من خالل اشتراط أن تكون العمليات على‬
‫مستوى القناة قطرية‪ ،‬مما يؤدي إلى هياكل مثل ‪.)2017 ،.Xie et al(،ResNeXt‬‬

‫‪7.4.5‬‬
‫‪ .1‬افترض أن لدينا نواة التفاف بالحجم ‪ 𝑘2 ،𝑘1‬وعلى التوالي (مع عدم وجود نواة غير‬
‫خطية بينهما)‪.‬‬
‫‪ .1‬إثبت أنه يمكن التعبير عن نتيجة العملية من خالل التفاف واحد ‪single‬‬
‫‪.convolution‬‬
‫‪ .2‬ما هي أبعاد االلتفاف الواحد المكافئ؟‬
‫‪ .3‬هل العكس صحيح ‪ ،‬أي هل يمكنك دائمًا تحليل االلتفاف إلى قسمين أصغر؟‬
‫‪ .2‬افترض مدخالً للشكل 𝑤 × ‪ 𝑐𝑖 × ℎ‬ونواة التفاف من الشكل 𝑤𝑘 × ‪𝑐𝑜 × 𝑐𝑖 × 𝑘ℎ‬‬
‫والحشو ) 𝑤𝑝 ‪ (𝑝ℎ ,‬والخطوة ) 𝑤𝑠 ‪.(𝑠ℎ ,‬‬
‫‪ .1‬ما هي التكلفة الحسابية ‪( computational cost‬الضرب والجمع) لالنتشار‬
‫األمامي؟‬
‫‪ .2‬ما هي بصمة الذاكرة ‪memory footprint‬؟‬
‫‪ .3‬ما هي بصمة الذاكرة للحساب العكسي ‪backward computation‬؟‬
‫‪ .4‬ما هي التكلفة الحسابية لالنتشار الخلفي ‪backpropagation‬؟‬
‫‪81‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪ .3‬بأي عامل يزداد عدد الحسابات إذا ضاعفنا عدد قنوات اإلدخال 𝑖𝑐 وعدد قنوات‬
‫اإلخراج 𝑜𝑐؟ ماذا يحدث إذا ضاعفنا الحشو؟‬
‫‪ .4‬هل المتغيرين ‪ Y1‬و ‪ Y2‬في المثال األخير من هذا القسم متطابقان تمامًا؟ لماذا؟‬
‫‪ .5‬عبر عن التالفيف كضرب مصفوفة ‪ ،‬حتى عندما ال تكون نافذة االلتفاف ‪1 × 1‬؟‬
‫‪ .6‬مهمتك هي تنفيذ التالفيف السريعة باستخدام النواة 𝑘 × 𝑘‪ .‬أحد الخوارزمية المرشحة‬
‫هو المسح أفقيًا عبر المصدر‪ ،‬وقراءة 𝑘‪-‬خطوة عريضة وحساب ‪-1‬خطوة عريضة من‬
‫اإلخراج على نطاق واسع بقيمة واحدة في كل مرة‪ .‬البديل هو قراءة ‪ 𝑘 + Δ‬خطوة‬
‫عريضة وحساب ‪ Δ‬خطوة عريضة من اإلخراج‪ .‬لماذا هذا األخير هو األفضل؟ هل هناك‬
‫حد لمدى الحجم الذي يجب أن تختار ‪ Δ‬؟‬
‫‪ .7‬افترض أن لدينا مصفوفة 𝑐 × 𝑐‪.‬‬
‫‪ .1‬ما مقدار سرعة الضرب بمصفوفة كتلة قطرية إذا تم تقسيم المصفوفة إلى كتل‬
‫𝑏؟‬
‫‪ .2‬ما هو الجانب السلبي من وجود الكتل 𝑏؟ كيف يمكنك إصالحه جزئيًا على‬
‫األقل؟‬

‫‪Pooling‬‬ ‫‪7.5‬‬
‫في كثير من الحاالت‪ ،‬تطرح مهمتنا النهائية بعض األسئلة العالمية حول الصورة‪ ،‬على سبيل‬
‫المثال‪ ،‬هل تحتوي على قطة؟ وبالتالي‪ ،‬يجب أن تكون وحدات الطبقة النهائية حساسة‬
‫للمدخالت بالكامل‪ .‬من خالل تجميع المعلومات تدريجيًا‪ ،‬وإنتاج خرائط خشنة وأكثر خشونة‪،‬‬
‫نحقق هذا الهدف المتمثليف تعلم تمثيل عالمييف النهاية‪ ،‬مع االحتفاظ بجميع مزايا الطبقات‬
‫التالفيفيةيف الطبقات الوسيطة للمعالجة‪ .‬كلما تعمقنايف الشبكة‪ ،‬زاد المجال التأثيري ‪receptive‬‬
‫‪( field‬بالنسبة إلى المدخالت) الذي تكون كل عقدة مخفية حساسة له‪ .‬يؤدي تقليل الدقة‬
‫المكانية إلى تسريع هذه العملية‪ ،‬حيث تغطي نواة االلتفاف مساحة فعالة أكبر‪.‬‬

‫عالوة على ذلك‪ ،‬عند اكتشاف ميزات المستوى األدنى‪ ،‬مثل الحواف (كما تمت مناقشتهيف القسم‬
‫‪ ،)7.2‬غالبًا ما نريد أن تكون تمثيالتنا ثابتة إلى حد ما للترجمة‪ .‬على سبيل المثال‪ ،‬إذا أخذنا‬
‫الصورة ‪ X‬بتحديد حاد بين األسود واألبيض وقمنا بتحويل الصورة بأكملها بمقدار بكسل واحد‬
‫إلى اليمين‪ ،‬أي ]‪ ، Z[i, j] = X[i, j + 1‬فإن الناتج للصورة الجديدة ‪ Z‬قد يكون‬
‫مختلفًا تمامًا‪ .‬سيتم إزاحة الحافة بمقدار بكسل واحد‪.‬يف الواقع‪ ،‬نادرًا ما تحدث األشياءيف نفس‬
‫المكان تمامًا‪.‬يف الواقع‪ ،‬حتى مع وجود حامل ثالثي القوائم وجسم ثابت‪ ،‬فإن اهتزاز الكاميرا‬
‫بسبب حركة مصراع الكاميرا قد يغير كل شيء بمقدار بكسل أو نحو ذلك (يتم تحميل الكاميرات‬
‫المتطورة بميزات خاصة لمعالجة هذه المشكلة)‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪82‬‬

‫يقدم هذا القسم طبقات التجميع ‪ ،pooling layers‬التي تخدم األغراض المزدوجة للتخفيف‬
‫من حساسية الطبقات التالفيفية تجاه الموقع وتمثيالت االختزال المكاني ‪spatially‬‬
‫‪.downsampling representations‬‬

‫‪Maximum Pooling and‬‬ ‫‪7.5.1‬‬


‫‪Average Pooling‬‬
‫مثل الطبقات التالفيفية‪ ،‬تتكون عوامل التجميع ‪ pooling operators‬من نافذة ذات شكل‬
‫ثابت تنزلق فوق جميع المناطقيف اإلدخال وفقًا لخطواتها ‪ ،stride‬وتحسب ناتجًا واحدًا لكل‬
‫موقع يتم اجتيازه بواسطة نافذة الشكل الثابت ‪( fixed-shape window‬تُعرف أحيانًا باسم‬
‫نافذة التجميع ‪ .)pooling window‬ومع ذلك‪ ،‬على عكس حساب االرتباط المتبادل‬
‫للمدخالت والنواةيف الطبقة التالفيفية‪ ،‬ال تحتوي طبقة التجميع على معلمات (ال توجد نواة)‪.‬‬
‫بدالً من ذلك‪ ،‬تكون عوامل التجميع قطعية ‪ ،deterministic‬وتحسب عادةً إما الحد األقصى‬
‫‪ maximum‬أو متوسط ‪ average‬قيمة العناصريف نافذة التجميع‪ .‬تسمى هذه العمليات التجميع‬
‫األقصى ‪ max-pooling( maximum pooling‬لالختصار) وتجميع المتوسط ‪average‬‬
‫‪ ،pooling‬على التوالي‪.‬‬

‫تجميع المتوسط ‪ Average pooling‬قديم قدم شبكات ‪ .CNN‬الفكرة تشبه اختزال‬


‫‪ downsampling‬الصورة‪ .‬بدالً من مجرد أخذ قيمة كل ثانية (أو ثالثة) بكسل للصورة ذات‬
‫الدقة األقل‪ ،‬يمكننا أن نحصل على متوسط أعلى من البكسالت المجاورة للحصول على صورة‬
‫ذات ن سبة إشارة إلى ضوضاء أفضل نظرًا ألننا نجمع المعلومات من عدة وحدات بكسل متجاورة‪.‬‬
‫تم تقديم تجميع الحد االقصى ‪Max-pooling‬يف (‪)1999 ،Riesenhuber and Poggio‬‬
‫في سياق علم األعصاب اإلدراكي ‪ cognitive neuroscience‬لوصف كيفية تجميع‬
‫المعلومات بشكل هرمي لغرض التعرف على األشياء ‪ ،object recognition‬وإصدار سابقيف ‬
‫التعرف على الكالم ‪.)1990 ،Yamaguchi et al.( speech recognition‬يف جميع الحاالت‬
‫تقريبًا‪ ،‬يُفضل استخدام ‪ ،max-pooling‬كما يُشار إليه أيضًا‪.‬‬

‫في كلتا الحالتين‪ ،‬كما هو الحال مع عامل االرتباط المتبادل‪ ،‬يمكننا التفكيريف نافذة التجميع‬
‫‪ pooling window‬على أنها تبدأ من أعلى يسار موتر اإلدخال وتنزلق عبر موتر اإلدخال من‬
‫اليسار إلى اليمين ومن أعلى إلى أسفل‪.‬يف كل موقع تصل إليه نافذة التجميع‪ ،‬فإنها تحسب الحد‬
‫األقصى أو المتوسط لقيمة المستشعر الفرعي لإلدخاليف النافذة‪ ،‬اعتمادًا على ما إذا كان التجميع‬
‫األقصى ‪ max‬أو المتوسط ‪ average‬مستخدمًا‪.‬‬
‫‪83‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪ 7.5.1‬تجميع الحد األقصى ‪ Max-pooling‬مع شكل نافذة تجمع ‪ .2 × 2‬األجزاء المظللة‬


‫هي أول عنصر إخراج باإلضافة إلى عناصر موتر اإلدخال المستخدمة لحساب اإلخراج‪:‬‬
‫‪.𝑚𝑎𝑥(0,1,3,4) = 4‬‬

‫يبلغ ارتفاع موتر االخراجيف الشكل ‪ 2 7.5.1‬وعرضه ‪ .2‬وتُشتق العناصر األربعة من القيمة‬
‫القصوىيف كل نافذة تجميع‪:‬‬

‫‪𝑚𝑎𝑥(0,1,3,4) = 4,‬‬
‫‪𝑚𝑎𝑥(1,2,4,5) = 5,‬‬
‫‪𝑚𝑎𝑥(3,4,6,7) = 7,‬‬
‫‪𝑚𝑎𝑥(4,5,7,8) = 8.‬‬

‫بشكل عام‪ ،‬يمكننا تحديد طبقة تجميع 𝑞 × 𝑝 عن طريق التجميع فوق منطقة بالحجم المذكور‪.‬‬
‫بالعودة إلى مشكلة اكتشاف الحواف‪ ،‬نستخدم ناتج الطبقة التالفيفية كمدخل لتجميع الحد‬
‫األقصى ‪ .2 × 2‬تشير بواسطة ‪ X‬إلى مدخالت الطبقة التالفيفية و‪ Y‬ناتج طبقة التجميع‪ .‬بغض‬
‫و‬ ‫]‪X[i, j], X[i, j + 1], X[i+1, j‬‬ ‫قيم‬ ‫كانت‬ ‫إذا‬ ‫عما‬ ‫النظر‬
‫]‪ X[i+1, j + 1‬مختلفة ‪ ،‬طبقة التجميع دائمًا لها المخرجات ‪ .Y[i, j] = 1‬أي‬
‫باستخدام طبقة الحد األقصى من التجميع ‪ ، 2 × 2‬ال يزال بإمكاننا اكتشاف ما إذا كان النمط‬
‫الذي تم التعرف عليه بواسطة الطبقة االلتفافية ال يتحرك أكثر من عنصر واحديف االرتفاع أو‬
‫العرض‪.‬‬

‫في الكود أدناه‪ ،‬نقوم بتنفيذ االنتشار األمامي لطبقة التجميعيف دالة ‪ pool2d.‬هذه الدالة مشابهة‬
‫للدالة ‪ corr2d‬يف القسم ‪ .7.2‬ومع ذلك‪ ،‬ليست هناك حاجة إلى نواة‪ ،‬حيث يتم حساب‬
‫المخرجات على أنها الحد األقصى أو المتوسط لكل منطقةيف اإلدخال‪.‬‬

‫‪import tensorflow as tf‬‬

‫‪def pool2d(X, pool_size, mode='max'):‬‬


‫‪p_h, p_w = pool_size‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪84‬‬

‫‪Y = tf.Variable(tf.zeros((X.shape[0] - p_h + 1,‬‬


‫)))‪X.shape[1] - p_w +1‬‬
‫‪for i in range(Y.shape[0]):‬‬
‫‪for j in range(Y.shape[1]):‬‬
‫‪if mode == 'max':‬‬
‫‪Y[i, j].assign(tf.reduce_max(X[i: i +‬‬
‫))]‪p_h, j: j + p_w‬‬
‫‪elif mode =='avg':‬‬
‫‪Y[i, j].assign(tf.reduce_mean(X[i: i +‬‬
‫))]‪p_h, j: j + p_w‬‬
‫‪return Y‬‬
‫يمكننا إنشاء موتر اإلدخال ‪X‬يف الشكل ‪ 7.5.1‬للتحقق من صحة خرج طبقة التجميع الحد‬
‫االقصى ثنائية األبعاد ‪.two-dimensional max-pooling layer‬‬

‫‪X = tf.constant([[0.0, 1.0, 2.0], [3.0, 4.0, 5.0], [6.0,‬‬


‫)]]‪7.0, 8.0‬‬
‫))‪pool2d(X, (2, 2‬‬
‫‪<tf.Variable 'Variable:0' shape=(2, 2) dtype=float32,‬‬
‫=‪numpy‬‬
‫‪array([[4., 5.],‬‬
‫>)‪[7., 8.]], dtype=float32‬‬
‫أيضًا‪ ،‬نجرب طبقة تجميع المتوسط ‪.average pooling layer‬‬

‫)'‪pool2d(X, (2, 2), 'avg‬‬


‫‪<tf.Variable 'Variable:0' shape=(2, 2) dtype=float32,‬‬
‫=‪numpy‬‬
‫‪array([[2., 3.],‬‬
‫>)‪[5., 6.]], dtype=float32‬‬
‫‪Padding and Stride‬‬ ‫‪7.5.2‬‬
‫كما هو الحال مع الطبقات التالفيفية‪ ،‬تغير طبقات التجميع شكل اإلخراج‪ .‬وكمايف السابق‪،‬‬
‫يمكننا ضبط العملية لتحقيق الشكل المطلوب لإلخراج عن طريق حشو ‪ Padding‬المدخالت‬
‫وضبط الخطوة ‪ . Stride‬يمكننا إثبات استخدام الحشو والخطواتيف طبقات التجميع عبر طبقة‬
‫تجميع الحد االقصى ثنائية األبعاد المضمنة من إطار عمل التعلم العميق‪ .‬نقوم أوالً ببناء موتر‬
‫اإلدخال ‪ X‬الذي يحتوي شكله على أربعة أبعاد‪ ،‬حيث يكون عدد األمثلة (حجم الدُفعة ‪batch‬‬
‫‪ )size‬وعدد القنوات ‪.1‬‬

‫الحظ أنه بخالف األطر األخرى‪ ،‬يفضل ‪ TensorFlow‬ويتم تحسينه لمدخل آخر القنوات‬
‫‪.channels-last input‬‬
85 ‫ الشبكات العصبية االلتفافية‬:‫الفصل السابع‬

X = tf.reshape(tf.range(16, dtype=tf.float32), (1, 4, 4,


1))
X
<tf.Tensor: shape=(1, 4, 4, 1), dtype=float32, numpy=
array([[[[ 0.],
[ 1.],
[ 2.],
[ 3.]],

[[ 4.],
[ 5.],
[ 6.],
[ 7.]],

[[ 8.],
[ 9.],
[10.],
[11.]],

[[12.],
[13.],
[14.],
[15.]]]], dtype=float32)>
‫ فإن أطر التعلم العميق تتطابق مع أحجام نوافذ‬،‫نظرًا ألن التجميع يجمع المعلومات من منطقة ما‬
‫) نحصل على‬3 ،3( ‫ إذا استخدمنا نافذة تجميع للشكل‬،‫ على سبيل المثال‬.‫التجميع والخطوات‬
.‫) افتراضيًا‬3 ،3( ‫شكل خطوة‬

pool2d = tf.keras.layers.MaxPool2D(pool_size=[3, 3])


# Pooling has no model parameters, hence it needs no
initialization
pool2d(X)
<tf.Tensor: shape=(1, 1, 1, 1), dtype=float32,
numpy=array([[[[10.]]]], dtype=float32)>

‫ يمكن تحديد الخطوة والحشو يدويًا لتجاوز اإلعدادات االفتراضية إلطار العمل‬،‫كما هو متوقع‬
.‫إذا لزم األمر‬

paddings = tf.constant([[0, 0], [1,0], [1,0], [0,0]])


X_padded = tf.pad(X, paddings, "CONSTANT")
pool2d = tf.keras.layers.MaxPool2D(pool_size=[3, 3],
padding='valid',
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪86‬‬

‫)‪strides=2‬‬
‫)‪pool2d(X_padded‬‬
‫=‪<tf.Tensor: shape=(1, 2, 2, 1), dtype=float32, numpy‬‬
‫‪array([[[[ 5.],‬‬
‫‪[ 7.]],‬‬

‫‪[[13.],‬‬
‫>)‪[15.]]]], dtype=float32‬‬
‫بالطبع‪ ،‬يمكننا تحديد نافذة تجميع عشوائية مستطيلة ذات ارتفاع وعرض تعسفيين على التوالي‪،‬‬
‫كما يوضح المثال أدناه‪.‬‬

‫)]]‪paddings = tf.constant([[0, 0], [0, 0], [1, 1], [0, 0‬‬


‫)"‪X_padded = tf.pad(X, paddings, "CONSTANT‬‬

‫‪pool2d = tf.keras.layers.MaxPool2D(pool_size=[2, 3],‬‬


‫‪padding='valid',‬‬
‫))‪strides=(2, 3‬‬
‫)‪pool2d(X_padded‬‬
‫=‪<tf.Tensor: shape=(1, 2, 2, 1), dtype=float32, numpy‬‬
‫‪array([[[[ 5.],‬‬
‫‪[ 7.]],‬‬

‫‪[[13.],‬‬
‫>)‪[15.]]]], dtype=float32‬‬
‫‪Multiple Channels‬‬ ‫‪7.5.3‬‬
‫عند معالجة بيانات اإلدخال متعددة القنوات ‪ ،multi-channel input data‬تقوم طبقة‬
‫التجميع بتجميع كل قناة إدخال على حدة‪ ،‬بدالً من جمع المدخالت عبر القنوات كما هو الحال‬
‫في الطبقة ال تالفيفية‪ .‬هذا يعني أن عدد قنوات اإلخراج لطبقة التجميع هو نفسه عدد قنوات‬
‫اإلدخال‪ .‬أدناه‪ ،‬سنقوم بتجميع الموترات ‪ X‬و ‪ X + 1‬على بُعد القناة إلنشاء إدخال بقناتين‪.‬‬

‫الحظ أن هذا سيتطلب تسلسالً على طول البعد األخير لـ ‪ TensorFlow‬بسبب بناء جملة‬
‫القنوات األخير‪.‬‬

‫‪X = tf.concat([X, X + 1], 3) # Concatenate along‬‬


‫‪`dim=3` due to channels-last syntax‬‬
‫كما نرى‪ ،‬ال يزال عدد قنوات اإلخراج ‪ 2‬بعد التجميع‪.‬‬

‫)]]‪paddings = tf.constant([[0, 0], [1,0], [1,0], [0,0‬‬


‫)"‪X_padded = tf.pad(X, paddings, "CONSTANT‬‬
‫‪87‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪pool2d = tf.keras.layers.MaxPool2D(pool_size=[3, 3],‬‬


‫‪padding='valid',‬‬
‫)‪strides=2‬‬
‫)‪pool2d(X_padded‬‬
‫=‪<tf.Tensor: shape=(1, 2, 2, 2), dtype=float32, numpy‬‬
‫‪array([[[[ 5., 6.],‬‬
‫‪[ 7., 8.]],‬‬

‫‪[[13., 14.],‬‬
‫>)‪[15., 16.]]]], dtype=float32‬‬
‫الحظ أن ناتج تجميع ‪ TensorFlow‬يبدو للوهلة األولى مختلفًا‪ ،‬ولكن يتم عرض نفس النتائج‬
‫عدديًا على أنها ‪ MXNet‬و ‪ .PyTorch‬يكمن االختالفيف األبعاد‪ ،‬وتؤدي قراءة اإلخراج‬
‫عموديًا إلى نفس اإلخراج مثل التطبيقات األخرى‪.‬‬

‫‪7.5.4‬‬
‫التجميع ‪ Pooling‬هو عملية بسيطة للغاية‪ .‬إنه يفعل بالضبط ما يشير إليه اسمه‪ ،‬النتائج اإلجمالية‬
‫عبر نافذة من القيم‪ .‬كل دالالت االلتفاف ‪ ،convolution semantics‬مثل الخطوات ‪strides‬‬
‫والحشو ‪ ،padding‬تنطبق بنفس الطريقة كما فعلت سابقًا‪ .‬الحظ أن التجميع غير مكترث‬
‫بالقنوات‪ ،‬أي أنه يترك عدد القنوات دون تغيير وينطبق على كل قناة على حدة‪ .‬أخيرًا‪ ،‬من بين‬
‫خياري التجميع الشائعين‪ ،‬يُفضل تجميع الحد األقصى ‪ max-pooling‬على تجميع المتوسط‬
‫‪ ، average pooling‬ألنه يمنح درجة معينة من الثبات لإلخراج‪ .‬االختيار الشائع هو اختيار‬
‫حجم نافذة التجميع ‪ 2 × 2‬إلى ربع الدقة المكانية لإلخراج‪.‬‬

‫الحظ أن هناك العديد من الطرق لتقليل الدقة بعد التجميع‪ .‬على سبيل المثال‪،‬يف التجميع‬
‫العشوائي ‪ )2013 ،Zeiler and Fergus( stochastic pooling‬والتجميع األقصى الكسري‬
‫‪ )2014 ،Graham( fractional max-pooling‬يتم الجمع بين التجميع ‪aggregation‬‬
‫والعشوائية ‪ .randomization‬يمكن أن يؤدي ذلك إلى تحسين الدقة قليالًيف بعض الحاالت‪.‬‬
‫أخيرًا‪ ،‬كما سنرى الحقًا مع آلية االنتباه ‪ ،attention mechanism‬هناك طرق أكثر دقة لتجميع‬
‫المخرجات ‪ ،aggregating over outputs‬على سبيل المثال‪ ،‬باستخدام المحاذاة بين متجهي‬
‫االستعالم ‪ query‬والتمثيل ‪.representation vectors‬‬

‫‪7.5.5‬‬
‫‪ .1‬نفذ تجميع المتوسط ‪ average pooling‬من خالل االلتفاف‪.‬‬
‫‪ .2‬إثبت أن تجميع الحد األقصى ‪ max-pooling‬ال يمكن تنفيذه من خالل االلتفاف‬
‫وحده‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪88‬‬

‫‪ .3‬يمكن تحقيق تجميع الحد األقصى باستخدام عمليات ‪ ، ReLU‬أي‪.‬‬


‫‪ .1‬عبر عن )𝑏 ‪ 𝑚𝑎𝑥(𝑎,‬باستخدام عمليات ‪ ReLU‬فقط‪.‬‬
‫‪ .2‬استخدم هذا لتنفيذ تجميع الحد األقصى عن طريق التالفيف وطبقات ‪.ReLU‬‬
‫‪ .3‬كم عدد القنوات والطبقات التي تحتاجها لاللتفاف ‪ 2 × 2‬؟ كم العدد لاللتفاف‬
‫‪.3 × 3‬‬
‫‪ .4‬ما هي التكلفة الحسابية لطبقة التجميع؟ افترض أن المدخالت إلى طبقة التجميع ذات‬
‫حجم 𝑤 × ‪ ، 𝑐 × ℎ‬وأن نافذة التجميع لها شكل 𝑤𝑝 × ‪ 𝑝ℎ‬مع حشوة ) 𝑤𝑝 ‪(𝑝ℎ ,‬‬
‫وخطوة ) 𝑤𝑠 ‪.(𝑠ℎ ,‬‬
‫‪ .5‬لماذا تتوقع أن يعمل تجميع الحد األقصى وتجميع المتوسط بشكل مختلف؟‬
‫‪ .6‬هل نحتاج إلى طبقة تجميع صغيرة منفصلة؟ هل يمكنك استبدالها بعملية أخرى؟‬
‫‪ .7‬يمكننا استخدام عملية ‪ softmax‬للتجميع‪ .‬لماذا قد ال تحظى بشعبية كبيرة؟‬

‫‪LeNet‬‬ ‫‪7.6‬‬
‫لدينا اآلن جميع المكونات المطلوبة لتجميع شبكة ‪ CNN‬كاملة الوظائف‪.‬يف مواجهتنا السابقة‬
‫لبيانات الصورة‪ ،‬طبقنا نموذجًا خطيًا مع انحدار ‪( softmax‬القسم ‪ )4.4‬و‪( MLP‬القسم ‪)5.2‬‬
‫على صور المالبسيف مجموعة بيانات ‪ .Fashion-MNIST‬لجعل هذه البيانات قابلة‬
‫للتمكين‪ ،‬قمنا أوالً بتسطيح ‪ flattened‬كل صورة من مصفوفة ‪ 28 × 28‬إلى متجه ‪ 784‬أبعاد‬
‫ثابت الطول‪ ،‬وبعد ذلك قمنا بمعالجتهايف طبقات متصلة بالكامل‪ .‬اآلن بعد أن أصبح لدينا التعامل‬
‫مع الطبقات التالفيفية‪ ،‬يمكننا االحتفاظ بالبنية المكانيةيف صورنا‪ .‬كميزة إضافية الستبدال‬
‫الطبقات المتصلة بالكامل بطبقات تالفيفية‪ ،‬سنستمتع بنماذج شحيحة تتطلب معلمات أقل‬
‫بكثير‪.‬‬

‫في هذا القسم‪ ،‬سنقدم ‪ ،LeNet‬من بين أولى شبكات ‪ CNN‬المنشورة لجذب اهتمام واسع‬
‫ألدائهايف مهام الرؤية الحاسوبية‪ .‬تم تقديم النموذج بواسطة (وسمي بإسم) ‪ ،Yann LeCun‬ثم‬
‫باحثيف ‪ ،AT&T Bell Labs‬بغرض التعرف على األرقام المكتوبة بخط اليديف الصور‬
‫(‪ .) 1998 ،LeCun et al.‬يمثل هذا العمل تتويجا لعقد من البحث لتطوير التكنولوجيا‪.‬يف عام‬
‫‪ ،1989‬نشر فريق ‪ LeCun‬أول دراسة لتدريب شبكات ‪ CNN‬بنجاح من خالل االنتشار‬
‫الخلفي ‪.)1989 ،LeCun et al.( backpropagation‬‬

‫في ذلك الوقت‪ ،‬حققت ‪ LeNet‬نتائج رائعة مطابقة ألداء آالت المتجهات الداعمة ‪support‬‬
‫‪ ،vector machines‬ثم نهجًا مهيمنًايف التعلم الخاضع لإلشراف‪ ،‬حيث حقق معدل خطأ أقل‬
‫من ‪ ٪1‬لكل رقم‪ .‬تم تكييف ‪LeNet‬يف النهاية للتعرف على األرقام لمعالجة الودائعيف أجهزة‬
‫‪89‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫الصراف اآللي‪ .‬حتى يومنا هذا‪ ،‬ال تزال بعض أجهزة الصراف اآللي تشغل الكود الذي كتبه يان‬
‫ليكون وزميله ليون بوتويف التسعينيات!‬

‫‪LeNet 7.6.1‬‬
‫على مستوى عالٍ‪ ،‬تتكون )‪ LeNet (LeNet-5‬من جزأين‪ )1( :‬مشفر تالفيفي‬
‫‪ convolutional encoder‬يتكون من طبقتين تالفيفيتين؛ و (‪ )2‬كتلة كثيفة ‪dense block‬‬
‫تتكون من ثالث طبقات متصلة بالكامل؛ تم تلخيص المعماريةيف الشكل ‪.7.6.1‬‬

‫الشكل ‪ 7.6.1‬تدفق البياناتيف ‪ .LeNet‬اإلدخال عبارة عن رقم مكتوب بخط اليد‪ ،‬والمخرج‬
‫هو احتمال أكثر من ‪ 10‬نتائج محتملة‪.‬‬

‫الوحدات األساسيةيف كل كتلة تالفيفية ‪ convolutional block‬هي طبقة تالفيفية‬


‫‪ ،convolutional layer‬ودالة تنشيط ‪ ،sigmoid‬وعملية تجميع المتوسط ‪average‬‬
‫‪ pooling‬الحقة‪ .‬الحظ أنه بينما تعمل ‪ ReLUs‬و‪ max-pooling‬بشكل أفضل‪ ،‬لم يتم إجراء‬
‫هذه االكتشافاتيف ذلك الوقت‪ .‬تستخدم كل طبقة تالفيفية نواة ودالة تنشيط ‪ .sigmoid‬تطابق‬
‫هذه الطبقات مدخالت مرتبة مكانيًا إلى عدد من خرائط المعالم ثنائية األبعاد‪ ،‬مما يؤدي عادةً‬
‫إلى زيادة عدد القنوات‪ .‬تحتوي الطبقة التالفيفية األولى على ‪ 6‬قنوات إخراج‪ ،‬بينما تحتوي الثانية‬
‫على ‪ .16‬كل عملية تجميع (خطوة ‪ )2‬تقلل األبعاد بعامل من خالل االختزال المكاني ‪spatial‬‬
‫‪ .downsampling‬تبعث الكتلة التالفيفية ناتجًا بالشكل المعطى بواسطة (حجم الدُفعة‪ ،‬عدد‬
‫القنوات‪ ،‬االرتفاع‪ ،‬العرض)‪.‬‬

‫من أجل تمرير اإلخراج من الكتلة التالفيفية ‪ convolutional block‬إلى الكتلة الكثيفة ‪dense‬‬
‫‪ ،block‬يجب علينا تسطيح كل مثاليف الدفعات الصغيرة ‪ .minibatch‬بمعنى آخر‪ ،‬نأخذ هذا‬
‫اإلدخال رباعي األبعاد ونحوله إلى مدخالت ثنائية األبعاد تتوقعها طبقات متصلة تمامًا‪ :‬كتذكير‪،‬‬
‫يستخدم التمثيل ثنائي األبعاد الذي نرغب فيه البعد األول لفهرسة األمثلةيف ‪ minibatch‬والثانية‬
‫إلعطاء تمثيل متجه مسطح ‪ flat‬لكل مثال‪ .‬تحتوي كتلة ‪ LeNet‬الكثيفة على ثالث طبقات‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪90‬‬

‫متصلة بالكامل‪ ،‬مع مخرجات ‪ 120‬و‪ 84‬و‪ 10‬على التوالي‪ .‬نظرًا ألننا ما زلنا نقوم بالتصنيف‪،‬‬
‫فإن طبقة اإلخراج ذات ‪ 10‬أبعاد تتوافق مع عدد فئات اإلخراج الممكنة‪.‬‬

‫أثناء الوصول إلى النقطة التي تفهم فيها حقًا ما يجري داخل ‪ ،LeNet‬ربما تكون قد اتخذت‬
‫القليل من العمل‪ ،‬نأمل أن يقنعك مقتطف الشفرة التالي بأن تنفيذ مثل هذه النماذج باستخدام‬
‫أطر عمل التعلم العميق الحديثة أمر بسيط بشكل ملحوظ‪ .‬نحتاج فقط إلى إنشاء كتلة‬
‫‪ Sequential‬وتربط معًا للطبقات المناسبة ‪ ،‬باستخدام تهيئة ‪ Xavier‬كما هو مقدميف القسم‬
‫‪.5.4.2.2‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪class LeNet(d2l.Classifier):‬‬
‫‪def __init__(self, lr=0.1, num_classes=10):‬‬
‫)(__‪super().__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫[(‪self.net = tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Conv2D(filters=6,‬‬
‫‪kernel_size=5,‬‬
‫‪activation='sigmoid',‬‬
‫‪padding='same'),‬‬
‫‪tf.keras.layers.AvgPool2D(pool_size=2,‬‬
‫‪strides=2),‬‬
‫‪tf.keras.layers.Conv2D(filters=16,‬‬
‫‪kernel_size=5,‬‬

‫‪activation='sigmoid'),‬‬
‫‪tf.keras.layers.AvgPool2D(pool_size=2,‬‬
‫‪strides=2),‬‬
‫‪tf.keras.layers.Flatten(),‬‬
‫‪tf.keras.layers.Dense(120,‬‬
‫‪activation='sigmoid'),‬‬
‫‪tf.keras.layers.Dense(84,‬‬
‫‪activation='sigmoid'),‬‬
‫)])‪tf.keras.layers.Dense(num_classes‬‬
‫نأخذ بعض الحريةيف إعادة إنتاج ‪ LeNet‬بقدر ما نستبدل طبقة التنشيط الغاوسية بطبقة‬
‫‪ .softmax‬هذا يبسط التنفيذ إلى حد كبير‪ ،‬ليس أقلها بسبب حقيقة أن مفكك شفرة ‪Gaussian‬‬
‫نادراً ما يستخدميف الوقت الحاضر‪ .‬بخالف ذلك‪ ،‬تتطابق هذه الشبكة مع بنية ‪LeNet-5‬‬
‫األصلية‪.‬‬
91 ‫ الشبكات العصبية االلتفافية‬:‫الفصل السابع‬

‫ (باألبيض‬28 × 28 ‫ من خالل تمرير صورة أحادية القناة‬.‫دعونا نرى ما يحدث داخل الشبكة‬
‫ يمكننا فحص النموذج للتأكد من أن‬،‫واألسود) عبر الشبكة وطباعة شكل اإلخراجيف كل طبقة‬
.7.6.2 ‫عملياته تتماشى مع ما نتوقعه من الشكل‬

.LeNet-5 ‫ لـ‬Compressed notation ‫ التدوين المضغوط‬7.6.2 ‫الشكل‬

@d2l.add_to_class(d2l.Classifier) #@save
def layer_summary(self, X_shape):
X = tf.random.normal(X_shape)
for layer in self.net.layers:
X = layer(X)
print(layer.__class__.__name__, 'output
shape:\t', X.shape)

model = LeNet()
model.layer_summary((1, 28, 28, 1))
Conv2D output shape: (1, 28, 28, 6)
AveragePooling2D output shape: (1, 14, 14, 6)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪92‬‬

‫‪Conv2D output shape:‬‬ ‫)‪(1, 10, 10, 16‬‬


‫‪AveragePooling2D output shape:‬‬ ‫)‪(1, 5, 5, 16‬‬
‫‪Flatten output shape:‬‬ ‫)‪(1, 400‬‬
‫)‪Dense output shape: (1, 120‬‬
‫)‪Dense output shape: (1, 84‬‬
‫)‪Dense output shape: (1, 10‬‬
‫الحظ أنه يتم تقليل ارتفاع وعرض التمثيليف كل طبقة عبر الكتلة التالفيفية (مقارنة بالطبقة‬
‫السابقة)‪ .‬تستخدم الطبقة التالفيفية األولى ‪ 2‬بكسل من الحشو للتعويض عن االنخفاضيف ‬
‫االرتفاع والعرض الذي قد ينتج عن استخدام النواة ‪ .5 × 5‬باإلضافة إلى ذلك‪ ،‬فإن حجم صورة‬
‫‪ 28 × 28‬بكسليف مجموعة بيانات ‪ MNIST OCR‬األصلية هو نتيجة القتطاع صفوف ‪2‬‬
‫بكسل (وأعمدة) من عمليات المسح األصلية التي تم قياس ‪ 32 × 32‬بكسل‪ .‬تم القيام بذلك‬
‫بشكل أساسي لتوفير مساحة (تخفيض بنسبة ‪)٪30‬يف وقت كانت فيه الميجابايت مهمة‪.‬‬

‫في المقابل‪ ،‬تتجاهل الطبقة التالفيفية الثانية الحشو‪ ،‬وبالتالي يتم تقليل االرتفاع والعرض بمقدار‬
‫‪ 4‬بكسل‪ .‬مع صعود كومة الطبقات‪ ،‬يزيد عدد القنوات طبقة الطبقة العلوية من ‪1‬يف اإلدخال إلى‬
‫‪ 6‬بعد الطبقة التالفيفية األولى و‪ 16‬بعد الطبقة التالفيفية الثانية‪ .‬ومع ذلك‪ ،‬فإن كل طبقة تجميع‬
‫تقسم االرتفاع والعرض إلى النصف‪ .‬أخيرًا‪ ،‬تقلل كل طبقة متصلة بالكامل من األبعاد‪ ،‬وتصدر‬
‫أخيرًا ناتجًا يتطابق بعده مع عدد الفئات‪.‬‬

‫‪Training‬‬ ‫‪7.6.2‬‬
‫اآلن بعد أن قمنا بتنفيذ النموذج‪ ،‬دعنا نجري تجربة لنرى كيف يعمل نموذج ‪ LeNet-5‬على‬
‫‪.Fashion-MNIST‬‬

‫بينما تحتوي شبكات ‪ CNN‬على عدد أقل من المعلمات‪ ،‬إال أنه ال يزال من الممكن حسابها‬
‫أكثر تكلفة من ‪ MLPs‬العميقة المماثلة ألن كل معلمة تشاركيف العديد من عمليات الضرب‪ .‬إذا‬
‫كان لديك وصول إلى وحدة معالجة الرسومات ‪ ،GPU‬فقد يكون هذا هو الوقت المناسب‬
‫لوضعها موضع التنفيذ لتسريع التدريب‪ .‬الحظ أن فئة ‪ d2l.Trainer‬تهتم بكل التفاصيل‪.‬‬
‫بشكل افتراضي‪ ،‬يقوم بتهيئة معلمات النموذج على األجهزة المتاحة‪ .‬تمامًا كما هو الحال مع‬
‫‪ ،MLPs‬فإن دالة الخطأ لدينا هي إنتروبيا متقاطعة ‪ ،cross-entropy‬ونقوم بتقليلها عن طريق‬
‫التدرج االشتقاقي العشوائي المصغر ‪.minibatch stochastic gradient descent‬‬

‫)‪trainer = d2l.Trainer(max_epochs=10‬‬
‫)‪data = d2l.FashionMNIST(batch_size=128‬‬
‫‪with d2l.try_gpu():‬‬
‫)‪model = LeNet(lr=0.1‬‬
‫)‪trainer.fit(model, data‬‬
‫‪93‬‬ ‫الفصل السابع‪ :‬الشبكات العصبية االلتفافية‬

‫‪7.6.3‬‬
‫في هذا الفصل أحرزنا تقدمًا كبيرًا‪ .‬انتقلنا من ‪ MLPs‬في الثمانينيات إلى شبكات ‪ CNN‬في‬
‫التسعينيات وأوائل العقد األول من القرن الحادي والعشرين‪ .‬تظل ال ُبنى المقترحة‪ ،‬على سبيل‬
‫المثال‪،‬يف شكل ‪ LeNet-5‬ذات مغزى‪ ،‬حتى يومنا هذا‪ .‬يجدر مقارنة معدالت الخطأيف ‬
‫‪Fashion-MNIST‬التي يمكن تحقيقها مع ‪ LeNet-5‬بأفضل ما يمكن باستخدام ‪MLPs‬‬
‫(القسم ‪ )5.2‬وتلك ذات البنى األكثر تقدمًا مثل ‪( ResNet‬القسم ‪ .)8.6‬يشبه ‪ LeNet‬األخير‬
‫أكثر من السابق‪ .‬أحد االختالفات األساسية‪ ،‬كما سنرى‪ ،‬هو أن الكميات األكبر من الحسابات‬
‫أتاحت بنى معمارية أكثر تعقيدًا بشكل ملحوظ‪.‬‬

‫االختالف الثاني هو السهولة النسبية التي تمكنا بها من تنفيذ ‪ .LeNet‬ما كان يمثل تحديًا هندسيًا‬
‫يستحق شهورًا من ‪ ++ C‬وكود التجميع ‪ ،assembly code‬والهندسة لتحسين ‪ ،SN‬وأداة‬
‫التعلم العميق القائمة على ‪ ،)1988, Bottou and Le Cun( ،Lisp‬وأخيراً يمكن اآلن إجراء‬
‫التجارب مع النماذجيف دقائق‪ .‬هذه الزيادة الهائلةيف اإلنتاجية هي التي أدت إلى إضفاء الطابع‬
‫الديمقراطي على تطوير نموذج التعلم العميق بشكل هائل‪.‬يف الفصل التالي سوف نتبع هذا األرنب‬
‫لنرى أين يأخذنا‪.‬‬

‫‪7.6.4‬‬
‫‪ .1‬دعونا نحدث ‪ .LeNet‬نفِّذ واختبر التغييرات التالية‪:‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪94‬‬

‫‪ .1‬استبدل تجميع المتوسط ‪ average pooling‬بتجميع الحد االقصى ‪max-‬‬


‫‪.pooling‬‬
‫‪ .2‬استبدل طبقة ‪ softmax‬بـ ‪.ReLU‬‬
‫‪ .2‬حاول تغيير حجم شبكة نمط ‪ LeNet‬لتحسين دقتها باإلضافة إلى ‪max-pooling‬‬
‫و ‪.ReLU‬‬
‫‪ .1‬اضبط حجم نافذة االلتفاف‪.‬‬
‫‪ .2‬اضبط عدد قنوات اإلخراج‪.‬‬
‫‪ .3‬اضبط عدد طبقات االلتفاف‪.‬‬
‫‪ .4‬اضبط عدد الطبقات المتصلة بالكامل‪.‬‬
‫‪ .5‬اضبط معدالت التعلم وتفاصيل التدريب األخرى (على سبيل المثال ‪ ،‬التهيئة‬
‫وعدد الفترات‪).‬‬
‫‪ .3‬جرب الشبكة المحسنة على مجموعة بيانات ‪ MNIST‬األصلية‪.‬‬
‫‪ .4‬اعرض تنشيط الطبقة األولى والثانية من ‪ LeNet‬لمدخالت مختلفة (على سبيل‬
‫المثال‪ ،‬السترات والمعاطف ‪.)sweaters and coats‬‬
‫‪ .5‬ماذا يحدث لعمليات التنشيط عندما تقوم بإدخال صور مختلفة بشكل كبيريف الشبكة‬
‫(على سبيل المثال‪ ،‬القطط أو السيارات أو حتى الضوضاء العشوائية)؟‬
‫الشبكات العصبية التالفيفية‬
‫الحديثة‬
‫‪8‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪96‬‬

‫‪Modern‬‬ ‫‪8‬‬
‫‪Convolutional Neural Networks‬‬
‫اآلن بعد أن فهمنا أساسيات توصيل شبكات ‪ CNN‬معًا‪ ،‬فلنقم بجولةيف هياكل ‪ CNN‬الحديثة‪.‬‬
‫هذه الجولة‪ ،‬بالضرورة‪ ،‬غير مكتملة‪ ،‬وذلك بفضل العدد الكبير من التصاميم الجديدة المثيرة‬
‫التي تمت إضافتها‪ .‬تنبع أهميتها من حقيقة أنه ال يمكن استخدامها مباشرة لمهام الرؤية فحسب‪،‬‬
‫بل إنها تعمل أيضًا كمولدات ميزات أساسية للمهام األكثر تقدمًا مثل التتبع ‪Zhang ( tracking‬‬
‫‪ ،)2021 ،et al.‬والتقطيع ‪ ،)2015 ،Long et al.( segmentation‬اكتشاف الكائن ‪object‬‬
‫‪ ،)2018 ،Redmon and Farhadi( detection‬أو تغيير النمط ‪style transformation‬‬
‫(‪.)2016 ،Gatys et al.‬يف هذا الفصل‪ ،‬تتوافق معظم األقسام مع بُنية ‪ CNN‬الهامة التي كانت‬
‫في مرحلة ما (أو حاليًا) النموذج األساسي الذي تم بناء العديد من مشاريع البحث واألنظمة‬
‫المنشورة عليه‪ .‬كانت كل من هذه الشبكات لفترة وجيزة معمارية مهيمنة وكان العديد منهم فائزين‬
‫أو وصيفينيف مسابقة ‪ ImageNet‬التي كانت بمثابة مقياس للتقدميف التعلم الخاضع لإلشراف‬
‫في الرؤية الحاسوبية منذ عام ‪ .2010‬وفي اآلونة األخيرة فقط بدأت المحوالت ‪transformers‬‬
‫في استبدال شبكات ‪ ،CNN‬بدءًا من ‪ )2021( .Dosovitskiy et al‬ويليه محول‪،swin‬‬
‫(‪ .) 2021 ،.Liu et al‬سنغطي هذا التطور الحقًايف الفصل الخاص بآليات االنتباه والمحوالت‬
‫‪.Attention Mechanisms and Transformers‬‬

‫في حين أن فكرة الشبكات العصبية العميقة بسيطة للغاية (تكديس مجموعة من الطبقات معًا)‪،‬‬
‫يمكن أن يختلف األداء بشكل كبير عبر خيارات ال ُبنى والمعلمات الفائقة‪ .‬الشبكات العصبية‬
‫الموصوفةيف هذا الفصل هي نتاج الحدس ‪ ،intuition‬وبعض األفكار الرياضية‪ ،‬والكثير من‬
‫التجربة والخطأ ‪ .trial and error‬نقدم هذه النماذج بترتيب زمني‪ ،‬جزئيًا لنقل إحساس بالتاريخ‬
‫بحيث يمكنك تكوين حدسك الخاص حول المكان الذي يتجه إليه المجال وربما تطوير ال ُبنى‬
‫الخاصة بك‪ .‬على سبيل المثال‪ ،‬قدّم التسوية بالدُفعات ‪ batch normalization‬والتوصيالت‬
‫المتبقية الموصوفة ‪ residual connections‬يف هذا الفصل فكرتين شائعتين للتدريب وتصميم‬
‫النماذج العميقة‪ ،‬وكالهما تم تطبيقهما منذ ذلك الحين على ال ُبنى التي تتجاوز الرؤية الحاسوبية‬
‫أيضًا‪.‬‬

‫نبدأ جولتنايف شبكات ‪ CNN‬الحديثة مع ‪ ،)2012 ،.Krizhevsky et al(،AlexNet‬وهي‬


‫أول شبكة واسعة النطاق تم نشرها للتغلب على أساليب الرؤية الحاسوبية التقليديةيف تحدي الرؤية‬
‫واسع النطاق ؛ شبكة ‪ ، )2014 ،Simonyan and Zisserman(،VGG‬والتي تستخدم عددًا‬
‫من الكتل المتكررة للعناصر ؛ الشبكةيف الشبكة (‪ )NiN‬التي تجمع الشبكات العصبية بالكامل‬
‫عبر المدخالت ( ‪ )2013 ،Lin et al.‬؛ ‪ GoogLeNet‬التي تستخدم شبكات ذات تالفيف‬
‫‪97‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫متعددة الفروع ‪ Szegedy( multi-branch convolutions‬وآخرون ‪ )2015 ،‬؛ الشبكة‬


‫المتبقية ‪ ، )2016 ،.He et al(،(ResNet) residual network‬والتي ال تزال من أشهر‬
‫ال ُبنى الجاهزة ‪off-the-shelf architectures‬يف الرؤية الحاسوبية ؛ كتل ‪Xie( ResNeXt‬‬
‫وآخرون ‪ )2017 ،‬لالتصاالت المتفرقة ‪sparser connections‬؛ و ‪Huang (،DenseNet‬‬
‫‪ )2017,.et al‬لتعميم العمارة المتبقية‪ .‬بمرور الوقت‪ ،‬تم تطوير العديد من التحسينات الخاصة‬
‫للشبكات الفعالة‪ ،‬مثل تحويالت اإلحداثيات ‪Wu et ( ،(ShiftNet) coordinate shifts‬‬
‫‪ . )2018 ،.al‬بلغ هذا ذروتهيف البحث التلقائي عن بنيات فعالة مثل ‪MobileNet v3‬‬
‫‪ .)2019..Howard et al(،‬ويشمل أيضًا استكشاف التصميم شبه التلقائي ‪semi-‬‬
‫‪ automatic design exploration‬لـ ‪ )2020( .Radosavovic et al‬التي أدت إلى‬
‫‪ RegNetX / Y‬والتي سنناقشها الحقًايف هذا الفصل‪ .‬العمل مفيد بقدر ما يوفر مسارًا لتزاوج‬
‫حساب القوة العمياء ببراعة المجربيف البحث عن مساحات تصميم فعالة‪ .‬وتجدر اإلشارة أيضًا‬
‫إلى عمل ‪ )2022( .Liu et al‬كما يوضح أن تقنيات التدريب (مثل‪ ،‬المحسنون ‪،optimizers‬‬
‫وزيادة البيانات ‪ ،data augmentation‬والتنظيم ‪ )regularization‬تلعب دورًا محوريًايف ‬
‫تحسين الدقة‪ .‬كما يوضح أيضًا أن االفتراضات القديمة‪ ،‬مثل حجم نافذة االلتفاف‪ ،‬قد تحتاج‬
‫إلى إعادة النظر‪ ،‬نظرًا للزيادةيف الحساب والبيانات‪ .‬سنغطي هذا والعديد من األسئلة األخرىيف ‬
‫الوقت المناسب خالل هذا الفصل‪.‬‬

‫‪AlexNet‬‬ ‫‪8.1‬‬
‫على الرغم من أن شبكات ‪ CNN‬كانت معروفة جيدًايف مجتمعات الرؤية الحاسوبية والتعلم‬
‫اآللي بعد تقديم ‪ ،)1995,.LeCun et al( ،LeNet‬إال أنها لم تهيمن على هذا المجال على‬
‫الفور‪ .‬على الرغم من أن ‪ LeNet‬حققت نتائج جيدةيف مجموعات البيانات الصغيرة المبكرة‪ ،‬إال‬
‫أنه لم يتم بعد إنشاء أداء وجدوى تدريب شبكات ‪ CNN‬على مجموعات بيانات أكبر وأكثر‬
‫واقعية‪.‬يف الواقع‪ ،‬خالل معظم الوقت الفاصل بين أوائل التسعينيات ونتائج مستجمعات المياه‬
‫‪ watershed results‬لعام ‪ ،)2012 ،Krizhevsky et al.( 2012‬غالبًا ما تم تجاوز الشبكات‬
‫العصبية بواسطة طرق التعلم اآللي األخرى‪ ،‬مثل طرق النواة ‪Schölkopf and ( ،kernel‬‬
‫‪ ،)2002,Smola‬الطرق الجماعية ‪ ،)1996 ،.Freund et al( ensemble‬والتقدير المهيكل‬
‫‪.)2004 ،Taskar et al.( structured estimation‬‬

‫بالنسبة للرؤية الحاسوبية‪ ،‬ربما ال تكون هذه المقارنة دقيقة تمامًا‪ .‬أي‪ ،‬على الرغم من أن مدخالت‬
‫الشبكات التالفيفية ‪ CNN‬تتكون من قيم بكسل خام أو معالجة بخفة ‪lightly-processed‬‬
‫(على سبيل المثال‪ ،‬عن طريق التوسيط ‪ ،)centering‬فإن الممارسين لن يقوموا أبدًا بتغذية‬
‫وحدات البكسل الخاميف النماذج التقليدية‪ .‬بدالً من ذلك‪ ،‬تتكون خطوط أنابيب الرؤية الحاسوبية‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪98‬‬

‫النموذجية من خطوط أنابيب استخراج الميزات الهندسية يدويًا‪ ،‬مثل ‪،)2004,Lowe( ،SIFT‬‬
‫‪ ،)2006,Bay et al.( ،SURF‬وأكياس الكلمات المرئية ‪Sivic ( bags of visual words‬‬
‫‪ .)2003 ،and Zisserman‬بدالً من تعلم الميزات ‪ ،learning the features‬تم تصميم‬
‫الميزات ‪ .features were crafted‬جاء معظم التقدم من وجود أفكار أكثر ذكاءً الستخراج‬
‫الميزات من ناحية ونظرة عميقةيف الهندسة ‪)2000 ،Hartley and Zisserman( geometry‬‬
‫من ناحية أخرى‪ .‬غالبًا ما كانت خوارزمية التعلم تعتبر فكرة متأخرة‪.‬‬

‫على الرغم من توفر بعض مسرعات الشبكة العصبيةيف التسعينيات‪ ،‬إال أنها لم تكن قوية بما يكفي‬
‫إلنشاء شبكات ‪ CNN‬عميقة متعددة القنوات ومتعددة الطبقات مع عدد كبير من المعلمات‪.‬‬
‫على سبيل المثال‪ ،‬تمكنت ‪ GeForce 256‬من ‪ NVIDIA‬من عام ‪ 1999‬من معالجة ‪480‬‬
‫مليون عمليةيف الثانية على األكثر (‪ ،)MFLOPs‬دون أي إطار عمل برمجة مفيد للعمليات خارج‬
‫األلعاب‪ .‬تستطيع مسرعات اليوم أداء ما يزيد عن ‪ TFLOPs 300‬لكل جهاز ( ‪NVIDIA's‬‬
‫‪ .)Ampere A100‬الحظ أن ‪ FLOPs‬هي عمليات الفاصلة العائمة مثل عمليات الضرب‬
‫واإلضافات‪ .‬عالوة على ذلك‪ ،‬كانت مجموعات البيانات ‪ datasets‬ال تزال صغيرة نسبيًا‪ :‬كان‬
‫التعرف الضوئي على الحروف على ‪ 60.000‬صورة بكسل منخفضة الدقة مهمة صعبة للغاية‪.‬‬
‫يضاف إلى هذه العقبات‪ ،‬الحيل الرئيسية لتدريب الشبكات العصبية بمايف ذلك توجيهات تهيئة‬
‫المعلمات (‪ ،)2010 ،Glorot and Bengio‬االنواع الذكية من التدرج االشتقاقي العشوائي‬
‫(‪ ،)2014 ،Kingma and Ba‬دوال التنشيط غير السحق ‪non-squashing activation‬‬
‫‪ ،)2010 ،Nair and Hinton( functions‬وتقنيات التنظيم الفعالة ‪effective‬‬
‫‪ )2014 ،.Srivastava et al( regularization techniques‬ال تزال مفقودة‪.‬‬

‫وبالتالي‪ ،‬بدالً من تدريب أنظمة من طرف إلى طرف ‪( end-to-end‬بكسل إلى تصنيف ‪pixel‬‬
‫‪ ،)to classification‬بدت خطوط األنابيب الكالسيكية ‪ classical pipelines‬أكثر مثل هذا‪:‬‬

‫‪ .1‬احصل على مجموعة بيانات مثيرة لالهتمام‪.‬يف األيام األولى‪ ،‬كانت مجموعات البيانات‬
‫هذه تتطلب أجهزة استشعار باهظة الثمن‪ .‬على سبيل المثال‪ ،‬تتميز ‪Apple‬‬
‫‪ QuickTake 100‬لعام ‪ 1994‬بدقة هائلة تبلغ ‪ 0.3‬ميجابكسل (‪ ،)VGA‬قادرة‬
‫على تخزين ما يصل إلى ‪ 8‬صور‪ ،‬وكل ذلك بسعر ‪ 1000‬دوالر‪.‬‬
‫‪ .2‬قم بإجراء معالجة مسبقة لمجموعة البيانات باستخدام ميزات مصنوعة يدويًا استنادًا‬
‫إلى بعض المعرفة بالبصريات والهندسة وأدوات التحليل األخرى‪ ،‬وأحيانًا على‬
‫االكتشافات المصادفة لطالب الدراسات العليا المحظوظين‪.‬‬
‫‪ .3‬قم بتغذية البيانات من خالل مجموعة قياسية من مستخلصات الميزات مثل ‪SIFT‬‬
‫(تحويل ميزة مقياس ثابت ‪،)scale-invariant feature transform‬‬
‫‪99‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫(‪( SURF ،)2004,Lowe‬ميزات قوية مسرعة ‪)speeded up robust features‬‬


‫(‪ ،)2006 ،Bay et al.‬أو أي عدد من ناحية أخرى ‪ -‬خطوط األنابيب المضبوطة‪ .‬ال‬
‫يزال ‪ OpenCV‬يوفر مستخلصات ‪ SIFT‬حتى يومنا هذا!‬
‫‪ .4‬تخلص من التمثيالت ‪ representations‬الناتجةيف المصنف المفضل لديك‪ ،‬من‬
‫المحتمل أن يكون نموذجًا خطيًا أو طريقة ‪ ،kernel‬لتدريب المصنف‪.‬‬

‫إذا تحدثت إلى باحثي التعلم اآللي‪ ،‬فإنهم يعتقدون أن التعلم اآللي مهم وجميليف نفس الوقت‪.‬‬
‫أثبتت النظريات األنيقة خصائص المصنفات المختلفة (‪ )2005 ،Boucheron et al.‬وأصبح‬
‫التحسين المحدب ‪)2004 ،Boyd and Vandenberghe( convex optimization‬‬
‫الدعامة األساسية للحصول عليها‪ .‬كان مجال التعلم اآللي مزدهرًا وصارمًا ومفيدًا بشكل كبير‪.‬‬
‫ومع ذلك‪ ،‬إذا تحدثت إلى باحثيف الرؤية الحاسوبية‪ ،‬فستسمع قصة مختلفة تمامًا‪ .‬سيقولون لك‬
‫إن الحقيقة القذرة للتعرف على الصور هي أن الميزات ‪ features‬والهندسة الرياضية ‪geometry‬‬
‫(‪ ،)2009 ،Hartley and Kahl ،2000 ،Hartley and Zisserman‬والهندسة‬
‫‪ ،engineering‬بدالً من خوارزميات التعلم الجديدة‪ ،‬هي التي أدت إلى التقدم‪ .‬يعتقد الباحثون‬
‫في الرؤية الحاسوبية بشكل مبرر أن مجموعة بيانات أكبر أو أنظف قليالً أو خط أنابيب محسّن‬
‫قليالً الستخراج الميزات أهم بكثير بالنسبة للدقة النهائية أكثر من أي خوارزمية تعلم‪.‬‬

‫‪Representation Learning‬‬ ‫‪8.1.1‬‬


‫هناك طريقة أخرى لتصوير الوضع وهي أن أهم جزء من خط األنابيب كان التمثيل‬
‫‪ .representation‬وحتى عام ‪ ،2012‬تم حساب التمثيليف الغالب ميكانيكيًا‪.‬يف الواقع‪ ،‬كانت‬
‫هندسة مجموعة جديدة من دوال الميزات‪ ،‬وتحسين النتائج‪ ،‬وكتابة الطريقة نوعًا بارزًا من‬
‫المقاالت‪( HOG ، )2006,.Bay et al( ،SURF ، )2004,Lowe( ،SIFT .‬الرسوم‬
‫البيانية للتدرج الموجه ‪،Dalal and Triggs ( )histograms of oriented gradient‬‬
‫‪ ، )2005‬وأكياس الكلمات المرئية ‪،Sivic and Zisserman ( bags of visual words‬‬
‫‪ ، )2003‬وما شابه ذلك من مستخلصات الميزة السائدة‪.‬‬

‫مجموعة أخرى من الباحثين‪ ،‬بمايف ذلك ‪ Yann LeCun‬و ‪ Geoff Hinton‬و ‪Yoshua‬‬
‫‪ Bengio‬و ‪ Andrew Ng‬و ‪ Shun-ichi Amari‬و ‪ ،Juergen Schmidhuber‬لديهم‬
‫خطط مختلفة‪ .‬لقد اعتقدوا أنه يجب تعلم الميزات نفسها‪ .‬عالوة على ذلك‪ ،‬اعتقدوا أنه لكي‬
‫تكون معقدة بشكل معقول‪ ،‬يجب أن تتكون الميزات بشكل هرمي ‪ hierarchically‬من طبقات‬
‫متعددة تم تعلمها بشكل مشترك‪ ،‬ولكل منها معلمات قابلة للتعلم‪.‬يف حالة الصورة‪ ،‬قد تكتشف‬
‫الطبقات الدنيا الحواف واأللوان والنسيج ‪ ،textures‬على غرار الطريقة التي يعالج بها النظام‬
‫المرئييف الحيوانات مدخالته‪ .‬على وجه الخصوص‪ ،‬ظل التصميم التلقائي للميزات المرئية مثل‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪100‬‬

‫تلك التي تم الحصول عليها عن طريق التشفير المتناثر ‪Olshausen and ( sparse coding‬‬
‫‪ )1996 ،Field‬يمثل تحديًا مفتوحًا حتى ظهور شبكات ‪ CNN‬الحديثة‪ .‬لم يكن األمر كذلك‬
‫حتى )‪ ) 2013( Le ،Dean et al. (2012‬أن فكرة إنشاء ميزات من بيانات الصورة اكتسبت‬
‫تلقائيًا جذباً كبيرًا‪.‬‬

‫أول شبكة ‪ CNN‬حديثة (‪ ،)2012 ،Krizhevsky et al.‬التي سميت ‪ AlexNet‬على اسم‬


‫أحد مخترعيها‪ ،Alex Krizhevsky ،‬هي إلى حد كبير تحسين تطوري على ‪ .LeNet‬لقد‬
‫حققت أداءً ممتازًايف تحدي ‪ ImageNet‬لعام ‪.2012‬‬

‫الشكل ‪ 8.1.1‬تم التعرف على فالتر الصور بواسطة الطبقة األولى من ‪ .AlexNet‬إعادة التوليد‬
‫‪ Reproduction‬مجاملة من ‪.)2012( .Krizhevsky et al‬‬

‫ومن المثير لالهتماميف الطبقات السفلية للشبكة‪ ،‬أن النموذج تعلم مستخلصات الميزات‬
‫‪ feature extractors‬التي تشبه بعض المرشحات التقليدية ‪ .traditional filters‬يوضح‬
‫الشكل ‪ 8.1.1‬واصفات الصورة ذات المستوى األدنى‪ .‬قد تبني الطبقات العليايف الشبكة على هذه‬
‫التمثيالت لتمثيل هياكل أكبر‪ ،‬مثل العيون واألنوف وشفرات العشب وما إلى ذلك‪ .‬قد تمثل‬
‫الطبقات العليا كائنات كاملة مثل األشخاص أو الطائرات أو الكالب أو األطباق الطائرة‪.‬يف النهاية‪،‬‬
‫تتعلم الحالة المخفية النهائية تمثيلًا مضغوطًا للصورة يلخص محتوياتها بحيث يمكن فصل‬
‫البيانات التي تنتمي إلى فئات مختلفة بسهولة‪.‬‬
‫‪101‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫تشترك ‪ )2012( AlexNet‬وسابقتها ‪)1995( LeNet‬يف العديد من العناصر المعمارية‪ .‬هذا‬


‫يطرح السؤال‪ :‬لماذا استغرق األمر كل هذا الوقت؟ يتمثل أحد االختالفات الرئيسيةيف أنه خالل‬
‫العقدين الماضيين‪ ،‬زادت كمية البيانات وقوة الحوسبة المتاحة بشكل كبير‪ .‬على هذا النحو‪ ،‬كان‬
‫‪ AlexNet‬أكبر بكثير‪ :‬فقد تم تدريبه على المزيد من البيانات‪ ،‬وعلى وحدات معالجة رسومات‬
‫‪ GPU‬أسرع بكثير‪ ،‬مقارنة بوحدات المعالجة المركزية ‪ CPU‬المتوفرةيف عام ‪.1995‬‬

‫‪Missing Ingredient: Data‬‬ ‫‪8.1.1.1‬‬


‫تتطلب النماذج العميقة ذات الطبقات المتعددة كميات كبيرة من البيانات من أجل الدخول إلى‬
‫النظام حيث تتفوق بشكل كبير على األساليب التقليدية القائمة على التحسينات المحدبة‬
‫‪( convex optimizations‬على سبيل المثال‪ ،‬األساليب الخطية والنواة)‪ .‬ومع ذلك‪ ،‬نظرًا‬
‫لقدرة التخزين المحدودة ألجهزة الكمبيوتر‪ ،‬والتكلفة النسبية ألجهزة االستشعار (التصويرية)‪،‬‬
‫وميزانيات البحث األكثر تشددًا نسبيًايف التسعينيات‪ ،‬اعتمدت معظم األبحاث على مجموعات‬
‫بيانات صغيرة‪ .‬اعتمدت العديد من األوراق البحثية على مجموعة قواعد البيانات الخاصة بـ‬
‫‪ ، UCI‬والتي احتوى الكثير منها على مئات أو (بضعة آالف) من الصور الملتقطة بدقة منخفضة‬
‫وغالبًا بخلفية نظيفة بشكل مصطنع‪.‬‬

‫في عام ‪ ،2009‬تم إصدار مجموعة بيانات ‪ ،)2009,Deng et al.( ،ImageNet‬مما يشكل‬
‫تحديا للباحثين لتعلم نماذج من مليون مثال‪ 1000 ،‬لكل منها من ‪ 1000‬فئة مميزة من الكائنات‪.‬‬
‫كانت الفئات نفسها مبنية على أكثر عُقد األسماء شيوعًايف ‪.)1995,Miller( ،WordNet‬‬
‫استخدم فريق ‪ ImageNet‬بحث الصور من ‪ Google‬للترشيح المسبق لمجموعات كبيرة من‬
‫المرشحين لكل فئة واستخدم خط أنابيب التعهيد الجماعي ‪Amazon Mechanical Turk‬‬
‫لتأكيد ما إذا كانت تنتمي إلى الفئة المرتبطة بكل صورة‪ .‬كان هذا المقياس غير مسبوق‪ ،‬متجاوزًا‬
‫اآلخرين بأكثر من ترتيب من حيث الحجم (على سبيل المثال‪ ،‬يحتوي ‪ CIFAR-100‬على‬
‫‪ 60000‬صورة)‪ .‬كان الجانب اآلخر هو أن الصور كانت بدقة عالية نسبيًا ‪ 224 × 224‬بكسل‪،‬‬
‫على عكس مجموعة بيانات ‪ TinyImages‬بحجم ‪ 80‬مليون (‪،)2008 ،Torralba et al.‬‬
‫والتي تتكون من صور مصغرة ‪ 32 × 32‬بكسل‪ .‬سمح هذا بتشكيل ميزات ذات مستوى أعلى‪.‬‬
‫دفعت المنافسة المصاحبة‪ ،‬والتي أطلق عليها اسم تحدي التعرف البصري على نطاق واسع على‬
‫‪ImageNet‬‬ ‫‪Large‬‬ ‫‪Scale‬‬ ‫‪Visual‬‬ ‫‪Recognition‬‬ ‫‪Challenge،ImageNet‬‬
‫(‪ ،)2015,Russakovsky et al.‬الرؤية الحاسوبية وأبحاث التعلم اآللي إلى األمام‪ ،‬مما أدى‬
‫إلى تحدي الباحثين لتحديد النماذج األفضل أداءً على نطاق أكبر مما كان األكاديميون يعتبرونه‬
‫سابقًا‪ .‬تحتوي أكبر مجموعات بيانات الرؤية‪ ،‬مثل ‪Schuhmann et ( ،LAION-5B‬‬
‫‪ )2022,al.‬على مليارات الصور مع بيانات وصفية إضافية‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪102‬‬

‫‪Missing Ingredient: Hardware‬‬ ‫‪8.1.1.2‬‬


‫نماذج التعلم العميق هي مستهلكين شرهين لدورات الحوسبة ‪ .compute cycles‬يمكن أن‬
‫يستغرق التدريب مئات الفترات ‪ ،epochs‬ويتطلب كل تكرار تمرير البيانات عبر طبقات عديدة‬
‫من عمليات الجبر الخطي المكلفة حسابيًا‪ .‬هذا هو أحد األسباب الرئيسية وراء تفضيل‬
‫الخوارزميات البسيطةيف التسعينيات وأوائل العقد األول من القرن الحادي والعشرين‪ ،‬بناءً على‬
‫األهداف المحدبة المحسّنة ‪ optimized convex objectives‬بشكل أكثر كفاءة‪.‬‬

‫أثبتت وحدات المعالجة الرسومية (‪ )GPUs‬أنها غيرت قواعد اللعبةيف جعل التعلم العميق‬
‫ممكنًا‪ .‬تم تطوير هذه الرقائق منذ فترة طويلة لتسريع معالجة الرسومات إلفادة ألعاب الكمبيوتر‪.‬‬
‫على وجه الخصوص‪ ،‬تم تحسينها لضرب المصفوفة‪-‬المتجه عالية ‪ ،4 × 4‬والتي تعد مطلوبة‬
‫للعديد من مهام رسومات الكمبيوتر‪ .‬لحسن الحظ‪ ،‬الرياضيات مشابهة بشكل الفت للنظر لتلك‬
‫المطلوبة لحساب الطبقات التالفيفية‪.‬يف ذلك الوقت تقريبًا‪ ،‬بدأت ‪ NVIDIA‬و‪ATI‬يف تحسين‬
‫وحدات معالجة الرسومات لعمليات الحوسبة العامة (‪ ،)2004 ،Fernando‬ووصلت إلى حد‬
‫تسويقها على أنها وحدات معالجة رسومات لألغراض العامة ‪general-purpose GPUs‬‬
‫(‪.)GPGPUs‬‬

‫لتوفير بعض الحدس‪ ،‬ضعيف اعتبارك أنوية المعالج الدقيق الحديث (‪ .)CPU‬كل من النوى قوي‬
‫إلى حد ما يعمل بتردد ساعة عالٍ وذاكرة تخزين مؤقت كبيرة (تصل إلى عدة ميغا بايت من ‪.)L3‬‬
‫كل نواة مناسبة تمامًا لتنفيذ مجموعة واسعة من التعليمات ‪ ،instructions‬مع تنبؤات الفروع‬
‫‪ ،branch predictors‬وخط أنابيب عميق ‪ ،deep pipeline‬ووحدات تنفيذ متخصصة‪،‬‬
‫وتنفيذ تخميني ‪ ،speculative execution‬والعديد من األجراس والصفارات األخرى التي‬
‫تمكنه من تشغيل مجموعة كبيرة ومتنوعة من البرامج مع تدفق تحكم متطور ‪sophisticated‬‬
‫‪ .control flow‬ومع ذلك‪ ،‬فإن هذه القوة الواضحة تكمن أيضًايف كعب أخيل‪ :‬فلبناء األغراض‬
‫العامة م كلف للغاية‪ .‬إنها تتفوقيف كود األغراض العامة مع الكثير من التحكميف التدفق‪ .‬هذا‬
‫يتطلب الكثير من مساحة الرقاقة ‪ ،chip area‬ليس فقط لوحدة الحساب والمنطق ‪arithmetic‬‬
‫‪ )ALU( logical unit‬حيث يحدث الحساب‪ ،‬ولكن أيضًا لجميع األجراس والصفارات‬
‫المذكورة أعاله‪ ،‬باإلضافة إلى واجهات الذاكرة ‪ ،memory interfaces‬ومنطق التخزين المؤقت‬
‫بين النوى ‪ ،caching logic between cores‬والوصالت عالية السرعة ‪high-speed‬‬
‫‪ ، interconnects‬وما إلى ذلك‪ .‬تعد وحدات المعالجة المركزية سيئة نسبيًايف أي مهمة واحدة‬
‫عند مقارنتها باألجهزة المخصصة‪ .‬تحتوي أجهزة الكمبيوتر المحمولة الحديثة على ‪ 8-4‬نوى‬
‫‪ ،cores‬ونادرًا ما تتجاوز الخوادم المتطورة ‪ 64‬نواة لكل مقبس ‪ ،socket‬وذلك ببساطة ألنها‬
‫ليست فعالة من حيث التكلفة‪.‬‬
‫‪103‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫وبالمقارنة‪ ،‬يمكن أن تتكون وحدات معالجة الرسومات من آالف عناصر المعالجة الصغيرة‬
‫(تحتوي أحدث رقائق ‪ Ampere‬من ‪ NIVIDA‬على ما يصل إلى ‪ 6912‬نواة ‪،)CUDA‬‬
‫وغالبًا ما يتم تجميعهايف مجموعات أكبر (تسميها ‪ NVIDIA‬االعوجاج ‪ .)warps‬تختلف‬
‫التفاصيل إلى حد ما بين ‪ NVIDIA‬و‪ AMD‬و‪ ARM‬وبائعي الرقائق اآلخرين‪.‬يف حين أن كل‬
‫نواة ضعيفة نسبيًا‪ ،‬تعمل بتردد ساعة ‪ 1‬جيجاهرتز‪ ،‬فإن العدد اإلجمالي لهذه النوى هو الذي‬
‫يجعل أوامر وحدات معالجة الرسومات من حيث الحجم أسرع من وحدات المعالجة المركزية‪.‬‬
‫على سبيل المثال‪ ،‬توفر وحدة معالجة الرسومات ‪ Ampere A100‬الحديثة من ‪NVIDIA‬‬
‫أكثر من ‪ TFLOPs 300‬لكل شريحة من أجل ضرب المصفوفة‪-‬المصفوفة متخصصة ‪ 16‬بت‬
‫(‪ ،)BFLOAT16‬وما يصل إلى ‪ TFLOPs 20‬لعمليات النقطة العائمة ذات األغراض العامة‬
‫(‪.)FP32‬يف الوقت نفسه‪ ،‬نادراً ما يتجاوز أداء النقطة العائمة لوحدات المعالجة المركزية ‪1‬‬
‫‪ .TFLOPs‬على سبيل المثال‪ ،‬يصل ‪ Graviton 3‬من ‪ Amazon‬إلى ‪ TFLOPs 2‬لعمليات‬
‫دقيقة ‪ 16‬بت‪ ،‬وهو رقم مشابه ألداء ‪ GPU‬لمعالج ‪.Apple M1‬‬

‫هناك العديد من األسباب التي تجعل وحدات معالجة الرسومات ‪ GPU‬أسرع بكثير من وحدات‬
‫المعالجة المركزية من حيث ‪ .FLOPs‬أوالً‪ ،‬يميل استهالك الطاقة إلى النمو بشكل تربيعي مع‬
‫تردد الساعة‪ .‬وبالتالي‪ ،‬بالنسبة لميزانية الطاقة لنواة وحدة المعالجة المركزية التي تعمل ‪ 4‬مرات‬
‫‪1‬‬
‫أسرع (رقم نموذجي)‪ ،‬يمكنك استخدام ‪16‬نواة لوحدة معالجة الرسوماتيف ‪ 4‬السرعة التي تنتج‬
‫‪1‬‬
‫‪16 × 4 = 4‬مرات من األداء‪ .‬ثانيًا‪ ،‬تعد نوى ‪ GPU‬أبسط بكثير (في الواقع‪ ،‬لم تكن قادرة حتى‬
‫على تنفيذ التعليمات البرمجية لألغراض العامة لفترة طويلة)‪ ،‬مما يجعلها أكثر كفاءةيف استخدام‬
‫الطاقة‪ .‬على سبيل المثال‪ )1( ،‬تميل إلى عدم دعم التقييم التخميني ‪speculative‬‬
‫‪ ) 2( ،evaluation‬عادةً ما يكون من غير الممكن برمجة كل عنصر معالجة على حدة‪ ،‬و(‪)3‬‬
‫ذاكرة التخزين المؤقت ‪ caches‬لكل نواة تميل إلى أن تكون أصغر بكثير‪ .‬أخيرًا‪ ،‬تتطلب العديد‬
‫من العملياتيف التعلم العميق نطاقًا تردديًا عاليًا للذاكرة‪ .‬مرة أخرى‪ ،‬تتألق وحدات معالجة‬
‫الرسومات هنا مع المسارات ‪ buses‬التي يبلغ عرضها على األقل ‪ 10‬أضعاف عدد وحدات‬
‫المعالجة المركزية‪.‬‬

‫بالعودة إلى عام ‪ .2012‬حدث تقدم كبير عندما نفذ ‪ Alex Krizhevsky‬و‪Ilya Sutskever‬‬
‫شبكة ‪ CNN‬عميقة يمكن تشغيلها على وحدات معالجة الرسومات‪ .‬لقد أدركوا أن االختناقات‬
‫الحسابية ‪computational bottlenecks‬يف شبكات ‪ ،CNN‬والتالفيف ومضاعفات‬
‫المصفوفات‪ ،‬كلها عمليات يمكن أن تكون متوازيةيف األجهزة‪ .‬باستخدام اثنين من ‪NVIDIA‬‬
‫‪ GTX 580s‬مع ‪ 3‬جيجابايت من الذاكرة‪ ،‬أي منهما كان قادرًا على ‪( TFLOPs 1.5‬ال يزال‬
‫يمثل تحديًا لمعظم وحدات المعالجة المركزية بعد عقد من الزمان)‪ ،‬قاموا بتنفيذ التفافات‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪104‬‬

‫سريعة‪ .‬كان كود ‪ cuda-convnet‬جيدًا بما يكفي ألنه لعدة سنوات كان معيارًا صناعيًا وعمل‬
‫على تشغيل أول عامين من طفرة التعلم العميق‪.‬‬

‫‪AlexNet 8.1.2‬‬
‫‪ ، AlexNet‬التي استخدمت شبكة ‪ CNN‬ذات ‪ 8‬طبقات ‪ ،‬فازتيف مسابقة ‪ImageNet‬‬
‫‪ Large Scale Visual Recognition Challenge 2012‬بهامش كبير ( ‪Russakovsky‬‬
‫‪ .)2013 ،et al.‬أظهرت هذه الشبكة‪ ،‬ألول مرة‪ ،‬أن الميزات التي تم الحصول عليها من خالل‬
‫التعلم يمكن أن تتجاوز الميزات المصممة يدويًا‪ ،‬مما يكسر النموذج السابقيف الرؤية الحاسوبية‪.‬‬

‫إن معماريات ‪ AlexNet‬و‪ LeNet‬متشابهة بشكل الفت للنظر‪ ،‬كما يوضح الشكل ‪.8.1.2‬‬
‫الحظ أننا نقدم نسخة مبسطة قليالً من ‪ AlexNet‬إلزالة بعض المراوغات التصميمية ‪design‬‬
‫‪ quirks‬التي كانت مطلوبةيف عام ‪ 2012‬لجعل النموذج مناسبًا لوحدتي ‪ GPU‬صغيرتين‪.‬‬

‫الشكل ‪ 8.1.2‬من ‪( LeNet‬يسار) إلى( ‪) AlexNet‬يمين)‪.‬‬


‫‪105‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫هناك أيضًا اختالفات كبيرة بين ‪ AlexNet‬و‪ .LeNet‬أوالً‪ AlexNet ،‬أعمق بكثير من‬
‫‪ LeNet5‬الصغير نسبيًا‪ .‬تتكون ‪ AlexNet‬من ثماني طبقات‪ :‬خمس طبقات تالفيفية‪ ،‬وطبقتان‬
‫مخفيتان متصلتان بالكامل‪ ،‬وطبقة إخراج متصلة بالكامل‪ .‬ثانيًا‪AlexNet ،‬تستخدم ‪ReLU‬‬
‫بدالً من ‪ sigmoid‬كدالة التنشيط‪ .‬دعنا نتعمقيف التفاصيل أدناه‪.‬‬

‫‪Architecture‬‬ ‫‪8.1.2.1‬‬
‫في الطبقة األولى لـ ‪ ،AlexNet‬يكون شكل نافذة االلتفاف ‪ convolution window‬هو‬
‫‪ .11 × 11‬نظرًا ألن الصوريف ‪ ImageNet‬أعلى بثماني مرات وأعرض من صور ‪،MNIST‬‬
‫تميل الكائنات الموجودةيف بيانات ‪ ImageNet‬إلى احتالل المزيد من وحدات البكسل بتفاصيل‬
‫مرئية أكثر‪ .‬وبالتالي‪ ،‬هناك حاجة إلى نافذة التفاف أكبر اللتقاط الكائن‪ .‬يتم تقليل شكل نافذة‬
‫االلتفافيف الطبقة الثانية إلى ‪ ،5 × 5‬متبوعًا بـ ‪ .3 × 3‬باإلضافة إلى ذلك‪ ،‬بعد الطبقات‬
‫التالفيفية األولى والثانية والخامسة‪ ،‬تضيف الشبكة طبقات تجميع حد اقصى مع شكل نافذة‬
‫‪ 3 × 3‬وخطوة ‪ .2‬عالوة على ذلك‪ ،‬تمتلك ‪ AlexNet‬قنوات التفاف أكثر بعشر مرات من‬
‫‪.LeNet‬‬

‫بعد آخر طبقة تالفيفية‪ ،‬توجد طبقتان كبيرتان متصلتان بالكامل مع ‪ 4096‬ناتجًا‪ .‬تتطلب هذه‬
‫الطبقات معلمات نموذج ‪ 1‬جيجابايت تقريبًا‪ .‬نظرًا للذاكرة المحدودةيف وحدات معالجة‬
‫الرسومات المبكرة‪ ،‬استخدم ‪ AlexNet‬األصلي تصميمًا مزدوجًا لدفق البيانات‪ ،‬بحيث يمكن‬
‫أن تكون كل واحدة من وحدتي ‪ GPU‬مسؤولة عن تخزين وحساب نصف النموذج فقط‪ .‬لحسن‬
‫الحظ‪ ،‬أصبحت ذاكرة ‪ GPU‬وفيرة نسبيًا اآلن‪ ،‬لذلك نادرًا ما نحتاج إلى تفكيك النماذج عبر‬
‫وحدات معالجة الرسومات هذه األيام (إصدارنا من طراز ‪ AlexNet‬ينحرف عن الورقة األصلية‬
‫في هذا الجانب)‪.‬‬

‫‪Activation Functions‬‬ ‫‪8.1.2.2‬‬


‫إلى جانب ذلك‪ ،‬قامت ‪ AlexNet‬بتغيير دالة التنشيط ‪ sigmoid‬إلى دالة تنشيط ‪ ReLU‬أبسط‪.‬‬
‫من ناحية أخرى‪ ،‬يعد حساب دالة تنشيط ‪ ReLU‬أبسط‪ .‬على سبيل المثال‪ ،‬ال يحتوي على‬
‫عملية االُس الموجودةيف دالة التنشيط ‪ .sigmoid‬من ناحية أخرى‪ ،‬تجعل دالة التنشيط ‪ReLU‬‬
‫تدريب النموذج أسهل عند استخدام طرق تهيئة مختلفة للمعلمات‪ .‬هذا ألنه‪ ،‬عندما يكون ناتج‬
‫دالة التنشيط ‪ sigmoid‬قريبًا جدًا من ‪ 0‬أو ‪ ،1‬يكون التدرج ‪ gradient‬لهذه المناطق تقريبًا ‪،0‬‬
‫لذلك ال يمكن أن يستمر االنتشار الخلفي ‪backpropagation‬يف تحديث بعض معلمات‬
‫النموذج‪.‬يف المقابل‪ ،‬يكون التدرج لدالة تنشيط ‪ReLU‬يف الفاصل الزمني الموجب ‪positive‬‬
‫‪ interval‬دائمًا ‪( 1‬القسم ‪ .)5.1.2‬لذلك‪ ،‬إذا لم تتم تهيئة معلمات النموذج بشكل صحيح‪ ،‬فقد‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 106

‫ بحيث ال يمكن‬،‫ تقريبًايف الفاصل الزمني الموجب‬0 ‫ على تدرج يبلغ‬sigmoid ‫تحصل الدالة‬
.‫تدريب النموذج بشكل فعال‬

Capacity Control and 8.1.2.3


Preprocessing
‫يف تعقيد نموذج الطبقة المتصلة بالكامل عن طريق التسرب (الحذف‬AlexNet ‫تتحكم‬
weight ‫ سوى انحالل الوزن‬LeNet ‫ بينما ال تستخدم‬،)5.6 ‫ (القسم‬dropout )‫العشوائي‬
AlexNet ‫ أضافت حلقة التدريب الخاصة بـ‬،‫ البيانات بشكل أكبر‬augment ‫ لزيادة‬.decay
color ‫ وتغيير اللون‬clipping ‫ والقص‬flipping ‫ مثل التقليب‬،‫قدرًا كبيرًا من تكبير الصورة‬
‫ هذا يجعل النموذج أكثر قوة ويقلل حجم العينة األكبر بشكل فعال من الضبط الزائد‬.changes
‫ بمزيد من التفصيليف القسم‬data augmentation ‫ سنناقش زيادة البيانات‬.overfitting
‫) للحصول على مراجعة متعمقة لخطوات المعالجة‬2020 ،Buslaev et al.( ‫ انظر أيضًا‬.14.1
.‫ هذه‬preprocessing ‫المسبقة‬

import tensorflow as tf
from d2l import tensorflow as d2l

class AlexNet(d2l.Classifier):
def __init__(self, lr=0.1, num_classes=10):
super().__init__()
self.save_hyperparameters()
self.net = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=96,
kernel_size=11, strides=4,
activation='relu'),
tf.keras.layers.MaxPool2D(pool_size=3,
strides=2),
tf.keras.layers.Conv2D(filters=256,
kernel_size=5, padding='same',
activation='relu'),
tf.keras.layers.MaxPool2D(pool_size=3,
strides=2),
tf.keras.layers.Conv2D(filters=384,
kernel_size=3, padding='same',
activation='relu'),
tf.keras.layers.Conv2D(filters=384,
kernel_size=3, padding='same',
activation='relu'),
107 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

tf.keras.layers.Conv2D(filters=256,
kernel_size=3, padding='same',
activation='relu'),
tf.keras.layers.MaxPool2D(pool_size=3,
strides=2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(4096,
activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(4096,
activation='relu'),
tf.keras.layers.Dropout(0.5),
tf.keras.layers.Dense(num_classes)])
‫ لمالحظة‬224 ‫ بارتفاع وعرض‬single-channel data ‫نقوم ببناء مثال بيانات أحادية القناة‬
.8.1.2 ‫يف الشكل‬AlexNet ‫ إنها تتطابق مع بنية‬.‫شكل اإلخراج لكل طبقة‬

AlexNet().layer_summary((1, 224, 224, 1))


Conv2D output shape: (1, 54, 54, 96)
MaxPooling2D output shape: (1, 26, 26, 96)
Conv2D output shape: (1, 26, 26, 256)
MaxPooling2D output shape: (1, 12, 12, 256)
Conv2D output shape: (1, 12, 12, 384)
Conv2D output shape: (1, 12, 12, 384)
Conv2D output shape: (1, 12, 12, 256)
MaxPooling2D output shape: (1, 5, 5, 256)
Flatten output shape: (1, 6400)
Dense output shape: (1, 4096)
Dropout output shape: (1, 4096)
Dense output shape: (1, 4096)
Dropout output shape: (1, 4096)
Dense output shape: (1, 10)
Training 8.1.3
‫ فإننا‬،)2012 ،Krizhevsky et al.( ‫يف‬ImageNet ‫ على‬AlexNet ‫على الرغم من تدريب‬
‫ على التقارب‬ImageNet ‫ هنا نظرًا ألن تدريب نموذج‬Fashion-MNIST ‫نستخدم‬
‫ تتمثل‬.‫ قد يستغرق ساعات أو أيام حتى على وحدة معالجة الرسومات الحديثة‬convergence
‫يف أن صورها ذات دقة‬Fashion-MNIST ‫ مباشرة على‬AlexNet ‫إحدى مشكالت تطبيق‬
‫ نقوم بتجميعها الى‬،‫ لجعل األشياء تعمل‬.ImageNet ‫ بكسل) من صور‬28 × 28( ‫أقل‬
‫ ألنها ببساطة تزيد من التعقيد الحسابي دون‬،‫ هذه ليست ممارسة ذكية بشكل عام‬.224 × 224
‫ نقوم‬.AlexNet ‫ فإننا نفعل ذلك هنا لنكون مخلصين لمعمارية‬،‫ ومع ذلك‬.‫إضافة معلومات‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪108‬‬

‫‪resize‬هذا باستخدام وسيطة تغيير الحجميف مُنشئ‬ ‫بإجراء تغيير الحجم‬


‫‪.d2l.FashionMNIST‬‬

‫اآلن‪ ،‬يمكننا البدءيف تدريب ‪ .AlexNet‬بالمقارنة مع ‪LeNet‬يف القسم ‪ ،7.6‬فإن التغيير الرئيسي‬
‫هنا هو استخدام معدل تعليمي أصغر وتدريب أبطأ بكثير بسبب الشبكة األعمق واألوسع‪ ،‬ودقة‬
‫الصورة األعلى‪ ،‬والتالفيف األكثر تكلفة‪.‬‬

‫)‪trainer = d2l.Trainer(max_epochs=10‬‬
‫‪data = d2l.FashionMNIST(batch_size=128, resize=(224,‬‬
‫))‪224‬‬
‫‪with d2l.try_gpu():‬‬
‫)‪model = AlexNet(lr=0.01‬‬
‫)‪trainer.fit(model, data‬‬

‫‪8.1.4‬‬
‫يحمل هيكل ‪ AlexNet‬تشابهًا مذهالً مع ‪ ،LeNet‬مع عدد من التحسينات المهمة‪ ،‬من حيث‬
‫الدقة (‪ )dropout‬وسهولة التدريب (‪ .)ReLU‬األمر المذهل بنفس القدر هو مقدار التقدم‬
‫الذي تم إحرازه فيما يتعلق بأدوات التعلم العميق‪ .‬ما كان لعدة أشهر من العمليف عام ‪2012‬‬
‫يمكن اآلن إنجازهيف عشرات األسطر من التعليمات البرمجية باستخدام أي إطار عمل حديث‪.‬‬

‫بمراجعة المعمارية‪ ،‬نرى أن ‪ AlexNet‬لديها كعب أخيل عندما يتعلق األمر بالكفاءة‪ :‬تتطلب‬
‫آخر طبقتين مخفيتين مصفوفات من الحجم ‪ 6400 × 4096‬و‪ 4096 × 4096‬على التوالي‪.‬‬
‫هذا يتوافق مع ذاكرة ‪ 164‬ميجابايت و‪ MFLOPs 81‬من الحسابات‪ ،‬وكالهما نفقات غير‬
‫‪109‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫بديهية‪ ،‬خاصة على األجهزة األصغر‪ ،‬مثل الهواتف المحمولة‪ .‬هذا هو أحد أسباب تجاوز‬
‫‪ AlexNet‬لهياكل أكثر فاعلية سنغطيهايف األقسام التالية‪ .‬ومع ذلك‪ ،‬فهي خطوة أساسية من‬
‫الشبكات الضحلة إلى الشبكات العميقة المستخدمةيف الوقت الحاضر‪ .‬الحظ أنه على الرغم من‬
‫أن عدد المعلمات يتجاوز إلى حد بعيد كمية بيانات التدريبيف تجاربنا (تحتوي الطبقتان‬
‫األخيرتان على أكثر من ‪ 40‬مليون معلمة‪ ،‬تم تدريبهما على مجموعات بيانات من ‪ 60‬ألف‬
‫صورة)‪ ،‬ال يكاد يوجد أي ضبط زائد ‪ :overfitting‬خطأ التدريب والتحقق من الصحة متطابقة‬
‫تقريبًا خالل التدريب‪ .‬ويرجع ذلك إلى التنظيم المحسن‪ ،‬مثل ‪ dropout‬المتأصليف تصميمات‬
‫الشبكات العميقة الحديثة‪.‬‬

‫على الرغم من أنه يبدو أن هناك عددًا قليالً فقط من الخطوطيف تطبيق ‪ AlexNet‬مقارنةً بتطبيق‬
‫‪ ،LeNet‬فقد استغرق المجتمع األكاديمي سنوات عديدة الحتضان هذا التغيير المفاهيمي‬
‫واالستفادة من نتائجه التجريبية الممتازة‪ .‬كان هذا أيضًا بسبب عدم وجود أدوات حسابية فعالة‪.‬‬
‫في ذلك الوقت‪ ،‬لم يكن ‪ )2012,Dean et al.( ،DistBelief‬وال ‪)2014,Jia et al.( ،Caffe‬‬
‫موجودًا‪ ،‬وال يزال ‪ )2010,Bergstra et al.( ،Theano‬يفتقر إلى العديد من الميزات المميزة‪.‬‬
‫إن توفر ‪ )2016,Abadi et al.( ،TensorFlow‬هو الوحيد الذي غير هذا الوضع بشكل كبير‪.‬‬

‫‪8.1.5‬‬
‫‪ .1‬لمتابعة المناقشة أعاله‪ ،‬قم بتحليل الخصائص الحسابية لـ ‪.AlexNet‬‬
‫‪ .1‬احسب بصمة الذاكرة للتالفيف والطبقات المتصلة بالكامل‪ ،‬على التوالي‪ .‬أي‬
‫واحد يهيمن؟‬
‫‪ .2‬احسب التكلفة الحسابية لاللتفافات والطبقات المتصلة بالكامل‪.‬‬
‫‪ .3‬كيف تؤثر الذاكرة (عرض النطاق الترددي ‪ bandwidth‬للقراءة والكتابة‬
‫ووقت التاخير ‪ latency‬والحجم) على الحساب؟ وهل هناك فرقيف تأثيره على‬
‫التدريب واالستدالل؟‬
‫‪ .2‬أنت مصمم شريحة ‪ chip designer‬وتحتاج إلى موازنة الحساب وعرض النطاق‬
‫الترددي للذاكرة‪ .‬على سبيل المثال‪ ،‬تتطلب الشريحة األسرع طاقة أكبر وربما مساحة‬
‫شريحة أكبر‪ .‬يتطلب المزيد من عرض النطاق الترددي للذاكرة المزيد من ‪ pins‬ومنطق‬
‫التحكم ‪ ،control logic‬وبالتالي مساحة أكبر أيضًا‪ .‬كيف تقوم بالتحسين؟‬
‫‪ .3‬لماذا لم يعد المهندسون يقدمون تقارير عن معايير األداء على ‪AlexNet‬؟‬
‫‪ .4‬حاول زيادة عدد الفترات عند تدريب ‪ .AlexNet‬مقارنة مع ‪ ،LeNet‬كيف تختلف‬
‫النتائج؟ لماذا؟‬
‫‪ .5‬قد تكون ‪ AlexNet‬معقدة للغاية بالنسبة لمجموعة بيانات ‪،Fashion-MNIST‬‬
‫خاصة بسبب الدقة المنخفضة للصور األولية‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪110‬‬

‫‪ .1‬حاول تبسيط النموذج لجعل التدريب أسرع‪ ،‬مع ضمان عدم انخفاض الدقة‬
‫بشكل ملحوظ‪.‬‬
‫‪ .2‬قم بتعديل حجم الدُفعة ‪ ،batch size‬والحظ التغييراتيف اإلنتاجية‬
‫‪( throughput‬الصور‪/‬الثانية) والدقة وذاكرة وحدة معالجة الرسومات‪.‬‬
‫‪ .6‬طبق التسرب ‪ dropout‬و‪ ReLU‬على ‪ .LeNet-5‬هل تتحسن؟ هل يمكنك‬
‫تحسين األمور أكثر من خالل المعالجة المسبقة لالستفادة من الثوابت ‪invariances‬‬
‫الكامنةيف الصور؟‬
‫‪ .7‬هل يمكنك جعل ‪ AlexNet‬تعاني من الضبط الزائد ‪overfitting‬؟ ما الميزة التي‬
‫تحتاج إلى إزالتها أو تغييرها لكسر التدريب؟‬

‫‪Networks Using Blocks VGG‬‬ ‫‪8.2‬‬


‫بينما قدمت ‪ AlexNet‬دليلًا تجريبيًا على أن شبكات ‪ CNN‬العميقة يمكنها تحقيق نتائج‬
‫جيدة‪ ،‬إال أنها لم تقدم نموذجًا عامًا لتوجيه الباحثين الالحقينيف تصميم شبكات جديدة‪.‬يف ‬
‫األقسام التالية‪ ،‬سوف نقدم عدة مفاهيم إرشادية ‪ heuristic concepts‬شائعة االستخدام‬
‫لتصميم شبكات عميقة‪.‬‬

‫يعكس التقدميف هذا المجال تقدم ‪( VLSI‬تكامل واسع النطاق جدًا ‪very large scale‬‬
‫‪) integration‬يف تصميم الرقائق حيث انتقل المهندسون من وضع الترانزستورات إلى العناصر‬
‫المنطقية ‪ logical elements‬إلى الكتل المنطقية ‪ .)1980 ،Mead( logic blocks‬وبالمثل‪،‬‬
‫فإن تصميم معماريات الشبكات العصبية قد أصبح أكثر تجريدًا بشكل تدريجي‪ ،‬مع انتقال‬
‫الباحثين من التفكير من حيث الخاليا العصبية الفردية إلى طبقات كاملة‪ ،‬واآلن إلى الكتل‬
‫‪ ،blocks‬وتكرار أنماط الطبقات‪ .‬بعد عقد من الزمان‪ ،‬تقدم هذا اآلن للباحثين الذين يستخدمون‬
‫نماذج مدربة بالكامل إلعادة توظيفهم لمهام مختلفة‪ ،‬وإن كانت مرتبطة‪ .‬عادة ما تسمى هذه‬
‫النماذج الكبيرة التي تم اختبارها مسبقًا بنماذج األساس ‪foundation models‬‬
‫(‪.)2021 ،Bommasani et al.‬‬

‫العودة إلى تصميم الشبكة‪ .‬ظهرت فكرة استخدام الكتل ألول مرة من مجموعة الهندسة المرئية‬
‫‪)VGG( Visual Geometry Group‬يف جامعة أكسفورد‪،‬يف شبكة ‪ VGG‬التي تحمل االسم‬
‫نفسه (‪ .)2014 ،Simonyan and Zisserman‬من السهل تنفيذ هذه الهياكل المتكررةيف ‬
‫الكود مع أي إطار عمل تعلم عميق حديث باستخدام الحلقات والروتينات الفرعية‪.‬‬

‫‪VGG‬‬ ‫‪8.2.1‬‬
‫كتلة البناء األساسية لشبكات ‪ CNN‬هي سلسلة مما يلي‪ )1( :‬طبقة تالفيفية مع حشوة للحفاظ‬
‫على الدقة‪ )2( ،‬غير خطية مثل ‪ )3( ،ReLU‬طبقة تجميع مثل ‪ max-pooling‬لتقليل الدقة‪.‬‬
‫‪111‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫تتمثل إحدى مشكالت هذا النهجيف أن الدقة المكانية تتناقص بسرعة كبيرة‪ .‬على وجه الخصوص‪،‬‬
‫يفرض هذا حدًا صارمًا للطبقات التالفيفية 𝑑 ‪ log 2‬على الشبكة قبل استخدام جميع األبعاد‬
‫(𝑑)‪ .‬على سبيل المثال‪،‬يف حالة ‪ ،ImageNet‬سيكون من المستحيل وجود أكثر من ‪ 8‬طبقات‬
‫تالفيفية بهذه الطريقة‪.‬‬

‫كانت الفكرة الرئيسية لـ ‪ Simonyan‬و‪ )2014( Zisserman‬هي استخدام تالفيف متعددة‬


‫بين االختزال ‪ downsampling‬عبر تجميع الحد األقصى ‪max-pooling‬يف شكل كتلة‪ .‬كانوا‬
‫مهتمينيف المقام األول بما إذا كانت الشبكات العميقة أو الواسعة تعمل بشكل أفضل‪ .‬على سبيل‬
‫المثال‪ ،‬يالمس التطبيق المتتابع لتالفيفين ‪ 3 × 3‬نفس وحدات البكسل ‪ 5 × 5‬كما يفعل‬
‫التفاف واحد‪.‬يف نفس الوقت‪ ،‬يستخدم األخير تقريبًا العديد من المعلمات ( ‪ )25 ⋅ 𝑐 2‬كما تفعل‬
‫ثالثة تالفيف (‪.)3 ⋅ 9 ⋅ 𝑐 2‬يف تحليل مفصل إلى حد ما‪ ،‬أظهروا أن الشبكات العميقة والضيقة‬
‫تتفوق بشكل كبير على نظيراتها الضحلة‪ .‬وضع هذا التعلم العميقيف البحث عن شبكات أعمق‬
‫من أي وقت مضى مع أكثر من ‪ 100‬طبقة للتطبيقات النموذجية‪ .‬أصبح تراص التالفيف ‪3 × 3‬‬
‫معي ارًا ذهبيًايف الشبكات العميقة الالحقة (قرار تصميم تمت إعادة النظر فيه مؤخرًا بواسطة ( ‪Liu‬‬
‫‪ .)2022,et al.‬وبالتالي‪ ،‬أصبحت عمليات التنفيذ السريعة للتالفيف الصغيرة عنصرًا أساسيًايف ‬
‫وحدات معالجة الرسومات (‪.)2016 ،Lavin and Gray‬‬

‫العودة إلى ‪ :VGG‬تتكون كتلة ‪ VGG‬من سلسلة من التالفيف ‪sequence of convolutions‬‬


‫مع ‪ 3 × 3‬قنوات مع حشوة من ‪( 1‬الحفاظ على االرتفاع والعرض) متبوعة بطبقة تجميع حد‬
‫أقصى بخطوة ‪( 2‬نصف ارتفاع وعرض بعد كل كتلة)‪.‬يف الكود أدناه‪ ،‬نحدد دالة تسمى‬
‫‪ vgg_block‬لتنفيذ كتلة ‪ VGG‬واحدة‪.‬‬

‫تأخذ الدالة أدناه وسيطتين ‪ ،arguments‬تقابالن عدد الطبقات التالفيفية ‪ num_convs‬وعدد‬


‫قنوات اإلخراج ‪.num_channels‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪def vgg_block(num_convs, num_channels):‬‬


‫)(‪blk = tf.keras.models.Sequential‬‬
‫‪for _ in range(num_convs):‬‬
‫(‪blk.add‬‬
‫‪tf.keras.layers.Conv2D(num_channels,‬‬
‫‪kernel_size=3,‬‬
‫‪padding='same',‬‬
‫))'‪activation='relu‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪112‬‬

‫‪blk.add(tf.keras.layers.MaxPool2D(pool_size=2,‬‬
‫))‪strides=2‬‬
‫‪return blk‬‬
‫‪VGG‬‬ ‫‪8.2.2‬‬
‫مثل ‪ AlexNet‬و‪ ،LeNet‬يمكن تقسيم شبكة ‪ VGG‬إلى جزأين‪ :‬األول يتكونيف الغالب من‬
‫طبقات تالفيفية ‪ convolutional‬وتجميعية ‪ pooling‬والثاني يتكون من طبقات متصلة‬
‫بالكامل مماثلة لتلك الموجودةيف ‪ .AlexNet‬يتمثل االختالف الرئيسييف أن الطبقات التالفيفية‬
‫يتم تجميعهايف تحويالت غير خطية تترك األبعاد دون تغيير‪ ،‬متبوعة بخطوة تقليل الدقة‬
‫‪ ،resolution-reduction step‬كما هو موضحيف الشكل ‪.8.2.1‬‬

‫الشكل‪ 8.2.1 .‬من ‪ AlexNet‬إلى ‪ .VGG‬الفرق الرئيسي هو أن ‪ VGG‬يتكون من كتل من‬


‫الطبقات‪،‬يف حين أن طبقات ‪ AlexNet‬مصممة بشكل فردي‪.‬‬

‫يربط الجزء التالفيفي من الشبكة عدة كتل ‪ VGG‬من الشكل ‪( 8.2.1‬كما هو محدديف دالة‬
‫‪ ) vgg_block‬على التوالي‪ .‬هذا التجمع من االلتفافات هو نمط ظل دون تغيير تقريبًا خالل‬
‫العقد الماضي‪ ،‬على الرغم من أن االختيار المحدد للعمليات قد خضع لتعديالت كبيرة‪ .‬يتكون‬
‫‪113‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫المتغير ‪ conv_arch‬من قائمة من المجموعات (واحدة لكل كتلة)‪ ،‬حيث تحتوي كل منها‬
‫على قيمتين‪ :‬عدد الطبقات التالفيفية وعدد قنوات المخرجات‪ ،‬وهما على وجه التحديد‬
‫الوسيطات المطلوبة الستدعاء دالة ‪ .vgg_block‬على هذا النحو‪ ،‬تحدد ‪ VGG‬عائلة من‬
‫الشبكات وليس مجرد مظهر محدد‪ .‬لبناء شبكة محددة‪ ،‬نقوم ببساطة بالتكرار عبر القوس ‪arch‬‬
‫لتكوين الكتل‪.‬‬

‫‪class VGG(d2l.Classifier):‬‬
‫‪def __init__(self, arch, lr=0.1, num_classes=10):‬‬
‫)(__‪super().__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫)(‪self.net = tf.keras.models.Sequential‬‬
‫‪for (num_convs, num_channels) in arch:‬‬
‫‪self.net.add(vgg_block(num_convs,‬‬
‫))‪num_channels‬‬
‫(‪self.net.add‬‬
‫[(‪tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Flatten(),‬‬
‫‪tf.keras.layers.Dense(4096,‬‬
‫‪activation='relu'),‬‬
‫‪tf.keras.layers.Dropout(0.5),‬‬
‫‪tf.keras.layers.Dense(4096,‬‬
‫‪activation='relu'),‬‬
‫‪tf.keras.layers.Dropout(0.5),‬‬
‫))])‪tf.keras.layers.Dense(num_classes‬‬
‫تحتوي شبكة ‪ VGG‬األصلية على ‪ 5‬كتل تالفيفية‪ ،‬من بينها الكتل التالفيفية األولى والثانية‬
‫تحتوي على طبقة تالفيفية واحدة لكل منها‪ ،‬وتحتوي الثالثة األخيرة على طبقتين تالفيفيتين لكل‬
‫منهما‪ .‬تحتوي الكتلة األولى على ‪ 64‬قناة إخراج وتضاعف كل كتلة الحقة عدد قنوات اإلخراج‪،‬‬
‫حتى يصل هذا الرقم إلى ‪ .512‬نظرًا ألن هذه الشبكة تستخدم ‪ 8‬طبقات تالفيفية و‪ 3‬طبقات‬
‫متصلة بالكامل‪ ،‬فإنها غالبًا ما تسمى ‪.VGG-11‬‬

‫‪VGG(arch=((1, 64), (1, 128),‬‬ ‫‪(2, 256), (2, 512), (2,‬‬


‫(‪512))).layer_summary‬‬
‫))‪(1, 224, 224, 1‬‬
‫‪Sequential output shape:‬‬ ‫‪(1,‬‬ ‫)‪112, 112, 64‬‬
‫‪Sequential output shape:‬‬ ‫‪(1,‬‬ ‫)‪56, 56, 128‬‬
‫‪Sequential output shape:‬‬ ‫‪(1,‬‬ ‫)‪28, 28, 256‬‬
‫‪Sequential output shape:‬‬ ‫‪(1,‬‬ ‫)‪14, 14, 512‬‬
‫‪Sequential output shape:‬‬ ‫‪(1,‬‬ ‫)‪7, 7, 512‬‬
‫‪Sequential output shape:‬‬ ‫‪(1,‬‬ ‫)‪10‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪114‬‬

‫كما ترون‪ ،‬نقوم بتخفيض االرتفاع والعرض إلى النصفيف كل كتلة‪ ،‬ونصل أخيرًا إلى ارتفاع‬
‫وعرض ‪ 7‬قبل تسطيح التمثيالت للمعالجة بواسطة الجزء المتصل بالكامل من الشبكة‪ .‬وصف‬
‫‪ Simonyan‬و‪ )2014( Zisserman‬العديد من المتغيرات األخرى لـ ‪.VGG‬يف الواقع‪ ،‬أصبح‬
‫من المعتاد اقتراح مجموعات شبكات ذات موازنات سرعة ودقة مختلفة عند تقديم بُنية جديدة‪.‬‬

‫‪Training‬‬ ‫‪8.2.3‬‬
‫نظرًا ألن ‪ VGG-11‬أكثر تطلبًا من الناحية الحسابية من ‪ ،AlexNet‬فإننا نبني شبكة مع عدد‬
‫أقل من القنوات‪ .‬هذا أكثر من كافٍ للتدريب على ‪ .Fashion-MNIST‬عملية التدريب‬
‫النموذجية مماثلة لتلك الخاصة بـ ‪AlexNet‬يف القسم ‪ .8.1‬الحظ مرة أخرى التطابق الوثيق بين‬
‫خطأ التحقق من الصحة وخطأ التدريب‪ ،‬مما يشير إلى كمية صغيرة فقط من الضبط الزائد‪.‬‬

‫)‪trainer = d2l.Trainer(max_epochs=10‬‬
‫‪data = d2l.FashionMNIST(batch_size=128, resize=(224,‬‬
‫))‪224‬‬
‫‪with d2l.try_gpu():‬‬
‫‪model = VGG(arch=((1, 16), (1, 32), (2, 64), (2,‬‬
‫)‪128), (2, 128)), lr=0.01‬‬
‫)‪trainer.fit(model, data‬‬

‫‪8.2.4‬‬
‫قد يجادل المرء بأن ‪ VGG‬هي أول شبكة عصبية تالفيفية حديثة حقًا‪ .‬بينما قدمت ‪AlexNet‬‬
‫العديد من المكونات التي تجعل التعلم العميق فعالًا على نطاق واسع‪ ،‬يمكن القول إن ‪VGG‬‬
‫هي التي قدمت الخصائص الرئيسية مثل كتل التالفيف المتعددة وتفضيل الشبكات العميقة‬
‫‪115‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫والضيقة‪ .‬إنها أيضًا الشبكة األولى التي هييف الواقع عائلة كاملة من النماذج ذات المعلمات‬
‫المتشابهة‪ ،‬مما يمنح الممارس موازنة كبيرة بين التعقيد والسرعة‪ .‬هذا أيضًا هو المكان الذي تتألق‬
‫فيه أطر التعلم العميق الحديثة‪ .‬لم يعد من الضروري إنشاء ملفات تكوين ‪ XML‬لتحديد الشبكة‪،‬‬
‫ولكن بدالً من ذلك‪ ،‬لتجميع الشبكات المذكورة من خالل كود بايثون البسيط‪.‬‬

‫أظهر ‪ ParNet‬مؤخرًا (‪ ) 2021 ،Goyal et al.‬أنه من الممكن تحقيق أداء تنافسي باستخدام‬
‫بُ نية ضحلة أكثر من خالل عدد كبير من الحسابات المتوازية‪ .‬هذا تطور مثير وهناك أمليف أن يؤثر‬
‫على تصاميم المعماريةيف المستقبل‪ .‬ومع ذلك‪ ،‬بالنسبة لبقية الفصل‪ ،‬سنتبع مسار التقدم العلمي‬
‫على مدى العقد الماضي‪.‬‬

‫‪8.2.5‬‬
‫‪ .1‬مقارنةً بـ ‪ ،AlexNet‬يُعد ‪ VGG‬أبطأ بكثير من حيث الحساب‪ ،‬كما أنه يحتاج إلى‬
‫المزيد من ذاكرة ‪.GPU‬‬
‫‪ .1‬قارن عدد المعلمات المطلوبة لـ ‪ AlexNet‬و‪.VGG‬‬
‫‪ .2‬قارن عدد عمليات الفاصلة العائمة المستخدمةيف الطبقات التالفيفية والطبقات‬
‫المتصلة بالكامل‪.‬‬
‫‪ .3‬كيف يمكنك تقليل التكلفة الحسابية التي أنشأتها الطبقات المتصلة بالكامل؟‬
‫‪ .4‬عند عرض األبعاد المرتبطة بالطبقات المختلفة للشبكة‪ ،‬ال نرى سوى المعلومات‬
‫المرتبطة بـ ‪ 8‬كتل (باإلضافة إلى بعض التحويالت المساعدة)‪ ،‬على الرغم من أن‬
‫الشبكة بها ‪ 11‬طبقة‪ .‬أين ذهبت الطبقات الثالث المتبقية؟‬
‫‪ .5‬استخدم الجدول ‪1‬يف مقالة ‪)2014,Simonyan and Zisserman( ،VGG‬‬
‫إلنشاء نماذج شائعة أخرى ‪ ،‬مثل ‪ VGG-16‬أو ‪.VGG-19‬‬
‫‪ .6‬يعد اختزال ‪ Upsampling‬الدقةيف ‪ Fashion-MNIST‬بعامل من ‪ 8‬إلى ‪28 × 28‬‬
‫أبعاد مضيعة للغاية‪ .‬حاول تعديل بُنية الشبكة وتحويل الدقة‪ ،‬على سبيل المثال‪ ،‬إلى‬
‫‪ 56‬أو ‪ 84‬بعدًا إلدخالها بدالً من ذلك‪ .‬هل يمكنك القيام بذلك دون التقليل من دقة‬
‫الشبكة؟ ضعيف اعتبارك ورقة ‪)2014,Simonyan and Zisserman( ،VGG‬‬
‫للحصول على أفكار حول إضافة المزيد من العناصر الالخطية قبل االختزال‬
‫‪.downsampling‬‬

‫‪Network in Network NiN‬‬ ‫‪8.3‬‬


‫تشترك ‪ LeNet‬و‪ AlexNet‬و‪ VGG‬جميعًايف نمط تصميم مشترك‪ :‬استخراج الميزات‬
‫‪ extract features‬التي تستغل ال ُبنية المكانية ‪ spatial structure‬عبر سلسلة من التالفيف‬
‫وطبقات التجميع ومعالجة التمثيالت بعد ذلك عبر طبقات متصلة بالكامل‪ .‬تكمن التحسينات‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪116‬‬

‫التي أدخلت على ‪ LeNet‬بواسطة ‪ AlexNet‬و‪ VGG‬بشكل أساسييف كيفية توسيع هذه‬
‫الشبكات الالحقة وتعميق هاتين الوحدتين‪.‬‬

‫يطرح هذا التصميم تحديين رئيسيين‪ .‬أوالً‪ ،‬تستهلك الطبقات المتصلة بالكامليف نهاية الهيكل‬
‫عددًا هائالً من المعلمات‪ .‬على سبيل المثال‪ ،‬حتى نموذج بسيط مثل ‪ VGG-11‬يتطلب‬
‫مصفوفة ضخمة ‪ ،25088 × 4096‬تشغل ما يقرب من ‪ 400‬ميجابايت من ذاكرة الوصول‬
‫العشوائي بدقة واحدة (‪ .)FP32‬هذا عائق كبير أمام الحساب‪ ،‬ال سيما على األجهزة المحمولة‬
‫والمضمنة‪ .‬بعد كل شيء‪ ،‬حتى الهواتف المحمولة المتطورة ال تحتوي على أكثر من ‪ 8‬جيجابايت‬
‫من ذاكرة الوصول العشوائي‪.‬يف الوقت الذي تم فيه اختراع ‪ ،VGG‬كان هذا ترتيبًا أقل من حيث‬
‫الحجم (كان لدى ايفون ‪ 512 4S‬ميجا بايت)‪ .‬على هذا النحو‪ ،‬كان من الصعب تبرير إنفاق‬
‫غالبية الذاكرة على مصنف الصور‪.‬‬

‫ثانيًا‪ ،‬من المستحيل أيضًا إضافة طبقات متصلة بالكامليف وقت سابقيف الشبكة لزيادة درجة‬
‫الالخطية‪ :‬سيؤدي القيام بذلك إلى تدمير البنية المكانية وقد يتطلب المزيد من الذاكرة‪.‬‬

‫تقدم كتل الشبكةيف الشبكة ‪ )2013,Lin et al.( ،(NiN) network in network‬بديالً‬


‫قادرًا على حل كلتا المشكلتينيف إستراتيجية واحدة بسيطة‪ .‬تم اقتراحها بناءً على نظرة ثاقبة بسيطة‬
‫للغاية‪ )1( :‬استخدام التالفيف ‪ 1 × 1‬إلضافة عناصر غير خطية محلية عبر عمليات تنشيط القناة‬
‫و(‪ )2‬استخدام متوسط التجميع العالمي ‪ global average pooling‬للتكامل عبر جميع‬
‫المواقعيف طبقة التمثيل األخيرة‪ .‬الحظ أن متوسط التجميع العالمي لن يكون فعاالً‪ ،‬لوال الالخطية‬
‫المضافة‪ .‬دعونا نتعمقيف هذا بالتفصيل‪.‬‬

‫‪NiN‬‬ ‫‪8.3.1‬‬
‫راجع القسم ‪ .7.4.3‬الذي ناقشنا فيه أن مدخالت ومخرجات الطبقات التالفيفية تتكون من موتر‬
‫رباعي األبعاد مع محاور مقابلة للمثال والقناة واالرتفاع والعرض‪ .‬تذكر أيضًا أن مدخالت‬
‫ومخرجات الطبقات المتصلة بالكامل تكون عادةً موترات ثنائية األبعاد تتوافق مع المثال والميزة‪.‬‬
‫الفكرة وراء ‪ NiN‬هي تطبيق طبقة متصلة بالكامليف كل موقع بكسل (لكل ارتفاع وعرض)‪.‬‬
‫يمكن اعتبار االلتفاف الناتج على أنه طبقة متصلة بالكامل تعمل بشكل مستقل على كل موقع‬
‫بكسل‪.‬‬

‫يوضح الشكل ‪ 8.3.1‬االختالفات الهيكلية الرئيسية بين ‪ VGG‬و‪ NiN‬وكتلهما‪ .‬الحظ كالً من‬
‫االختالفيف كتل ‪( NiN‬االلتفاف األولي يتبعه التالفيف ‪ ،1 × 1‬بينما يحتفظ ‪ VGG‬بالتالفيف‬
‫‪ ) 3 × 3‬وفي النهاية حيث لم نعد بحاجة إلى طبقة عمالقة متصلة بالكامل‪.‬‬
117 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

.‫ وكتلها‬NiN‫ و‬VGG ‫ مقارنة معماريات‬8.3.1 ‫الشكل‬

import tensorflow as tf
from d2l import tensorflow as d2l

def nin_block(out_channels, kernel_size, strides,


padding):
return tf.keras.models.Sequential([
tf.keras.layers.Conv2D(out_channels, kernel_size,
strides=strides,
padding=padding),
tf.keras.layers.Activation('relu'),
tf.keras.layers.Conv2D(out_channels, 1),
tf.keras.layers.Activation('relu'),
tf.keras.layers.Conv2D(out_channels, 1),
tf.keras.layers.Activation('relu')])
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 118

NiN 8.3.2
‫ (تم اقتراحه بعد ذلك بوقت‬AlexNet ‫ نفس أحجام االلتفاف األولية مثل‬NiN ‫يستخدم‬
‫ وعدد قنوات اإلخراج‬،‫ على التوالي‬،3 × 3 ‫ و‬5 × 5،11 × 11 ‫ أحجام النواة هي‬.)‫قصير‬
2 ‫ طبقة تجميع حد أقصى بخطوة‬NiN ‫ يتبع كل كتلة‬.AlexNet ‫يتطابق مع تلك الموجودةيف‬
.3 × 3 ‫وشكل نافذة‬

‫ يتجنب الطبقات‬NiN ‫يف أن‬VGG‫ و‬AlexNet‫ و‬NiN ‫يتمثل االختالف المهم الثاني بين‬
ٍ‫ مع عدد من قنوات اإلخراج مساو‬NiN ‫ كتلة‬NiN ‫ يستخدم‬،‫ بدالً من ذلك‬.ً‫المتصلة تمامًا معا‬
‫ مما ينتج عنه متجه‬،‫ متبوعة بطبقة تجميع متوسط عالمي‬،label classes ‫لعدد فئات التسميات‬
‫ يقلل هذا التصميم بشكل كبير من عدد معلمات النموذج‬.vector of logits ‫من السجالت‬
.‫ وإن كان ذلك على حساب زيادة محتملةيف وقت التدريب‬،‫المطلوبة‬

class NiN(d2l.Classifier):
def __init__(self, lr=0.1, num_classes=10):
super().__init__()
self.save_hyperparameters()
self.net = tf.keras.models.Sequential([
nin_block(96, kernel_size=11, strides=4,
padding='valid'),
tf.keras.layers.MaxPool2D(pool_size=3,
strides=2),
nin_block(256, kernel_size=5, strides=1,
padding='same'),
tf.keras.layers.MaxPool2D(pool_size=3,
strides=2),
nin_block(384, kernel_size=3, strides=1,
padding='same'),
tf.keras.layers.MaxPool2D(pool_size=3,
strides=2),
tf.keras.layers.Dropout(0.5),
nin_block(num_classes, kernel_size=3,
strides=1, padding='same'),
tf.keras.layers.GlobalAvgPool2D(),
tf.keras.layers.Flatten()])
.‫نقوم بإنشاء مثال بيانات لمعرفة شكل اإلخراج لكل كتلة‬

model = NiN()
X = tf.random.normal((1, 224, 224, 1))
for layer in model.net.layers:
X = layer(X)
119 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

print(layer.__class__.__name__,'output shape:\t',
X.shape)
Sequential output shape: (1, 54, 54, 96)
MaxPooling2D output shape: (1, 26, 26, 96)
Sequential output shape: (1, 26, 26, 256)
MaxPooling2D output shape: (1, 12, 12, 256)
Sequential output shape: (1, 12, 12, 384)
MaxPooling2D output shape: (1, 5, 5, 384)
Dropout output shape: (1, 5, 5, 384)
Sequential output shape: (1, 5, 5, 10)
GlobalAveragePooling2D output shape: (1, 10)
Flatten output shape: (1, 10)
Training 8.3.3
‫ لتدريب النموذج باستخدام نفس المُحسِّن‬Fashion-MNIST ‫ نستخدم‬،‫كما كان من قبل‬
.VGG‫ و‬AlexNet ‫الذي استخدمناه لـ‬

trainer = d2l.Trainer(max_epochs=10)
data = d2l.FashionMNIST(batch_size=128, resize=(224,
224))
with d2l.try_gpu():
model = NiN(lr=0.05)
trainer.fit(model, data)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪120‬‬

‫‪8.3.4‬‬
‫يحتوي ‪ NiN‬على معلمات أقل بشكل كبير من ‪ AlexNet‬و‪ .VGG‬ينبع هذايف المقام األول‬
‫من حقيقة أنه ال يحتاج إلى طبقات عمالقة متصلة بالكامل‪ .‬بدالً من ذلك‪ ،‬يستخدم متوسط‬
‫التجميع العالمي للتجميع عبر جميع مواقع الصور بعد المرحلة األخيرة من جسم الشبكة‪ .‬هذا‬
‫يغني عن الحاجة إلى عمليات تخفيض مكلفة (مكتسبة) ويستبدلها بمتوسط بسيط‪ .‬ما كان‬
‫مفاجئًايف ذلك الوقت هو حقيقة أن هذه العملية المتوسطة لم تضر بالدقة‪ .‬الحظ أن المتوسط عبر‬
‫تمثيل منخفض الدقة (مع العديد من القنوات) يضيف أيضًا إلى مقدار ثبات الترجمة الذي يمكن‬
‫للشبكة التعامل معه‪.‬‬

‫يساعد اختيار عدد أقل من التالفيفات ذات قنوات العريضة واستبدالها بالتالفيف ‪ 1 × 1‬يف ‬
‫البحث عن عدد أقل من المعلمات‪ .‬إنه يوفر قدرًا كبيرًا من الالخطية عبر القنوات داخل أي موقع‬
‫معين‪ .‬أثر كل من التالفيف ‪ 1 × 1‬والتجميع العالمي بشكل كبير على تصميمات ‪CNN‬‬
‫الالحقة‪.‬‬

‫‪8.3.5‬‬
‫‪ .1‬لماذا توجد طبقتان تالفيفيتان لكل كتلة ‪NiN‬؟ زد عددهم إلى ثالثة‪ .‬قلل عددهم إلى‬
‫واحد‪ .‬ما هي التغييرات؟‬
‫‪ .2‬ما الذي يتغير إذا استبدلت التالفيف ‪ 1 × 1‬بالتالفيف ‪3 × 3‬؟‬
‫‪ .3‬ماذا يحدث إذا استبدلت متوسط التجميع العالمي بطبقة متصلة بالكامل (السرعة‪،‬‬
‫الدقة‪ ،‬عدد المعلمات)؟‬
‫‪ .4‬احسب استخدام الموارد من أجل ‪.NiN‬‬
‫‪ .1‬ما هو عدد المعلمات؟‬
‫‪ .2‬ما هو مقدار الحساب؟‬
‫‪ .3‬ما هو مقدار الذاكرة المطلوبة أثناء التدريب؟‬
‫‪ .4‬ما هو مقدار الذاكرة المطلوبة أثناء التنبؤ؟‬
‫‪ .5‬ما هي المشاكل المحتملة مع تقليص التمثيل ‪ 384 × 5 × 5‬إلى التمثيل‬
‫‪ 10 × 5 × 5‬يف خطوة واحدة؟‬
‫‪ .6‬استخدم قرارات التصميم الهيكلييف ‪ VGG‬التي أدت إلى ‪ VGG-11‬و‪VGG-16‬‬
‫و‪ VGG-19‬لتصميم عائلة من الشبكات الشبيهة بـ ‪.NiN‬‬
‫‪121‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪Multi-Branch‬‬ ‫‪GoogLeNet‬‬ ‫‪8.4‬‬


‫‪Networks‬‬
‫في عام ‪ ،2014‬فازت ‪ GoogLeNet‬بتحدي ‪،)2015,Szegedy et al.( ،ImageNet‬‬
‫باستخدام هيكل يجمع بين نقاط القوةيف ‪ ،)2013,Lin et al.( ،NiN‬والكتل المتكررة‬
‫‪ ،)2014 ،Simonyan and Zisserman( repeated blocks‬ومجموعة من قنوات‬
‫االلتفاف‪ .‬يمكن القول أيضًا إنها أول شبكة تظهر تمييزًا واضحًا بين الجذع ‪( stem‬استيعاب‬
‫البيانات ‪ )data ingest‬والجسم ‪( body‬معالجة البيانات) والرأس ‪( head‬التنبؤ)يف شبكة‬
‫‪ .CNN‬استمر نمط التصميم هذا منذ ذلك الحينيف تصميم الشبكات العميقة‪ :‬يتم إعطاء الجذع‬
‫من خالل التالفيف ‪ 3-2‬األولى التي تعمل على الصورة‪ .‬يستخرجون ميزات منخفضة المستوى‬
‫من الصور األساسية‪ .‬يتبع ذلك مجموعة من الكتل التالفيفية‪ .‬أخيرًا‪ ،‬يقوم الرأس بتعيين الميزات‬
‫التي تم الحصول عليها حتى اآلن حسب مشكلة التصنيف أو التجزئة أو الكشف أو التتبع‬
‫المطلوبة‪.‬‬

‫كانت المساهمة الرئيسيةيف ‪ GoogLeNet‬هي تصميم هيكل الشبكة‪ .‬لقد حلت مشكلة اختيار‬
‫نواة االلتفاف بطريقة بارعة‪ .‬بينما حاولت أعمال أخرى تحديد االلتفاف األفضل‪ ،‬بدءًا من ‪1 × 1‬‬
‫إلى ‪ ، 11 × 11‬إال أنها قامت ببساطة بجمع التالفيف متعددة الفروع المتسلسلة‪ .‬فيما يلي نقدم‬
‫نسخة مبسطة قليالً من ‪ :GoogLeNet‬تضمن التصميم األصلي عددًا من الحيل لتحقيق‬
‫االستقراريف التدريب من خالل دوال الخسارة المتوسطة‪ ،‬المطبقة على طبقات متعددة من‬
‫الشبكة‪ .‬لم تعد ضرورية بسبب توفر خوارزميات تدريب محسّنة‪.‬‬

‫‪Inception Blocks‬‬ ‫‪8.4.1‬‬


‫تسمى الكتلة التالفيفية األساسيةيف ‪ GoogLeNet‬بكتل االستهالل ‪،Inception Blocks‬‬
‫وتنبع من الميم "نحن بحاجة إلى التعمق أكثر ‪"we need to go deeper‬يف فيلم ‪.Inception‬‬

‫الشكل ‪ 8.4.1‬هيكل كتلة االستهالل‪.‬‬

‫كما هو موضحيف الشكل ‪ ،8.4.1‬تتكون كتلة االستهالل ‪ inception block‬من أربعة فروع‬
‫متوازية‪ .‬تستخدم الفروع الثالثة األولى طبقات تالفيفية ذات أحجام نافذة ‪ ،1 × 1‬و‪5 × 5‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪122‬‬

‫الستخراج المعلومات من األحجام المكانية المختلفة‪ .‬يضيف الفرعان األوسطان أيضًا التفافًا‬
‫للمدخالت لتقليل عدد القنوات‪ ،‬مما يقلل من تعقيد النموذج‪ .‬يستخدم الفرع الرابع طبقة تجميع‬
‫الحد االقصى‪ ،‬متبوعة بطبقة تالفيفية لتغيير عدد القنوات‪ .‬تستخدم الفروع األربعة حشوة مناسبة‬
‫إلعطاء اإلدخال واإلخراج نفس االرتفاع والعرض‪ .‬أخيرًا‪ ،‬يتم ربط النواتج الموجودة على طول‬
‫كل فرع على طول بُعد القناة وتشكل ناتج الكتلة‪ .‬المعلمات الفائقة المضبوطة بشكل شائع لكتلة‬
‫البداية هي عدد قنوات اإلخراج لكل طبقة‪ ،‬أي كيفية تخصيص السعة بين التالفيف ذات الحجم‬
‫المختلف‪.‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪class Inception(tf.keras.Model):‬‬
‫‪# `c1`--`c4` are the number of output channels for‬‬
‫‪each branch‬‬
‫‪def __init__(self, c1, c2, c3, c4):‬‬
‫)(__‪super().__init‬‬
‫‪self.b1_1 = tf.keras.layers.Conv2D(c1, 1,‬‬
‫)'‪activation='relu‬‬
‫‪self.b2_1 = tf.keras.layers.Conv2D(c2[0], 1,‬‬
‫)'‪activation='relu‬‬
‫‪self.b2_2 = tf.keras.layers.Conv2D(c2[1], 3,‬‬
‫‪padding='same',‬‬

‫)'‪activation='relu‬‬
‫‪self.b3_1 = tf.keras.layers.Conv2D(c3[0], 1,‬‬
‫)'‪activation='relu‬‬
‫‪self.b3_2 = tf.keras.layers.Conv2D(c3[1], 5,‬‬
‫‪padding='same',‬‬

‫)'‪activation='relu‬‬
‫‪self.b4_1 = tf.keras.layers.MaxPool2D(3, 1,‬‬
‫)'‪padding='same‬‬
‫‪self.b4_2 = tf.keras.layers.Conv2D(c4, 1,‬‬
‫)'‪activation='relu‬‬

‫‪def call(self, x):‬‬


‫)‪b1 = self.b1_1(x‬‬
‫))‪b2 = self.b2_2(self.b2_1(x‬‬
‫))‪b3 = self.b3_2(self.b3_1(x‬‬
‫‪123‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫))‪b4 = self.b4_2(self.b4_1(x‬‬
‫‪return tf.keras.layers.Concatenate()([b1, b2,‬‬
‫)]‪b3, b4‬‬
‫للحصول على بعض الحدس عن سبب عمل هذه الشبكة بشكل جيد‪ ،‬ضعيف اعتبارك مجموعة‬
‫الفالتر‪ .‬يستكشفون الصورةيف مجموعة متنوعة من أحجام الفالتر‪ .‬هذا يعني أنه يمكن التعرف‬
‫على التفاصيل ذات النطاقات المختلفة بكفاءة بواسطة فالتر ذات أحجام مختلفة‪.‬يف الوقت نفسه‪،‬‬
‫يمكننا تخصيص كميات مختلفة من المعلمات لفالتر مختلفة‪.‬‬

‫‪GoogLeNet‬‬ ‫‪8.4.2‬‬
‫كما هو مبينيف الشكل ‪ ،8.4.2‬تستخدم ‪ GoogLeNet‬مكدس ‪ stack‬من إجمالي ‪ 9‬كتل‬
‫استهالل‪ ،‬مرتبةيف ‪ 3‬مجموعات مع أقصى تجميع بينهما‪ ،‬ومتوسط التجميع العالمييف رأسها‬
‫لتوليد تقديراتها‪ .‬تجميع الحد األقصى بين كتل البداية يقلل من األبعاد‪.‬يف جذعها‪ ،‬تشبه الوحدة‬
‫النمطية األولى ‪ AlexNet‬و‪.LeNet‬‬

‫الشكل ‪ 8.4.2‬بُنية ‪.GoogLeNet‬‬

‫يمكننا اآلن تنفيذ ‪ GoogLeNet‬قطعة قطعة‪ .‬لنبدأ بالجذع‪ .‬تستخدم الوحدة األولى طبقة‬
‫تالفيفية ‪ 7 × 7‬ذات ‪ 64‬قناة‪.‬‬

‫‪class GoogleNet(d2l.Classifier):‬‬
‫‪def b1(self):‬‬
‫[(‪return tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Conv2D(64, 7, strides=2,‬‬
‫‪padding='same',‬‬
‫‪activation='relu'),‬‬
‫‪tf.keras.layers.MaxPool2D(pool_size=3,‬‬
‫‪strides=2,‬‬
‫)])'‪padding='same‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪124‬‬

‫تستخدم الوحدة الثانية طبقتين تالفيفيتين‪ :‬األولى‪ ،‬طبقة تالفيفية ‪ 1 × 1‬ذات ‪ 64‬قناة‪ ،‬تليها‬
‫طبقة تالفيفية ‪ 3 × 3‬تضاعف عدد القنوات ثالث مرات‪ .‬هذا يتوافق مع الفرع الثانييف كتلة‬
‫االستهالل ويختتم تصميم الجسم‪.‬يف هذه المرحلة لدينا ‪192‬قناة‪.‬‬

‫)‪@d2l.add_to_class(GoogleNet‬‬
‫‪def b2(self):‬‬
‫[(‪return tf.keras.Sequential‬‬
‫‪tf.keras.layers.Conv2D(64, 1,‬‬
‫‪activation='relu'),‬‬
‫‪tf.keras.layers.Conv2D(192, 3, padding='same',‬‬
‫‪activation='relu'),‬‬
‫‪tf.keras.layers.MaxPool2D(pool_size=3,‬‬
‫)])'‪strides=2, padding='same‬‬
‫تقوم الوحدة الثالثة بتوصيل كتلتين كاملتين من كتل االستهالل على التوالي‪ .‬عدد قنوات اإلخراج‬
‫للكتلة األولى هو ‪ .64 + 128 + 32 + 32 = 256‬هذا يرقى إلى نسبة عدد قنوات اإلخراج‬
‫‪1‬‬
‫بين الفروع األربعة لـ ‪ .2: 4: 1: 1‬لتحقيق ذلك‪ ،‬نقوم أوالً بتقليل أبعاد اإلدخال بمقدار ‪ 2‬وبواسطة‬
‫‪1‬‬
‫يف الفرعين الثاني والثالث على التوالي للوصول إلى القنوات ‪ 16 = 192/12‬والقنوات‬ ‫‪12‬‬
‫‪ 16 = 192/12‬على التوالي‪.‬‬

‫يتم زيادة عدد قنوات اإلخراج لكتلة االستهالل الثانية إلى ‪128 + 192 + 96 + 64 = 480‬‬
‫محققاً نسبة ‪ .128: 192: 96: 64 = 4: 6: 3: 2‬كما كان من قبل‪ ،‬نحتاج إلى تقليل عدد األبعاد‬
‫‪1‬‬ ‫‪1‬‬
‫على التوالي يكفي‪ ،‬والعائد القنوات ‪ 128‬و ‪32‬‬ ‫و‬ ‫الوسيطةيف القناة الثانية والثالثة‪ .‬مقياس‬
‫‪8‬‬ ‫‪2‬‬
‫على التوالي‪ .‬يتم التقاط هذا من خالل وسيطات المنشئ ‪ Inception block‬التالية‪.‬‬

‫)‪@d2l.add_to_class(GoogleNet‬‬
‫‪def b3(self):‬‬
‫[(‪return tf.keras.models.Sequential‬‬
‫‪Inception(64, (96, 128), (16, 32), 32),‬‬
‫‪Inception(128, (128, 192), (32, 96), 64),‬‬
‫‪tf.keras.layers.MaxPool2D(pool_size=3,‬‬
‫)])'‪strides=2, padding='same‬‬
‫الوحدة الرابعة أكثر تعقيدًا‪ .‬يربط خمس كتل بدايةيف سلسلة‪ ،‬ولديهم ‪192 + 208 + 48 +‬‬
‫‪ ، 128 + 256 + 64 + 64 = 512 ، 160 + 224 + 64 + 64 = 512، 64 = 512‬و‬
‫‪ 256 + 320 + 128 + 128 = 832112 + 288 + 64 + 64 = 528‬قنوات اإلخراج‪،‬‬
‫على التوالي‪ .‬عدد القنوات المخصصة لهذه الفروع مماثل لتلك الموجودةيف الوحدة الثالثة‪ :‬الفرع‬
‫الثاني مع الطبقة التالفيفية ‪ 3 × 3‬يخرج أكبر عدد من القنوات‪ ،‬يليه الفرع األول مع الطبقة‬
‫التالفيفية ‪ 1 × 1‬فقط‪ ،‬والفرع الثالث مع الطبقة التالفيفية ‪ ، 5 × 5‬والفرع الرابع مع طبقة‬
‫‪125‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫التجميع القصوى ‪ .3 × 3‬سيقلل الفرعان الثاني والثالث أوالً عدد القنوات وفقًا للنسبة‪ .‬تختلف‬
‫هذه النسب اختالفًا طفيفًايف كتل التأسيس المختلفة‪.‬‬

‫)‪@d2l.add_to_class(GoogleNet‬‬
‫‪def b4(self):‬‬
‫[(‪return tf.keras.Sequential‬‬
‫‪Inception(192, (96, 208), (16, 48), 64),‬‬
‫‪Inception(160, (112, 224), (24, 64), 64),‬‬
‫‪Inception(128, (128, 256), (24, 64), 64),‬‬
‫‪Inception(112, (144, 288), (32, 64), 64),‬‬
‫‪Inception(256, (160, 320), (32, 128), 128),‬‬
‫‪tf.keras.layers.MaxPool2D(pool_size=3,‬‬
‫)])'‪strides=2, padding='same‬‬
‫تحتوي الوحدة الخامسة على كتلتين ابتدائيتين مع ‪ 256 + 320 + 128 + 128 = 832‬و‬
‫‪ 384 + 384 + 128 + 128 = 1024‬قنوات إخراج‪ .‬عدد القنوات المخصصة لكل فرع هو‬
‫نفسه الموجوديف الوحدتين الثالثة والرابعة‪ ،‬ولكنه يختلفيف القيم المحددة‪ .‬وتجدر اإلشارة إلى‬
‫أن الكتلة الخامسة تتبعها طبقة اإلخراج‪ .‬تستخدم هذه الكتلة طبقة تجميع المتوسط العالمية لتغيير‬
‫ارتفاع وعرض كل قناة إلى ‪ ،1‬تمامًا كما هو الحاليف ‪ .NiN‬أخيرًا‪ ،‬نقوم بتحويل اإلخراج إلى‬
‫مصفوفة ثنائية األبعاد متبوعة بطبقة متصلة بالكامل يكون عدد مخرجاتها هو عدد فئات التسمية‪.‬‬

‫)‪@d2l.add_to_class(GoogleNet‬‬
‫‪def b5(self):‬‬
‫[(‪return tf.keras.Sequential‬‬
‫‪Inception(256, (160, 320), (32, 128), 128),‬‬
‫‪Inception(384, (192, 384), (48, 128), 128),‬‬
‫‪tf.keras.layers.GlobalAvgPool2D(),‬‬
‫)])(‪tf.keras.layers.Flatten‬‬
‫اآلن بعد أن حددنا جميع الكتل من ‪ b1‬إلى ‪ ،b5‬فإن األمر يتعلق فقط بتجميعهم جميعًايف شبكة‬
‫كاملة‪.‬‬

‫)‪@d2l.add_to_class(GoogleNet‬‬
‫‪def __init__(self, lr=0.1, num_classes=10):‬‬
‫)(__‪super(GoogleNet, self).__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫[(‪self.net = tf.keras.Sequential‬‬
‫‪self.b1(), self.b2(), self.b3(), self.b4(),‬‬
‫‪self.b5(),‬‬
‫)])‪tf.keras.layers.Dense(num_classes‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪126‬‬

‫يعتبر نموذج ‪ GoogLeNet‬معقدًا من الناحية الحسابية‪ .‬الحظ العدد الكبير من المعلمات‬


‫الفائقة التعسفية نسبيًا من حيث عدد القنوات المختارة‪ ،‬وعدد الكتل قبل تقليل األبعاد‪ ،‬والتقسيم‬
‫النسبي للسعة عبر القنوات‪ ،‬وما إلى ذلك‪ .‬لم تكن األدوات اآللية لتعريف الشبكة أو استكشاف‬
‫التصميم متاحة بعد‪ .‬على سبيل المثال‪ ،‬نحن اآلن نعتبر أنه من المسلم به أن إطار عمل التعلم‬
‫العميق المختص قادر على استنتاج أبعاد موترات اإلدخال تلقائيًا‪.‬يف ذلك الوقت‪ ،‬كان يتعين على‬
‫المجرب تحديد العديد من هذه التكوينات صراحة‪ ،‬مما يؤدييف كثير من األحيان إلى إبطاء‬
‫التجريب النشط‪ .‬عالوة على ذلك‪ ،‬كانت األدوات الالزمة لالستكشاف التلقائي ال تزاليف حالة‬
‫تغير مستمر‪ ،‬وكانت التجارب األولية تصل إلى حد كبير إلى استكشاف القوة العمياء ‪brute‬‬
‫‪،genetic‬‬ ‫‪algorithms‬‬ ‫الجينية‬ ‫والخوارزميات‬ ‫المكلفة‪،‬‬ ‫‪force‬‬ ‫‪exploration‬‬
‫واالستراتيجيات المماثلة‪.‬‬

‫في الوقت الحالي‪ ،‬التعديل الوحيد الذي سنقوم به هو تقليل ارتفاع المدخالت وعرضها من ‪224‬‬
‫إلى ‪ 96‬للحصول على وقت تدريب معقول على ‪ .Fashion-MNIST‬هذا يبسط الحساب‪.‬‬
‫دعونا نلقي نظرة على التغييراتيف شكل اإلخراج بين الوحدات المختلفة‪.‬‬

‫))‪model = GoogleNet().layer_summary((1, 96, 96, 1‬‬


‫‪Sequential output shape:‬‬ ‫)‪(1, 24, 24, 64‬‬
‫‪Sequential output shape:‬‬ ‫)‪(1, 12, 12, 192‬‬
‫‪Sequential output shape:‬‬ ‫)‪(1, 6, 6, 480‬‬
‫‪Sequential output shape:‬‬ ‫)‪(1, 3, 3, 832‬‬
‫‪Sequential output shape:‬‬ ‫)‪(1, 1024‬‬
‫)‪Dense output shape: (1, 10‬‬
‫‪Training‬‬ ‫‪8.4.3‬‬
‫كمايف السابق‪ ،‬نقوم بتدريب نموذجنا باستخدام مجموعة بيانات ‪ .Fashion-MNIST‬نقوم‬
‫بتحويله إلى دقة ‪ 96 × 96‬بكسل قبل استدعاء إجراء التدريب‪.‬‬

‫)‪trainer = d2l.Trainer(max_epochs=10‬‬
‫))‪data = d2l.FashionMNIST(batch_size=128, resize=(96, 96‬‬
‫‪with d2l.try_gpu():‬‬
‫)‪model = GoogleNet(lr=0.01‬‬
‫)‪trainer.fit(model, data‬‬
‫‪127‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪8.4.4‬‬
‫الميزة الرئيسية لـ ‪ GoogLeNet‬هي أنها أرخصيف الواقع للحوسبة من سابقاتها مع توفير دقة‬
‫محسنةيف نفس الوقت‪ .‬يمثل هذا بداية تصميم شبكة مدروس بشكل أكبر والذي يتم فيه استبدال‬
‫تكلفة تقييم الشبكة مع تقليل األخطاء‪ .‬كما يمثل بداية التجريب على مستوى الكتلة باستخدام‬
‫معلمات فائقة لتصميم الشبكة‪ ،‬ع لى الرغم من أنها كانت يدوية بالكامليف ذلك الوقت‪ .‬سنعيد‬
‫النظريف هذا الموضوعيف القسم ‪ 8.8‬عند مناقشة استراتيجيات استكشاف بُنية الشبكة‪.‬‬

‫خالل األقسام التالية‪ ،‬سنواجه عددًا من خيارات التصميم (على سبيل المثال‪ ،‬تسوية الدُفعات‬
‫‪ ،batch normalization‬واالتصاالت المتبقية ‪ ،residual connections‬وتجميع القنوات‬
‫‪ )channel grouping‬التي تسمح لنا بتحسين الشبكات بشكل كبير‪.‬يف الوقت الحالي‪ ،‬يمكنك‬
‫أن تفخر بتنفيذ ما يمكن القول إنه أول شبكة ‪ CNN‬حديثة حقًا‪.‬‬

‫‪8.4.5‬‬
‫‪ .1‬كانت ‪ GoogLeNet‬ناجحة للغاية لدرجة أنها مرت بعدد من التكرارات‪ .‬هناك العديد‬
‫من التكرارات لـ ‪ GoogLeNet‬التي تعمل على تحسين السرعة والدقة بشكل‬
‫تدريجي‪ .‬حاول تنفيذ وتشغيل بعضها‪ .‬وهي تشمل ما يلي‪:‬‬
‫‪ .2‬أضف طبقة تسوية دفعية (‪ ،)2015 ،Ioffe and Szegedy‬كما هو موضح الحقًايف ‬
‫القسم ‪.8.5‬‬
‫‪ .3‬قم بإجراء تعديالت على كتلة االستهالل (العرض واالختيار وترتيب التالفيف)‪ ،‬كما‬
‫هو موضحيف (‪.)2016 ،Szegedy et al.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪128‬‬

‫‪ .4‬استخدم تجانس التسمية ‪ label smoothing‬لتسوية النموذج‪ ،‬كما هو موضحيف ‬


‫(‪.)2016 ،Szegedy et al.‬‬
‫‪ .5‬قم بإجراء مزيد من التعديالت على مجموعة ‪ Inception‬عن طريق إضافة اتصال‬
‫متبقي ‪ ،)2017 ،Szegedy et al.( residual connection‬كما هو موضح الحقًا‬
‫في القسم ‪.8.6.40‬‬
‫‪ .6‬ما هو الحد األدنى لحجم الصورة لكي يعمل ‪GoogLeNet‬؟‬
‫‪ .7‬هل يمكنك تصميم متغير من ‪ GoogLeNet‬يعمل على دقة ‪ 28 × 28‬بكسل‬
‫األصلية لـ ‪Fashion-MNIST‬؟ كيف ستحتاج إلى تغيير الجذع والجسم ورأس‬
‫الشبكة‪ ،‬إذا كان هناك أي شيء على اإلطالق؟‬
‫‪ .8‬قارن أحجام معلمات النموذج لـ ‪ AlexNet‬و‪ VGG‬و‪ NiN‬و‪ .GoogLeNet‬كيف‬
‫تقلل معماريتا الشبكة األخيرتان بشكل كبير من حجم معلمة النموذج؟‬
‫‪ .9‬قارن مقدار الحساب المطلوبيف ‪ GoogLeNet‬و‪ .AlexNet‬كيف يؤثر ذلك على‬
‫تصميم شريحة التسريع ‪ ،accelerator chip‬على سبيل المثال‪ ،‬من حيث حجم‬
‫الذاكرة وعرض النطاق الترددي للذاكرة ‪ memory bandwidth‬وحجم ذاكرة‬
‫التخزين ‪ cache size‬المؤقت ومقدار الحساب وفائدة العمليات المتخصصة؟‬

‫‪Batch Normalization‬‬ ‫‪8.5‬‬


‫تدريب الشبكات العصبية العميقة أمر صعب‪ .‬قد يكون جعلهم يتقاربونيف فترة زمنية معقولة أمرًا‬
‫صعبًا‪.‬يف هذا القسم‪ ،‬نصف التسوية بالدفعات ‪ ،Batch Normalization‬وهي تقنية شائعة‬
‫وفعالة تعمل باستمرار على تسريع تقارب الشبكات العميقة (‪.)2015 ،Ioffe and Szegedy‬‬
‫جنبًا إلى جنب مع الكتل المتبقية ‪ -‬التي تمت تغطيتها الحقًايف القسم ‪ - 8.6‬أتاح التسوية‬
‫بالدفعات للممارسين تدريب الشبكات بشكل روتيني مع أكثر من ‪ 100‬طبقة‪ .‬تكمن فائدة ثانوية‬
‫(مصادفة) للتسوية بالدُفعاتيف تنظيمها المتأصل‪.‬‬

‫‪Training Deep Networks‬‬ ‫‪8.5.1‬‬


‫عند التعامل مع البيانات‪ ،‬فإننا غالبًا ما نعالجها مسبقًا قبل التدريب‪ .‬غالبًا ما تُحدث الخيارات‬
‫المتعلقة بالمعالجة المسبقة للبيانات فرقًا كبيرًايف النتائج النهائية‪ .‬تذكر تطبيقنا لـ ‪ MLPs‬للتنبؤ‬
‫بأسعار المنازل (القسم ‪ .) 5.7‬كانت خطوتنا األولى عند العمل مع البيانات الحقيقية هي توحيد‬
‫‪ standardize‬ميزات اإلدخال لدينا بحيث يكون لها متوسط صفر ‪ 𝝁 = 0‬وتباين واحد 𝟏 = 𝚺‬
‫عبر العديد من المشاهدات ‪ .)1987 ،Friedman( observations‬كحد أدنى‪ ،‬كثيرًا ما يقوم‬
‫المرء بإعادة قياسه بحيث يكون القطر هو الوحدة ‪ ،unity‬أي ‪ .Σ𝑖𝑖 = 1‬هناك إستراتيجية أخرى‬
‫تتمثليف إعادة قياس المتجهات إلى طول الوحدة ‪ ،unit length‬وربما صفر متوسط لكل‬
‫‪129‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫مالحظة‪ .‬يمكن أن يعمل هذا بشكل جيد‪ ،‬على سبيل المثال‪ ،‬لبيانات المستشعر المكاني‪ .‬تعد‬
‫تقنيات المعالجة المسبقة هذه وغيرها الكثير مفيدة للحفاظ على التحكميف مشكلة التقدير بشكل‬
‫جيد‪ .‬انظر على سبيل المثال‪ ،‬المقاالت التي كتبها ‪ )2008( .Guyon et al‬لمراجعة اختيار‬
‫الميزات وتقنيات االستخراج‪ .‬توحيد المتجهات ‪ Standardizing vectors‬له أيضًا تأثير جانبي‬
‫لطيف يتمثليف تقييد دالة التعقيد للدوال التي تعمل على أساسها‪ .‬على سبيل المثال‪ ،‬الحد‬
‫المشهور بهامش الشعاع ‪)1995 ،Vapnik( radius-margin bound‬يف آالت ناقالت الدعم‬
‫‪،Perceptron‬‬ ‫‪Convergence‬‬ ‫و‪Theorem‬‬ ‫‪support‬‬ ‫‪vector‬‬ ‫‪machines‬‬
‫(‪ )1962,Novikoff‬يعتمدان على مدخالت ذات معيار محدود ‪.bounded norm‬‬

‫حدسيًا‪ ،‬يلعب هذا التوحيد ‪ standardization‬بشكل جيد مع مُحسِّنينا ‪ our optimizers‬ألنه‬


‫يضع المعلمات مسبقًا على نطاق مماثل‪ .‬على هذا النحو‪ ،‬من الطبيعي أن نتساءل عما إذا كانت‬
‫خطوة التسوية ‪ normalization‬المقابلة داخل شبكة عميقة قد ال تكون مفيدة‪.‬يف حين أن هذا‬
‫ليس السبب تمامًا الذي أدى إلى اختراع التسوية بالدُفعات (‪ ،)2015 ،Ioffe and Szegedy‬إال‬
‫أنه طريقة مفيدة لفهمه وتسوية الطبقات ‪)2016 ،Ba et al.( layer normalization‬يف إطار‬
‫موحد‪.‬‬

‫ثانيًا‪ ،‬بالنسبة إلى ‪ MLP‬أو ‪ CNN‬النموذجي‪ ،‬أثناء تدريبنا‪ ،‬قد تأخذ المتغيراتيف الطبقات‬
‫المتوسطة (على سبيل المثال‪ ،‬مخرجات التحويل األفينييف ‪ )MLP‬قيمًا بأحجام متفاوتة على‬
‫نطاق واسع‪ :‬كالهما على طول الطبقات من اإلدخال إلى اإلخراج‪ ،‬عبر الوحداتيف نفس الطبقة‪،‬‬
‫وبمرور الوقت بسبب تحديثاتنا لمعلمات النموذج‪ .‬افترض مخترعو التسوية بالدفعات بشكل غير‬
‫رسمي أن هذا االنجراف ‪drift‬يف توزيع مثل هذه المتغيرات يمكن أن يعيق تقارب الشبكة‪.‬‬
‫حدسيًا‪ ،‬قد نخمن أنه إذا كانت إحدى الطبقات بها عمليات تنشيط متغيرة تزيد ‪ 100‬مرة عن‬
‫تلك الموجودةيف طبقة أخرى‪ ،‬فقد يتطلب ذلك تعديالت تعويضيةيف معدالت التعلم‪ .‬تهدف‬
‫المحلالت التكيفية ‪ Adaptive solvers‬مثل‪ )2011,Duchi et al.( ،AdaGrad‬أو ‪،Adam‬‬
‫(‪ )2014,Kingma and Ba‬أو ‪ )2018,Zaheer et al.( ،Yogi‬أو ‪Distributed‬‬
‫‪ )2020,Anil et al.( ،Shampoo‬إلى معالجة هذا األمر من وجهة نظر التحسين‪ ،‬على سبيل‬
‫المثال‪ ،‬عن طريق إضافة جوانب من أساليب الدرجة الثانية‪ .‬البديل هو منع حدوث المشكلة‪،‬‬
‫ببساطة عن طريق التسوية التكيفية ‪.adaptive normalization‬‬

‫ثالثًا‪ ،‬الشبكات األعمق معقدة وتميل إلى أن تكون أكثر قدرة على الضبط الزائد ‪overfitting‬‬
‫بسهولة‪ .‬هذا يعني أن التنظيم ‪ regularization‬يصبح أكثر أهمية‪ .‬تقنية شائعة للتنظيم هي حقن‬
‫الضوضاء ‪ .noise injection‬كان هذا معروفًا لفترة طويلة‪ ،‬على سبيل المثال‪ ،‬فيما يتعلق بحقن‬
‫الضوضاء للمدخالت (‪ .)1995 ،Bishop‬كما أنه يشكل أساس التسرب ‪dropout‬يف القسم‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪130‬‬

‫‪ .5.6‬كما اتضح‪ ،‬مصادفة تمامًا‪ ،‬فإن تسوية الدُفعات ينقل جميع الفوائد الثالثة‪ :‬المعالجة‬
‫المسبقة ‪ ،preprocessing‬واالستقرار العددي ‪ ،numerical stability‬والتنظيم‬
‫‪.regularization‬‬

‫يتم تطبيق تسوية الدُفعات على الطبقات الفردية‪ ،‬أو اختياريًا‪ ،‬لكل منها‪:‬يف كل تكرار تدريبي‪،‬‬
‫نقوم أوالً بتسوية المدخالت (تسوية الدُفعة) بطرح متوسطها والقسمة على انحرافها المعياري‪،‬‬
‫حيث يتم تقدير كالهما بناءً على اإلحصائيات من الدفعات الصغيرة الحالي‪ .‬بعد ذلك‪ ،‬نطبق‬
‫معامل مقياس ‪ scale coefficient‬وتعويض الستعادة درجات الحرية المفقودة‪ .‬يرجع هذا‬
‫تحديدًا إلى هذا التسوية استنادًا إلى إحصائيات الدُفعات‪ ،‬حيث تشتق تسوية الدُفعة اسمها‪.‬‬

‫الحظ أنه إذا حاولنا تطبيق تسوية الدُفعات باستخدام دفعات صغيرة من الحجم ‪ ،1‬فلن نتمكن‬
‫من تعلم أي شيء‪ .‬هذا ألنه بعد طرح المتوسط‪ ،‬ستأخذ كل وحدة مخفية القيمة ‪ .0‬كما قد‬
‫تتخيل‪ ،‬نظرًا ألننا نخصص قسمًا كامالً لتسوية الدُفعات‪ ،‬مع وجود عدد كافٍ من الدُفعات‬
‫الصغيرة‪ ،‬فإن الطريقة تثبت فعاليتها وثباتها‪ .‬أحد الوجبات الجاهزة هنا هو أنه عند تطبيق تسوية‬
‫الدُفعات‪ ،‬يكون اختيار حجم الدُفعة أكثر أهمية من عدم تسوية الدُفعات‪ ،‬أو على األقل‪ ،‬هناك‬
‫حاجة إلى معايرة مناسبة حيث يمكننا تعديلها‪.‬‬

‫قم باإلشارة بواسطة الدفعات الصغيرة ‪ ℬ‬وليكن ‪ 𝐱 ∈ ℬ‬تكون مدخالً لتسوية الدُفعات (‪.)BN‬‬
‫في هذه الحالة‪ ،‬يتم تحديد تسوية الدُفعة على النحو التالي‪:‬‬

‫‪𝐱− 𝝁 ℬ‬‬
‫⊙ 𝜸 = )𝐱(‪BN‬‬ ‫‪+ 𝜷.‬‬ ‫(‪)8.5.1‬‬
‫‪𝝈 ℬ‬‬

‫^‬ ‫^‬
‫في (‪ 𝝁ℬ ،)8.5.1‬هو متوسط العينة و ‪ 𝝈ℬ‬هو االنحراف المعياري للعينة من الدفعات الصغيرة‪.‬‬
‫بعد تطبيق التوحيد القياسي ‪ ،standardization‬فإن الدفعات الصغيرة الناتج له متوسط صفري‬
‫وتباين الوحدة‪ .‬يعد اختيار تباين الوحدة (مقابل بعض األرقام السحرية األخرى) اختيارًا عشوائيًا‪.‬‬
‫نستعيد درجة الحرية هذه بتضمين معلمة مقياس عنصري (‪ 𝜸 )elementwise‬ومعلمة تحول‬
‫(‪ 𝜷 )shift parameter‬لها نفس الشكل مثل 𝐱‪ .‬كالهما معلمات يجب تعلمها كجزء من تدريب‬
‫النموذج‪.‬‬

‫ال يمكن لألحجام المتغيرة للطبقات المتوسطة أن تتباعد أثناء التدريب ألن تسوية الدُفعات يتركز‬
‫^‬ ‫^‬
‫بنشاط ويعيد قياسها مرة أخرى إلى متوسط وحجم معينين (عبر ‪ 𝝁ℬ‬و ‪ .)𝝈ℬ‬تؤكد التجربة العملية‬
‫أنه‪ ،‬كما أشير إليه عند مناقشة إعادة قياس الميزات ‪ ،feature rescaling‬يبدو أن تسوية الدُفعات‬
‫^‬ ‫^‬
‫يسمح بمعدالت تعلم أكثر قوة‪ .‬نحسب ‪ 𝝁ℬ‬و ‪ 𝝈ℬ‬يف (‪ )8.5.1‬كالتالي‪:‬‬
‫‪131‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫^‬ ‫‪1‬‬ ‫^‬ ‫‪1‬‬ ‫^‬


‫= ‪𝝁ℬ‬‬ ‫= ‪∑ 𝐱 and 𝝈2ℬ‬‬ ‫∑‬ ‫‪(𝐱 − 𝝁ℬ )2 + 𝜖.‬‬
‫|‪|ℬ‬‬ ‫|‪|ℬ‬‬
‫‪𝐱∈ℬ‬‬ ‫‪𝐱∈ℬ‬‬

‫الحظ أننا نضيف ثابتًا صغيرًا لتقدير التباين لضمان عدم محاولة القسمة على الصفر أبدًا‪ ،‬حتى‬
‫في الحاالت التي قد يكون فيها تقدير التباين التجريبي صغيرًا جدًا أو حتى يتالشى‪ .‬التقديرات‬
‫^‬ ‫^‬
‫‪ 𝝁ℬ‬و ‪ 𝝈ℬ‬مواجهة مشكلة القياس باستخدام تقديرات صاخبة ‪ noisy estimates‬للمتوسط‬
‫والتباين‪ .‬قد تعتقد أن هذه الضوضاء يجب أن تكون مشكلة‪ .‬على العكس تمامًا‪ ،‬هذا مفيد بالفعل‪.‬‬

‫تبين أن هذا موضوع متكرريف التعلم العميق‪ .‬ألسباب لم يتم وصفها جيدًا من الناحية النظرية‪،‬‬
‫غالبًا ما تؤدي المصادر المختلفة للضوضاءيف التحسين إلى تدريب أسرع وضبط زائد أقل‪ :‬يبدو‬
‫أن هذا االختالف يعمل كشكل من أشكال التنظيم‪ )2018 ،Teye et al.( .‬و (‪،Luo et al.‬‬
‫‪ )2018‬يربطان خصائص تسوية الدُفعات بـ ‪ Bayesian priors‬والعقوبات على التوالي‪ .‬على‬
‫وجه الخصوص‪ ،‬يلقي هذا بعض الضوء على اللغز لماذا يعمل تسوية الدُفعات بشكل أفضل مع‬
‫األحجام الصغيرة المتوسطةيف النطاق ‪ .50 ∼ 100‬يبدو أن هذا الحجم المعين من الدفعات‬
‫الصغيرة ‪ minibatch‬يضخ "المقدار المناسب ‪ "right amount‬من الضوضاء لكل طبقة‪ ،‬سواء‬
‫^‬ ‫^‬
‫من حيث الحجم عبر 𝝈‪ ،‬ومن حيث التعويض عن عبر 𝝁‪ :‬الدفعة الصغيرة األكبر ‪larger‬‬
‫‪ minibatch‬يتم تنظيمها بشكل أقل بسبب التقديرات األكثر ثباتًا‪،‬يف حين أن الدفعات الصغيرة‬
‫االصغر ‪ tiny minibatches‬تدمر اإلشارة المفيدة بسبب التباين العالي‪ .‬استكشاف هذا االتجاه‬
‫بشكل أكبر‪ ،‬والنظريف األنواع البديلة للمعالجة المسبقة والتصفية قد يؤدي إلى أنواع فعالة أخرى‬
‫من التنظيم‪.‬‬

‫عند إصالح نموذج مدرب‪ ،‬قد تعتقد أننا نفضل استخدام مجموعة البيانات ‪ dataset‬بأكملها‬
‫لتقدير المتوسط والتباين‪ .‬بمجرد اكتمال التدريب‪ ،‬لماذا نرغبيف تصنيف نفس الصورة بشكل‬
‫مختلف‪ ،‬اعتمادًا على المجموعة التي تتواجد فيها؟ أثناء التدريب‪ ،‬مثل هذا الحساب الدقيق غير‬
‫ممكن ألن المتغيرات الوسيطة لجميع أمثلة البيانات تتغيريف كل مرة نقوم فيها بتحديث نموذجنا‪.‬‬
‫ومع ذلك‪ ،‬بمجرد تدريب النموذج‪ ،‬يمكننا حساب متوسطات ومتغيرات كل طبقة بناءً على‬
‫مجموعة البيانات بأكملها‪.‬يف الواقع‪ ،‬هذه ممارسة قياسية للنماذج التي تستخدم تسوية الدُفعات‪،‬‬
‫وبالتالي تعمل طبقات تسوية الدفعات بشكل مختلفيف وضع التدريب ‪training mode‬‬
‫(التسوية عن طريق إحصائيات الدُفعة المصغرة) وفي وضع التنبؤ ‪( prediction mode‬التسوية‬
‫بواسطة إحصاءات مجموعة البيانات)‪.‬يف هذا النموذج‪ ،‬تشبه إلى حد كبير سلوك تنظيم التسرب‬
‫‪ dropout regularization‬من القسم ‪ ،5.6‬حيث يتم حقن الضوضاء فقط أثناء التدريب‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪132‬‬

‫‪Batch Normalization Layers‬‬ ‫‪8.5.2‬‬


‫تختلف تطبيقات تسوية الدفعات للطبقات المتصلة تمامًا والطبقات التالفيفية قليالً‪ .‬يتمثل أحد‬
‫االختالفات الرئيسية بين تسوية الدُفعات والطبقات األخرىيف أنه نظرًا ألن تسوية الدُفعات يعمل‬
‫على الدفعات الصغيرة ‪ minibatch‬كامليف كل مرة‪ ،‬ال يمكننا تجاهل بُعد الدُفعة ‪batch‬‬
‫‪ dimension‬كما فعلنا من قبل عند تقديم طبقات أخرى‪.‬‬

‫‪Fully Connected Layers‬‬ ‫‪8.5.2.1‬‬


‫عند تطبيق تسوية الدُفعات على طبقات متصلة بالكامل ‪ ،Fully Connected Layers‬يتم‬
‫إدخال تسوية الدُفعة للمقالة االصلية بعد التحويل األفيني وقبل دالة التنشيط غير الخطي‪ .‬جربت‬
‫التطبيقات الالحقة إدخال تسوية الدُفعات مباشرة بعد دوال التنشيط (‪،Ioffe and Szegedy‬‬
‫‪ .) 2015‬باإلشارة إلى المدخالت إلى الطبقة المتصلة بالكامل 𝐱 عن طريق التحويل األفيني‬
‫𝐛 ‪( 𝐖𝐱 +‬مع معلمة الوزن 𝐖 ومعلمة التحيز 𝐛)‪ ،‬ودالة التنشيط من خالل 𝜙‪ ،‬يمكننا التعبير‬
‫عن حساب الممكّن لتسوية الدفعات وإخراج الطبقة المتصل بالكامل 𝐡 على النحو التالي‪:‬‬

‫‪𝐡 = 𝜙(BN(𝐖𝐱 + 𝐛)).‬‬

‫تذكر أن المتوسط والتباين يتم حسابهما على نفس الدفعة الصغيرة ‪ minibatch‬الذي يتم تطبيق‬
‫التحويل عليه‪.‬‬

‫‪Convolutional Layers‬‬ ‫‪8.5.2.2‬‬


‫وبالمثل‪ ،‬مع الطبقات التالفيفية ‪ ،Convolutional Layers‬يمكننا تطبيق تسوية الدُفعات بعد‬
‫االلتفاف وقبل دالة التنشيط الالخطي‪ .‬يتمثل االختالف الرئيسي عن تسوية الدُفعاتيف الطبقات‬
‫المتصلة بالكامليف أننا نطبق العملية على أساس كل قناة عبر جميع المواقع‪ .‬يتوافق هذا مع‬
‫افتراضنا لثبات الترجمة الذي أدى إلى تالفيف‪ :‬لقد افترضنا أن الموقع المحدد لنمط داخل‬
‫الصورة لم يكن حاسمًا لغرض الفهم‪.‬‬

‫افترض أن الدفعات الصغيرة لدينا تحتوي على 𝑚 أمثلة وأن ناتج االلتفاف لكل قناة له ارتفاع 𝑝‬
‫وعرض 𝑞‪ .‬بالنسبة للطبقات التالفيفية‪ ،‬نقوم بتنفيذ تسوية كل دفعة على العناصر 𝑞 ⋅ 𝑝 ⋅ 𝑚 لكل‬
‫قناة إخراجيف وقت واحد‪ .‬وبالتالي‪ ،‬فإننا نجمع القيم عبر جميع المواقع المكانية عند حساب‬
‫المتوسط والتباين‪ ،‬وبالتالي نطبق نفس المتوسط والتباين داخل قناة معينة لتسوية القيمةيف كل‬
‫موقع مكاني‪ .‬كل قناة لها مقياسها ومعلمات التحول الخاصة بها‪ ،‬وكالهما قيمة قياسية ‪.scalar‬‬

‫‪Layer Normalization‬‬ ‫‪8.5.2.3‬‬


‫الحظ أنهيف سياق التالفيف‪ ،‬يتم تحديد تسوية الدُفعات جيدًا حتى بالنسبة للدفعات الصغيرة‬
‫ذات الحجم ‪ :1‬بعد كل شيء‪ ،‬لدينا جميع المواقع عبر الصورة إلى المتوسط‪ .‬وبالتالي‪ ،‬يتم تحديد‬
‫‪133‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫المتوسط والتباين جيدًا‪ ،‬حتى لو كان ذلك ضمن مالحظة واحدة فقط‪ .‬قاد هذا االعتبار ‪Ba et‬‬
‫‪ )2016( .al‬إلدخال مفهوم تسوية الطبقة ‪ .layer normalization‬إنه يعمل تمامًا مثل معيار‬
‫الدُفعة ‪ ،batch norm‬فقط أنه يتم تطبيقه على مالحظة واحدةيف كل مرة‪ .‬وبالتالي فإن كالً من‬
‫اإلزاحة والقيمة القياسية ‪ .scalars‬بالنظر إلى متجه 𝐱 ذي األبعاد 𝑛 ‪ ،‬يتم إعطاء معايير ‪norms‬‬
‫الطبقة بواسطة‬
‫^‬
‫𝜇‪𝐱−‬‬
‫= )𝐱(‪𝐱 → LN‬‬ ‫^‬
‫‪,‬‬
‫𝜎‬
‫حيث يتم تطبيق المقياس ‪ scaling‬واإلزاحة ‪ offset‬من حيث المعامل ويتم تقديمهما بواسطة‬
‫𝑛‬ ‫𝑛‬
‫^‬ ‫‪1‬‬ ‫‪^2‬‬ ‫‪1‬‬ ‫^‬
‫∑ = ‪𝜇:‬‬ ‫∑ = ‪𝑥𝑖 and 𝜎 :‬‬ ‫‪(𝑥𝑖 − 𝜇)2 + 𝜖.‬‬
‫𝑛‬ ‫𝑛‬
‫‪𝑖=1‬‬ ‫‪𝑖=1‬‬

‫كما كان من قبل‪ ،‬نضيف ازاحة صغيرًة ‪ 𝜖 > 0‬لمنع القسمة على الصفر‪ .‬تتمثل إحدى الفوائد‬
‫الرئيسية الستخدام تسوية الطبقةيف أنه يمنع التباعد ‪ .divergence‬بعد كل شيء‪ ،‬تجاهل 𝜖‪،‬‬
‫ناتج تسوية الطبقة مستقل عن المقياس‪ .‬هذا هو‪ ،‬لدينا )𝐱𝛼(‪ LN(𝐱) ≈ LN‬ألي خيار ‪.𝛼 ≠ 0‬‬
‫تصبح هذه مساواة لـ ∞ → |𝛼| (المساواة التقريبية ترجع إلى االزاحة 𝜖 لتعويض التباين)‪.‬‬

‫ميزة أخرى لتسوية الطبقة هي أنها ال تعتمد على حجم الدفعات الصغيرة‪ .‬كما أنها مستقلة عما‬
‫إذا كنايف تدريب أو نظام اختبار‪ .‬بمعنى آخر‪ ،‬إنه ببساطة تحول حتمي يوحد التنشيطات إلى مقياس‬
‫معين‪ .‬يمكن أن يكون هذا مفيدًا جدًايف منع التباعديف التحسين‪ .‬نتخطى المزيد من التفاصيل‬
‫ونوصي القارئ المهتم بالرجوع إلى المقالة األصلية‪.‬‬

‫‪Batch Normalization During Prediction‬‬ ‫‪8.5.2.4‬‬


‫كما ذكرنا سابقًا‪ ،‬عادةً ما يتصرف تسوية الدُفعات بشكل مختلفيف وضع التدريب ووضع التنبؤ‪.‬‬
‫أوالً‪ ،‬لم يعد الضجيجيف متوسط العينة وتباين العينة الناتج عن تقدير كل منها على الدفعات‬
‫الصغيرة مرغوبًا بعد أن نقوم بتدريب النموذج‪ .‬ثانيًا‪ ،‬قد ال نتمتع برفاهية حساب إحصائيات‬
‫التسوية لكل دفعة‪ .‬على سبيل المثال‪ ،‬قد نحتاج إلى تطبيق نموذجنا لعمل تنبؤ واحديف كل مرة‪.‬‬

‫عادةً‪ ،‬بعد التدريب‪ ،‬نستخدم مجموعة البيانات بأكملها لحساب التقديرات الثابتة لإلحصاءات‬
‫المتغيرة ثم إصالحهايف وقت التنبؤ‪ .‬وبالتالي‪ ،‬فإن تسوية الدُفعات يتصرف بشكل مختلف أثناء‬
‫التدريب وفي وقت االختبار‪ .‬تذكر أن التسرب يعرض أيضًا هذه الخاصية‪.‬‬

‫‪Implementation from Scratch‬‬ ‫‪8.5.3‬‬


‫لمعرفة كيفية عمل تسوية الدُفعات عمليًا‪ ،‬نطبق واحدًا من البداية أدناه‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪134‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬

‫‪def batch_norm(X, gamma, beta, moving_mean, moving_var,‬‬


‫‪eps):‬‬
‫‪# Compute reciprocal of square root of the moving‬‬
‫‪variance elementwise‬‬
‫‪inv = tf.cast(tf.math.rsqrt(moving_var + eps),‬‬
‫)‪X.dtype‬‬
‫‪# Scale and shift‬‬
‫‪inv *= gamma‬‬
‫)‪Y = X * inv + (beta - moving_mean * inv‬‬
‫‪return Y‬‬
‫يمكننا اآلن إنشاء طبقة ‪ BatchNorm‬مناسبة‪ .‬ستحتفظ طبقتنا بالمعلمات المناسبة لمقياس‬
‫‪ gamma‬وتحويل ‪ ،beta‬وسيتم تحديث كالهما أثناء التدريب‪ .‬باإلضافة إلى ذلك‪ ،‬ستحافظ‬
‫طبقتنا على المتوسطات واالنحرافات المعيارية المتحركة لالستخدام الالحق أثناء تنبؤ النموذج‪.‬‬

‫بوضع تفاصيل الخوارزمية جانبًا‪ ،‬الحظ نمط التصميم الذي يقوم عليه تنفيذنا للطبقة‪ .‬عادةً‪،‬‬
‫نحدد الرياضياتيف دالة منفصلة‪ ،‬على سبيل المثال ‪ .batch_norm‬نقوم بعد ذلك بدمج هذه‬
‫الدالةيف طبقة مخصصة ‪ ،custom layer‬والتي يعالج كودهايف الغالب مسائل مسك الدفاتر‬
‫‪ ،bookkeeping‬مثل نقل البيانات إلى سياق الجهاز الصحيح‪ ،‬وتخصيص أي متغيرات مطلوبة‬
‫وتهيئتها‪ ،‬وتتبع المتوسطات المتحركة (هنا للمتوسط والتباين)‪ ،‬وما إلى ذلك‪ .‬يتيح هذا النمط‬
‫فصلًا نظيفًا للرياضيات عن الكود المعياري‪ .‬الحظ أيضًا أنه من أجل السهولة‪ ،‬لم نقلق بشأن‬
‫االستنتاج التل قائي لشكل اإلدخال هنا‪ ،‬وبالتالي نحتاج إلى تحديد عدد الميزات طوال الوقت‪.‬يف ‬
‫الوقت الحالي‪ ،‬توفر جميع أطر التعلم العميق الحديثة اكتشافًا تلقائيًا للحجم والشكليف واجهات‬
‫برمجة تطبيقات ‪ API‬تسوية الدُفعات عالية المستوى (في الواقع‪ ،‬سنستخدم هذا بدالً من ذلك)‪.‬‬

‫‪class BatchNorm(tf.keras.layers.Layer):‬‬
‫‪def __init__(self, **kwargs):‬‬
‫)‪super(BatchNorm, self).__init__(**kwargs‬‬

‫‪def build(self, input_shape):‬‬


‫] ‪weight_shape = [input_shape[-1],‬‬
‫‪# The scale parameter and the shift parameter‬‬
‫‪(model parameters) are‬‬
‫‪# initialized to 1 and 0, respectively‬‬
‫‪self.gamma = self.add_weight(name='gamma',‬‬
‫‪shape=weight_shape,‬‬
135 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

initializer=tf.initializers.ones,
trainable=True)
self.beta = self.add_weight(name='beta',
shape=weight_shape,
initializer=tf.initializers.zeros,
trainable=True)
# The variables that are not model parameters
are initialized to 0
self.moving_mean =
self.add_weight(name='moving_mean',
shape=weight_shape,
initializer=tf.initializers.zeros,
trainable=False)
self.moving_variance =
self.add_weight(name='moving_variance',
shape=weight_shape,
initializer=tf.initializers.ones,
trainable=False)
super(BatchNorm, self).build(input_shape)

def assign_moving_average(self, variable, value):


momentum = 0.1
delta = (1.0 - momentum) * variable + momentum *
value
return variable.assign(delta)

@tf.function
def call(self, inputs, training):
if training:
axes = list(range(len(inputs.shape) - 1))
batch_mean = tf.reduce_mean(inputs, axes,
keepdims=True)
batch_variance =
tf.reduce_mean(tf.math.squared_difference(
inputs, tf.stop_gradient(batch_mean)),
axes, keepdims=True)
batch_mean = tf.squeeze(batch_mean, axes)
batch_variance = tf.squeeze(batch_variance,
axes)
mean_update = self.assign_moving_average(
self.moving_mean, batch_mean)
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 136

variance_update =
self.assign_moving_average(
self.moving_variance, batch_variance)
self.add_update(mean_update)
self.add_update(variance_update)
mean, variance = batch_mean, batch_variance
else:
mean, variance = self.moving_mean,
self.moving_variance
output = batch_norm(inputs, moving_mean=mean,
moving_var=variance,
beta=self.beta, gamma=self.gamma, eps=1e-5)
return output
‫ هذه‬.‫ للتحكميف التجميع على تقديرات المتوسط والتباين السابقة‬momentum ‫استخدمنا الزخم‬
‫ إلى حد ما حيث ال عالقة لها على اإلطالق بمصطلح الزخم‬misnomer ‫تسمية خاطئة‬
‫ فهو االسم المعتمد بشكل شائع‬،‫ ومع ذلك‬.12.6 ‫يف التحسينيف القسم‬momentum term
‫ نستخدم نفس اسم المتغيريف التعليمات البرمجية‬،API ‫ وإحترامًا التفاقية تسمية‬،‫لهذا المصطلح‬
.‫الخاصة بنا أيضًا‬

LeNet 8.5.4
‫ التقليدي‬LeNet ‫ نطبقه أدناه على نموذج‬،‫في السياق‬BatchNorm ‫لمعرفة كيفية تطبيق‬
‫ تذكر أنه يتم تطبيق تسوية الدفعات بعد الطبقات التالفيفية أو الطبقات المتصلة‬.) 7.6 ‫(القسم‬
.‫بالكامل ولكن قبل دوال التنشيط المقابلة‬

class BNLeNetScratch(d2l.Classifier):
def __init__(self, lr=0.1, num_classes=10):
super().__init__()
self.save_hyperparameters()
self.net = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=6,
kernel_size=5,
input_shape=(28, 28,
1)),
BatchNorm(),
tf.keras.layers.Activation('sigmoid'),
tf.keras.layers.AvgPool2D(pool_size=2,
strides=2),
tf.keras.layers.Conv2D(filters=16,
kernel_size=5),
137 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

BatchNorm(),
tf.keras.layers.Activation('sigmoid'),
tf.keras.layers.AvgPool2D(pool_size=2,
strides=2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(120),
BatchNorm(),
tf.keras.layers.Activation('sigmoid'),
tf.keras.layers.Dense(84), BatchNorm(),
tf.keras.layers.Activation('sigmoid'),
tf.keras.layers.Dense(num_classes)])
‫ هذا الكود‬.Fashion-MNIST ‫ سنقوم بتدريب شبكتنا على مجموعة بيانات‬،‫كمايف السابق‬
.‫ ألول مرة‬LeNet ‫مطابق تقريبًا لذلك عندما قمنا بتدريب‬

trainer = d2l.Trainer(max_epochs=10)
data = d2l.FashionMNIST(batch_size=128)
with d2l.try_gpu():
model = BNLeNetScratch(lr=0.5)
trainer.fit(model, data)

shift ( ‫ ومعامل التحويل‬gamma )scale parameter( ‫دعونا نلقي نظرة على معلمة المقياس‬
.‫ الذي تم تعلمه من طبقة تسوية الدفعة األولى‬beta )parameter
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 138

tf.reshape(model.net.layers[1].gamma, (-1,)),
tf.reshape(
model.net.layers[1].beta, (-1,))
(<tf.Tensor: shape=(6,), dtype=float32, numpy=
array([4.5314302, 2.9945924, 2.1465805, 2.1390676,
3.5647843, 2.0847673],
dtype=float32)>,
<tf.Tensor: shape=(6,), dtype=float32, numpy=
array([ 0.21811652, -0.152415 , -1.0798329 , -
1.2022917 , -0.03723535,
-0.7957938 ], dtype=float32)>)
Concise Implementation 8.5.5
‫ يمكننا استخدام كالس‬،‫ التي حددناها بأنفسنا للتو‬،BatchNorm ‫بالمقارنة مع كالس‬
‫ المحددةيف واجهات برمجة التطبيقات عالية المستوى من إطار عمل التعلم‬BatchNorm
‫ باستثناء أننا لم نعد بحاجة إلى تقديم‬،‫ يبدو الرمز مطابقًا تقريبًا لتطبيقنا أعاله‬.‫العميق مباشرة‬
.‫وسيطات إضافية له للحصول على األبعاد الصحيحة‬

class BNLeNet(d2l.Classifier):
def __init__(self, lr=0.1, num_classes=10):
super().__init__()
self.save_hyperparameters()
self.net = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(filters=6,
kernel_size=5,
input_shape=(28, 28,
1)),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Activation('sigmoid'),
tf.keras.layers.AvgPool2D(pool_size=2,
strides=2),
tf.keras.layers.Conv2D(filters=16,
kernel_size=5),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Activation('sigmoid'),
tf.keras.layers.AvgPool2D(pool_size=2,
strides=2),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(120),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Activation('sigmoid'),
‫‪139‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪tf.keras.layers.Dense(84),‬‬
‫‪tf.keras.layers.BatchNormalization(),‬‬
‫‪tf.keras.layers.Activation('sigmoid'),‬‬
‫)])‪tf.keras.layers.Dense(num_classes‬‬
‫أدناه‪ ،‬نستخدم نفس المعلمات الفائقة لتدريب نموذجنا‪ .‬الحظ أنه كالعادة‪ ،‬يعمل متغير واجهة‬
‫برمجة التطبيقات عالي المستوى بشكل أسرع نظرًا ألن كوده قد تم تجميعه إلى ‪ C++‬أو‬
‫‪ CUDA‬بينما يجب تفسير تطبيقنا المخصص بواسطة بايثون‪.‬‬

‫)‪trainer = d2l.Trainer(max_epochs=10‬‬
‫)‪data = d2l.FashionMNIST(batch_size=128‬‬
‫‪with d2l.try_gpu():‬‬
‫)‪model = BNLeNet(lr=0.5‬‬
‫)‪trainer.fit(model, data‬‬

‫‪8.5.6‬‬
‫بشكل بديهي‪ ،‬يُعتقد أن تسوية الدُفعات ‪ batch normalization‬تجعل مشهد التحسين أكثر‬
‫سالسة‪ .‬ومع ذلك‪ ،‬يجب أن نكون حريصين على التمييز بين الحدس التأملي والتفسيرات‬
‫الحقيقية للظواهر التي نالحظها عند تدريب النماذج العميقة‪ .‬تذكر أننا ال نعرف حتى لماذا تعمم‬
‫الشبكات العصبية العميقة األبسط (‪ MLPs‬و‪ CNN‬التقليدية) جيدًايف المقام األول‪ .‬حتى مع‬
‫التسرب ‪ dropout‬وتناقص الوزن ‪ ،weight decay‬فإنها تظل مرنة للغاية لدرجة أن قدرتها‬
‫على التعميم على البيانات غير المرئية تحتاج على األرجح إلى ضمانات تعلم نظرية أكثر دقة‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪140‬‬

‫في المقالة األصلية التي اقترحت تسوية الدُفعات ( ‪ ، )2015 ،Ioffe and Szegedy‬باإلضافة‬
‫إلى تقديم أداة قوية ومفيدة‪ ،‬قدمت شرحًا لسبب نجاحها‪ :‬عن طريق تقليل التحول المتغير‬
‫الداخلي ‪ .internal covariate shift‬من المفترض أن المؤلفين قصدوا عن طريق التحول‬
‫الداخلي المتغير شيئًا مثل الحدس المعبر عنه أعاله ‪ -‬فكرة أن توزيع القيم المتغيرة يتغير على‬
‫مدار التدريب‪ .‬ومع ذلك‪ ،‬كانت هناك مشكلتانيف هذا التفسير‪ )1 :‬هذا االنجراف ‪ drift‬مختلف‬
‫تمامًا عن التحول المتغير‪ ،‬مما يجعل االسم تسمية خاطئة ‪ .misnomer‬إذا كان هناك أي شيء‪،‬‬
‫فهو أقرب إلى مفهوم االنجراف‪ )2 .‬يقدم التفسير حدسًا غير محدد ولكنه يترك السؤال عن سبب‬
‫نجاح هذه التقنية تحديدًايف سؤال مفتوح يحتاج إلى تفسير دقيق‪.‬يف هذا الكتاب‪ ،‬نهدف إلى نقل‬
‫الحدس الذي يستخدمه الممارسون لتوجيه تطورهم للشبكات العصبية العميقة‪ .‬ومع ذلك‪ ،‬نعتقد‬
‫أنه من المهم فصل هذه البديهيات التوجيهية عن الحقائق العلمية الراسخة‪.‬يف النهاية‪ ،‬عندما تتقن‬
‫هذه المادة وتبدأيف كتابة أوراقك البحثية الخاصة‪ ،‬سترغبيف أن تكون واضحًايف التحديد بين‬
‫االدعاءات التقنية والحدس‪.‬‬

‫بعد نجاح تسوية الدفعات‪ ،‬ظهر تفسيره من حيث التحول الداخلي المتغير مرارًا وتكرارًايف ‬
‫المناقشاتيف األدبيات الفنية والخطاب األوسع حول كيفية تقديم أبحاث التعلم اآللي‪.‬يف خطاب‬
‫ال يُنسى ألقاه أثناء قبوله جائزة اختبار الوقت ‪Test of Time Award‬يف مؤتمر ‪NeurIPS‬‬
‫‪ ،2017‬استخدم علي رحيمي التحول الداخلي المشترك ‪ internal covariate shift‬كنقطة‬
‫محوريةيف حجة تشبه الممارسة الحديثة للتعلم العميق بالكيمياء‪ .‬بعد ذلك‪ ،‬تمت إعادة النظريف ‬
‫المثال بالتفصيليف ورقة موقف تحدد االتجاهات المثيرة للقلقيف التعلم اآللي (ليبتون‬
‫وشتاينهاردت‪ .)2018 ،‬اقترح مؤلفون آخرون تفسيرات بديلة لنجاح تسوية الدُفعات‪ ،‬حيث زعم‬
‫البعض أن نجاح التسوية على دفعات يأتي على الرغم من إظهار سلوك يتعارض من بعض النواحي‬
‫مع تلك التي زُعمتيف المقالة األصلية (‪.)2018 ،Santurkar et al.‬‬

‫نالحظ أن التحول المتغير الداخلي ال يستحق النقد أكثر من أي من آالف االدعاءات الغامضة‬
‫ال مماثلة التي يتم تقديمها كل عاميف أدبيات التعلم اآللي التقنية‪ .‬على األرجح‪ ،‬فإن صدى هذه‬
‫النقاشات كنقطة محوريةيف هذه المناقشات يرجع إلى التعرف الواسع على الجمهور المستهدف‪.‬‬
‫أثبت تسوية الدُفعات أنه أسلوب ال غنى عنه‪ ،‬تم تطبيقهيف جميع مصنفات الصور المنشورة تقريبًا‪،‬‬
‫مما أكسب المقالة التي قدمت التقنية عشرات اآلالف من االستشهادات‪ .‬ومع ذلك‪ ،‬فإننا نخمّن‬
‫أن المبادئ التوجيهية للتنظيم من خالل حقن الضوضاء والتسريع من خالل إعادة القياس‬
‫والمعالجة المسبقة أخيرًا قد تؤدي إلى المزيد من االختراعات للطبقات والتقنياتيف المستقبل‪.‬‬

‫في مالحظة أكثر عملية‪ ،‬هناك عدد من الجوانب ‪ aspects‬التي تستحق التذكر حول تسوية‬
‫الدُفعات‪:‬‬
‫‪141‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫أثناء تدريب النموذج‪ ،‬يضبط تسوية الدُفعات باستمرار اإلخراج الوسيط للشبكة من‬ ‫•‬
‫خالل استخدام المتوسط واالنحراف المعياري للدفعات الصغيرة‪ ،‬بحيث تكون قيم‬
‫المخرجات الوسيطةيف كل طبقة عبر الشبكة العصبية أكثر استقرارًا‪.‬‬
‫تختلف تسوية الدُفعات للطبقات المتصلة تمامًا والطبقات التالفيفية قليالً‪.‬يف الواقع‪،‬‬ ‫•‬
‫بالنسبة للطبقات التالفيفية‪ ،‬يمكن أحيانًا استخدام تسوية الطبقة كبديل‪.‬‬
‫مثل طبقة التسرب ‪ ،dropout layer‬فإن طبقات تسوية الدفعات لها سلوكيات‬ ‫•‬
‫مختلفةيف وضع التدريب ووضع التنبؤ‪.‬‬
‫يعد تسوية الدُفعات مفيدًا للتنظيم وتحسين التقاربيف التحسين‪ .‬من ناحية أخرى‪،‬‬ ‫•‬
‫يبدو أن الدافع األصلي لتقليل التحول المتغير الداخلي ليس تفسيرًا صالحًا‪.‬‬

‫‪8.5.7‬‬
‫‪ .1‬هل يجب إزالة معلمة التحيز من الطبقة المتصلة بالكامل أو الطبقة التالفيفية قبل تسوية‬
‫الدُفعة؟ لماذا؟‬
‫‪ .2‬قارن معدالت التعلم لـ ‪ LeNet‬مع أو بدون تسوية الدفعات‪.‬‬
‫‪ .1‬ارسم الزيادةيف دقة التحقق من الصحة ‪.validation accuracy‬‬
‫‪ .2‬ما الحجم الذي يمكنك جعل معدل التعلم قبل فشل التحسينيف كلتا الحالتين؟‬
‫‪ .3‬هل نحتاج إلى تسوية الدفعاتيف كل طبقة؟ جربها؟‬
‫‪ .4‬قم بتنفيذ إصدار "خفيف ‪ "lite‬من تسوية الدُفعات الذي يزيل فقط المتوسط ‪ ،‬أو بدالً‬
‫من ذلك يزيل التباين فقط‪ .‬كيف تتصرف؟‬
‫‪ .5‬إصلح معلمات ‪ beta‬و ‪ .gamma‬راقب وحلل النتائج‪.‬‬
‫‪ .6‬هل يمكنك استبدال التسرب ‪ dropout‬بتسوية الدفعات؟ كيف يتغير السلوك؟‬
‫‪ .7‬أفكار البحث‪ :‬فكريف تحوالت التسوية األخرى التي يمكنك تطبيقها‪:‬‬
‫‪ .1‬هل يمكنك تطبيق التحويل المتكامل االحتمالي ‪probability integral‬‬
‫‪transform‬؟‬
‫‪ .2‬هل يمكنك استخدام تقدير التغاير ‪ covariance estimate‬الكامل للرتبة؟‬
‫لماذا ربما ال تفعل ذلك؟‬
‫‪ .3‬هل يمكنك استخدام متغيرات مصفوفة مضغوطة ‪compact matrix‬‬
‫‪ variants‬أخرى (كتلة قطرية ‪ ،block-diagonal‬رتبة إزاحة منخفضة‬
‫‪ ،low-displacement rank‬مونارك ‪ ،Monarch‬إلخ)؟‬
‫‪sparsification compression‬كمنظم‬ ‫‪ .4‬هل يعمل ضغط التناثر‬
‫‪regularizer‬؟‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪142‬‬

‫‪ .5‬هل هناك توقعات أخرى (على سبيل المثال‪ ،‬مخروط محدب ‪convex‬‬
‫‪ ،cone‬وتحويالت خاصة بمجموعة تناظر ‪symmetry group-specific‬‬
‫‪ )transforms‬يمكنك استخدامها؟‬

‫‪Residual Networks ResNeXt ResNet‬‬ ‫‪8.6‬‬


‫نظرًا ألننا نصمم شبكات أعمق بشكل متزايد‪ ،‬يصبح من الضروري فهم كيف يمكن أن تؤدي‬
‫إضافة الطبقات إلى زيادة تعقيد الشبكة وتعبيرها‪ .‬واألهم من ذلك هو القدرة على تصميم‬
‫الشبكات حيث تؤدي إضافة الطبقات إلى جعل الشبكات أكثر تعبيرًا بشكل صارم بدالً من‬
‫االختالف فقط‪ .‬إلحراز بعض التقدم نحتاج إلى القليل من الرياضيات‪.‬‬

‫‪Function Classes‬‬ ‫‪8.6.1‬‬


‫ضعيف اعتبارك ‪ ℱ‬فئة الدوال ‪ Function Classes‬التي يمكن أن تصل إليها بُنية شبكة معينة‬
‫(جنبًا إلى جنب مع معدالت التعلم وإعدادات المعلمات الفائقة األخرى)‪ .‬وهذا يعني لكل ∈ 𝑓‬
‫‪ ℱ‬أنه توجد مجموعة من المعلمات (على سبيل المثال‪ ،‬األوزان والتحيزات) التي يمكن الحصول‬
‫عليها من خالل التدريب على مجموعة بيانات مناسبة‪ .‬لنفترض أن هذه ∗ 𝑓 هي دالة "الحقيقة‬
‫‪ "truth‬التي نود حقًا العثور عليها‪ .‬إذا كانيف ‪ ، ℱ‬فنحنيف حالة جيدة ولكنيف العادة لن نكون‬
‫محظوظين جدًا‪ .‬بدالً من ذلك‪ ،‬سنحاول العثور على بعض ∗‪ 𝑓ℱ‬وهو أفضل رهانيف ‪ .ℱ‬على سبيل‬
‫المثال‪ ،‬نظرًا لمجموعة بيانات تحتوي على ميزات 𝐗 وتسميات 𝐲‪ ،‬فقد نحاول العثور عليها من‬
‫خالل حل مشكلة التحسين التالية‪:‬‬

‫‪def‬‬
‫‪𝑓ℱ∗ = argmin 𝐿(𝐗, 𝐲, 𝑓) subject to 𝑓 ∈ ℱ.‬‬
‫𝑓‬

‫نحن نعلم أن التنظيم ‪،Tikhonov and Arsenin ،1984 ،Morozov( regularization‬‬


‫‪ )1977‬قد يتحكميف تعقيد ‪ ℱ‬ويحقق االتساق ‪ ،consistency‬لذا فإن الحجم األكبر لبيانات‬
‫التدريب يؤدي عمومًا إلى تحسين ∗‪ .𝑓ℱ‬من المعقول فقط أن نفترض أنه إذا صممنا بُنية مختلفة‬
‫وأكثر قوة ‪ ،ℱ ′‬يجب أن نصل إلى نتيجة أفضل‪ .‬بعبارة أخرى‪ ،‬نتوقع ‪ 𝑓ℱ∗′‬أفضل من ∗‪ .𝑓ℱ‬ومع‬
‫ذلك‪ ،‬إذا ‪ ℱ ⊈ ℱ ′‬لم يكن هناك ما يضمن حدوث ذلك‪.‬يف الواقع‪ 𝑓ℱ∗′ ،‬قد يكون أسوأ‪ .‬كما هو‬
‫موضحيف الشكل ‪ ،8.6.1‬بالنسبة لفئات الدوال غير المتداخلة‪ ،‬ال تقترب فئة الدالة األكبر دائمًا‬
‫من دالة "الحقيقة" ∗ 𝑓‪ .‬على سبيل المثال‪ ،‬على يسار الشكل ‪ ،8.6.1‬على الرغم من أن ‪ ℱ3‬أقرب‬
‫إلى ∗ 𝑓 من ‪ ،ℱ1‬فإنه يتحرك بعيدًا وليس هناك ما يضمن أن زيادة التعقيد يمكن أن تقلل المسافة‬
‫‪143‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫من ∗ 𝑓‪ .‬مع فئات الدوال المتداخلة حيث ‪ ℱ1 ⊆ ⋯ ⊆ ℱ6‬على يمين الشكل ‪ ،8.6.1‬يمكننا‬
‫تجنب المشكلة المذكورة أعاله من فئات الدوال غير المتداخلة‪.‬‬

‫الشكل ‪ 8.6.1‬بالنسبة لفئات الدوال غير المتداخلة‪ ،‬ال تضمن فئة الدالة األكبر (المشار إليها‬
‫بالمنطقة) االقتراب من دالة "الحقيقة" (∗ 𝑓)‪ .‬هذا ال يحدثيف فئات الدوال المتداخلة‪.‬‬

‫وبالتالي‪ ،‬فقط إذا كانت فئات الدوال األكبر تحتوي على الفئات األصغر‪ ،‬فإننا نضمن أن زيادتها‬
‫يزيد بشكل صارم من القوة التعبيرية للشبكة‪ .‬بالنسبة للشبكات العصبية العميقة‪ ،‬إذا تمكنا من‬
‫تدريب الطبقة المضافة حديثًا على دالة هوية ‪ ,𝑓(𝐱) = 𝐱،identity function‬فسيكون‬
‫النموذج الجديد فعالًا مثل النموذج األصلي‪ .‬نظرًا ألن النموذج الجديد قد يحصل على حل أفضل‬
‫يناسب مجموعة بيانات التدريب‪ ،‬فقد تسهل الطبقة المضافة تقليل أخطاء التدريب‪.‬‬

‫هذا هو السؤال الذي أخذيف االعتبار (‪ )2016 ،He et al.‬عند العمل على نماذج رؤية حاسوبية‬
‫عميقة جدًا‪.‬يف قلب شبكتهم المتبقية المقترحة (‪ )ResNet‬هي فكرة أن كل طبقة إضافية يجب‬
‫أن تحتوي بسهولة أكبر على دالة الهوية كأحد عناصرها‪ .‬هذه االعتبارات عميقة إلى حد ما لكنها‬
‫أدت إلى حل بسيط بشكل مدهش‪ ،‬وهو الكتلة المتبقية ‪ .residual block‬مع ذلك‪ ،‬فازت شبكة‬
‫‪ ResNet‬بتحدي التعرف البصري على نطاق واسع على ‪ImageNet‬يف عام ‪ .2015‬كان‬
‫للتصميم تأثير عميق على كيفية بناء شبكات عصبية عميقة‪ .‬على سبيل المثال‪ ،‬تمت إضافة الكتل‬
‫المتبقية إلى الشبكات المتكررة ‪.)2016 ،Prakash et al. ،2017 ،Kim et al.( RNN‬‬
‫وبالمثل‪ ،‬فإن المحوالت ‪ )2017 ،Vaswani et al.( transformers‬تستخدمها لتكديس‬
‫طبقات عديدة من الشبكات بكفاءة‪ .‬يتم استخدامه أيضًايف الشبكات العصبية للرسم البياني‬
‫‪ )2016 ،Kipf and Welling( graph neural networks‬وكمفهوم أساسي‪ ،‬فقد تم‬
‫استخدامه على نطاق واسعيف الرؤية الحاسوبية (‪Ren et ،2018 ،Redmon and Farhadi‬‬
‫‪ .) 2015 ،al.‬الحظ أن الشبكات المتبقية سبقتها شبكات الطرق السريعة ‪highway networks‬‬
‫(‪ )2015 ،Srivastava et al.‬التي تشتركيف بعض الدوافع‪ ،‬وإن كان ذلك بدون تحديد معلمات‬
‫أنيقة حول دالة الهوية‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪144‬‬

‫‪Residual Blocks‬‬ ‫‪8.6.2‬‬


‫دعونا نركز على جزء محلي من الشبكة العصبية‪ ،‬كما هو موضحيف الشكل ‪ .8.6.2‬داللة على‬
‫المدخالت 𝐱‪ .‬نفترض أن التعيين األساسي المطلوب الذي نريد الحصول عليه من خالل التعلم‬
‫هو )𝐱(𝑓‪ ،‬الستخدامه كمدخل لدالة التنشيطيف األعلى‪ .‬على اليسار‪ ،‬يجب أن يتعرف الجزء‬
‫الموجود داخل المربع ذي الخطوط المنقطة على المطابقة (التعيين) )𝐱(𝑓 مباشرةً‪ .‬على اليمين‪،‬‬
‫يحتاج الجزء الموجود داخل المربع ذي الخطوط المنقطة إلى معرفة التعيين المتبقي = )𝐱(𝑔‬
‫𝐱 ‪ ،𝑓(𝐱) −‬وهو كيفية اشتقاق الكتلة المتبقية اسمها‪ .‬إذا كان تعيين الهوية 𝐱 = )𝐱(𝑓 هو‬
‫التعيين األساسي المرغوب فيه‪ ،‬فإن التعيين المتبقي يصل إلى ‪ 𝑔(𝐱) = 0‬وبالتالي يسهل تعلمه‪:‬‬
‫نحتاج فقط إلى دفع األوزان والتحيزات الخاصة بطبقة الوزن األعلى (على سبيل المثال‪ ،‬الطبقة‬
‫المتصلة بالكامل والطبقة التالفيفية) داخل المنطقة المنقطة مربع خط إلى الصفر‪ .‬يوضح الشكل‬
‫األيمن الكتلة المتبقية لـ ‪ ،ResNet‬حيث يُطلق على الخط الصلب الذي يحمل إدخال الطبقة‬
‫إلى عامل اإلضافة اتصال متبقي ‪( residual connection‬أو اتصال اختصار ‪shortcut‬‬
‫‪ .)connection‬مع الكتل المتبقية ‪ ،residual blocks‬يمكن للمدخالت أن تنتشر بشكل أسرع‬
‫من خالل االتصاالت المتبقية عبر الطبقات‪.‬يف الواقع‪ ،‬يمكن اعتبار الكتلة المتبقية كحالة خاصة‬
‫لكتلة التأسيس متعددة الفروع ‪ :multi-branch Inception block‬لها فرعين أحدهما هو‬
‫تعيين الهوية ‪.identity mapping‬‬

‫الشكل ‪8.6.2‬يف الكتلة العادية (على اليسار)‪ ،‬يجب أن يتعلم الجزء الموجود داخل المربع ذي‬
‫الخطوط المنقطة تعيين )𝐱(𝑓 مباشرةً‪.‬يف الكتلة المتبقية (على اليمين)‪ ،‬يحتاج الجزء الموجود‬
‫داخل المربع ذي الخطوط المنقطة إلى معرفة التعيين المتبقي 𝐱 ‪ ،𝑔(𝐱) = 𝑓(𝐱) −‬مما يسهل‬
‫تعلم تعيين الهوية 𝐱 = )𝐱(𝑓‪.‬‬
145 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

‫ تحتوي الكتلة المتبقية على‬.VGG ‫ الكامل لـ‬3 × 3 ‫ تصميم الطبقة التالفيفية‬ResNet ‫تتبع‬
‫ تتبع كل طبقة تالفيفية طبقة تسوية دفعية‬.‫ بنفس عدد قنوات اإلخراج‬3 × 3 ‫طبقتين تالفيفيتين‬
‫ نتخطى عمليتي االلتفاف هاتين ونضيف اإلدخال مباشرةً قبل‬،‫ بعد ذلك‬.ReLU ‫ودالة تنشيط‬
‫ يتطلب هذا النوع من التصميم أن يكون ناتج الطبقتين التالفيفيتين‬.‫ النهائية‬ReLU ‫دالة تنشيط‬
‫ فنحن‬،‫ إذا أردنا تغيير عدد القنوات‬.‫ بحيث يمكن إضافتهما معًا‬،‫من نفس شكل المدخالت‬
‫ إضافية لتحويل المدخالت إلى الشكل المطلوب لعملية‬1 × 1 ‫بحاجة إلى إدخال طبقة تالفيفية‬
.‫ دعونا نلقي نظرة على الكود أدناه‬.‫اإلضافة‬

import tensorflow as tf
from d2l import tensorflow as d2l

class Residual(tf.keras.Model): #@save


"""The Residual block of ResNet."""
def __init__(self, num_channels, use_1x1conv=False,
strides=1):
super().__init__()
self.conv1 =
tf.keras.layers.Conv2D(num_channels, padding='same',

kernel_size=3, strides=strides)
self.conv2 =
tf.keras.layers.Conv2D(num_channels, kernel_size=3,

padding='same')
self.conv3 = None
if use_1x1conv:
self.conv3 =
tf.keras.layers.Conv2D(num_channels, kernel_size=1,

strides=strides)
self.bn1 = tf.keras.layers.BatchNormalization()
self.bn2 = tf.keras.layers.BatchNormalization()

def call(self, X):


Y =
tf.keras.activations.relu(self.bn1(self.conv1(X)))
Y = self.bn2(self.conv2(Y))
if self.conv3 is not None:
X = self.conv3(X)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪146‬‬

‫‪Y += X‬‬
‫)‪return tf.keras.activations.relu(Y‬‬
‫يولد هذا الرمز نوعين من الشبكات‪ :‬أحدهما حيث نضيف المدخالت إلى المخرجات قبل تطبيق‬
‫دالة ‪ ReLU‬الالخطيةكلما ‪ ،use_1x1conv=False‬واآلخر حيث نعدل القنوات والدقة‬
‫عن طريق متوسطات االلتفاف ‪ 1 × 1‬قبل اإلضافة‪ .‬يوضح الشكل ‪ 8.6.3‬هذا‪.‬‬

‫الشكل ‪ 8.6.3‬فدرة ‪ ResNet‬مع االلتفاف ‪ 1 × 1‬وبدونه‪ ،‬والذي يحول اإلدخال إلى الشكل‬
‫المطلوب لعملية اإلضافة‪.‬‬

‫)‪blk = Residual(3‬‬
‫))‪X = tf.random.normal((4, 6, 6, 3‬‬
‫)‪Y = blk(X‬‬
‫‪Y.shape‬‬
‫)]‪TensorShape([4, 6, 6, 3‬‬

‫لدينا أيضًا خيار خفض ارتفاع وعرض اإلخراج إلى النصف مع زيادة عدد قنوات اإلخراج‪.‬يف ‬
‫هذه الحالة‪ ،‬نستخدم التالفيف ‪ 1 × 1‬عبر ‪ .use_1x1conv=True‬يكون هذا مفيدًايف بداية‬
‫كل كتلة ‪ ResNet‬لتقليل األبعاد المكانية ‪ spatial dimensionality‬عبر الخطوات = ‪.2‬‬

‫)‪blk = Residual(6, use_1x1conv=True, strides=2‬‬


‫‪blk(X).shape‬‬
‫)]‪TensorShape([4, 3, 3, 6‬‬
‫‪147‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪ResNet‬‬ ‫‪8.6.3‬‬
‫أول طبقتين من ‪ ResNet‬هما نفس طبقات ‪ GoogLeNet‬التي وصفناها من قبل‪ :‬الطبقة‬
‫التالفيفية ‪ 7 × 7‬مع ‪ 64‬قناة إخراج وخطوة ‪ 2‬متبوعة بطبقة تجميع الحد األقصى ‪ 3 × 3‬بخطوة‬
‫‪ .2‬والفرق هو تسوية الدُفعات تمت إضافة طبقة بعد كل طبقة تالفيفيةيف ‪.ResNet‬‬

‫‪class ResNet(d2l.Classifier):‬‬
‫‪def b1(self):‬‬
‫[(‪return tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.Conv2D(64, kernel_size=7,‬‬
‫‪strides=2,‬‬
‫‪padding='same'),‬‬
‫‪tf.keras.layers.BatchNormalization(),‬‬
‫‪tf.keras.layers.Activation('relu'),‬‬
‫‪tf.keras.layers.MaxPool2D(pool_size=3,‬‬
‫‪strides=2,‬‬
‫)])'‪padding='same‬‬
‫تستخدم ‪ GoogLeNet‬أربع وحدات مكونة من كتل االستهالل ‪ .Inception‬ومع ذلك‪،‬‬
‫تستخدم شبكة ‪ ResNet‬أربع وحدات مكونة من الكتل المتبقية‪ ،‬يستخدم كل منها عدة كتل‬
‫متبقية مع نفس العدد من قنوات اإلخراج‪ .‬عدد القنواتيف الوحدة األولى هو نفس عدد قنوات‬
‫اإلدخال‪ .‬نظرًا ألنه تم بالفعل استخدام طبقة تجميع بحد أقصى بخطوة ‪ ،2‬فليس من الضروري‬
‫تقليل االرتفاع والعرض‪.‬يف أول كتلة متبقية لكل من الوحدات الالحقة‪ ،‬يتم مضاعفة عدد القنوات‬
‫مقارنةً بالوحدة السابقة‪ ،‬ويتم تقليل االرتفاع والعرض إلى النصف‪.‬‬

‫)‪@d2l.add_to_class(ResNet‬‬
‫‪def block(self, num_residuals, num_channels,‬‬
‫‪first_block=False):‬‬
‫)(‪blk = tf.keras.models.Sequential‬‬
‫‪for i in range(num_residuals):‬‬
‫‪if i == 0 and not first_block:‬‬
‫‪blk.add(Residual(num_channels,‬‬
‫))‪use_1x1conv=True, strides=2‬‬
‫‪else:‬‬
‫))‪blk.add(Residual(num_channels‬‬
‫‪return blk‬‬
‫ثم نضيف جميع الوحدات إلى ‪ .ResNet‬هنا‪ ،‬يتم استخدام كتلتين متبقيتين لكل وحدة‪ .‬أخيرًا‪،‬‬
‫تمامًا مثل ‪ ،GoogLeNet‬نضيف طبقة تجميع المتوسط العالمية‪ ،‬متبوعة بإخراج الطبقة‬
‫المتصلة بالكامل‪.‬‬

‫)‪@d2l.add_to_class(ResNet‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪148‬‬

‫‪def __init__(self, arch, lr=0.1, num_classes=10):‬‬


‫)(__‪super(ResNet, self).__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫))(‪self.net = tf.keras.models.Sequential(self.b1‬‬
‫‪for i, b in enumerate(arch):‬‬
‫)))‪self.net.add(self.block(*b, first_block=(i==0‬‬
‫[(‪self.net.add(tf.keras.models.Sequential‬‬
‫‪tf.keras.layers.GlobalAvgPool2D(),‬‬
‫))])‪tf.keras.layers.Dense(units=num_classes‬‬
‫هناك ‪ 4‬طبقات تالفيفيةيف كل وحدة (باستثناء الطبقة التالفيفية ‪ .)1 × 1‬جنبا إلى جنب مع‬
‫الطبقة التالفيفية األولى والطبقة النهائية المتصلة بالكامل‪ ،‬هناك ‪ 18‬طبقةيف المجموع‪ .‬لذلك‪،‬‬
‫يُعرف هذا النموذج باسم ‪ .ResNet-18‬من خالل تكوين أعداد مختلفة من القنوات والكتل‬
‫المتبقيةيف الوحدة النمطية ‪ ،module‬يمكننا إنشاء نماذج مختلفة من ‪ ،ResNet‬مثل أعمق‬
‫‪152‬طبقة ‪ .ResNet-152‬على الرغم من أن البنية الرئيسية لـ ‪ ResNet‬تشبه بنية‬
‫‪ ،GoogLeNet‬إال أن بنية ‪ ResNet‬أبسط وأسهليف التعديل‪ .‬أدت كل هذه العوامل إلى‬
‫االستخدام السريع والواسع النطاق لشبكة ‪ .ResNet‬الشكل ‪ 8.6.4‬يصور كامل ‪ResNet-‬‬
‫‪.18‬‬

‫الشكل ‪ 8.6.4‬بُنية ‪.ResNet-18‬‬

‫قبل تدريب ‪ ،ResNet‬دعنا نالحظ كيف يتغير شكل اإلدخال عبر وحدات مختلفةيف ‪.ResNet‬‬
‫كما هو الحاليف جميع البنى السابقة‪ ،‬تنخفض الدقة بينما يزداد عدد القنوات ألعلى حتى النقطة‬
‫التي تجمع فيها طبقة تجميع المتوسط العالمي كل المعالم‪.‬‬

‫‪class ResNet18(ResNet):‬‬
‫‪def __init__(self, lr=0.1, num_classes=10):‬‬
‫‪super().__init__(((2, 64), (2, 128), (2, 256),‬‬
‫‪(2, 512)),‬‬
‫)‪lr, num_classes‬‬

‫))‪ResNet18().layer_summary((1, 96, 96, 1‬‬


‫‪149‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪Sequential‬‬ ‫‪output‬‬ ‫‪shape:‬‬ ‫‪(1,‬‬ ‫)‪24, 24, 64‬‬


‫‪Sequential‬‬ ‫‪output‬‬ ‫‪shape:‬‬ ‫‪(1,‬‬ ‫)‪24, 24, 64‬‬
‫‪Sequential‬‬ ‫‪output‬‬ ‫‪shape:‬‬ ‫‪(1,‬‬ ‫)‪12, 12, 128‬‬
‫‪Sequential‬‬ ‫‪output‬‬ ‫‪shape:‬‬ ‫‪(1,‬‬ ‫)‪6, 6, 256‬‬
‫‪Sequential‬‬ ‫‪output‬‬ ‫‪shape:‬‬ ‫‪(1,‬‬ ‫)‪3, 3, 512‬‬
‫‪Sequential‬‬ ‫‪output‬‬ ‫‪shape:‬‬ ‫‪(1,‬‬ ‫)‪10‬‬
‫‪Training‬‬ ‫‪8.6.4‬‬
‫نقوم بتدريب ‪ ResNet‬على مجموعة بيانات ‪ ،Fashion-MNIST‬تمامًا كما كان من قبل‪.‬‬
‫‪ ResNet‬هي بُنية قوية ومرنة‪ .‬يوضح التدريب على التقاط الرسم وخطأ التحقق من الصحة‬
‫وجود فجوة كبيرة بين كال الرسمين البيانيين‪ ،‬حيث يكون خطأ التدريب أقل بكثير‪ .‬للحصول على‬
‫شبكة من هذه المرونة‪ ،‬فإن المزيد من بيانات التدريب ستوفر فائدة كبيرةيف سد الفجوة وتحسين‬
‫الدقة‪.‬‬

‫)‪trainer = d2l.Trainer(max_epochs=10‬‬
‫))‪data = d2l.FashionMNIST(batch_size=128, resize=(96, 96‬‬
‫‪with d2l.try_gpu():‬‬
‫)‪model = ResNet18(lr=0.01‬‬
‫)‪trainer.fit(model, data‬‬

‫‪ResNeXt 8.6.5‬‬
‫أحد التحديات التي يواجهها المرءيف تصميم ‪ResNet‬هو الموازنة ‪ trade-off‬بين الالخطية‬
‫واألبعاد داخل كتلة معينة‪ .‬بمعنى‪ ،‬يمكننا إضافة المزيد من الالخطية عن طريق زيادة عدد‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪150‬‬

‫الطبقات‪ ،‬أو عن طريق زيادة عرض التالفيف‪ .‬تتمثل اإلستراتيجية البديلةيف زيادة عدد القنوات‬
‫التي يمكنها نقل المعلومات بين الكتل‪ .‬لسوء الحظ‪ ،‬يأتي هذا األخير مع عقوبة تربيعية‬
‫‪ quadratic penalty‬ألن التكلفة الحسابية الستيعاب القنوات وقنوات البث تتناسب مع ⋅ 𝑖𝑐(𝒪‬
‫) 𝑜𝑐 (انظر مناقشتنايف القسم ‪.)7.4‬‬

‫يمكننا أخذ بعض اإللهام من كتلة االستهالل ‪Inception block‬يف الشكل ‪ 8.4.1‬الذي يحتوي‬
‫على معلومات تتدفق عبر الكتلةيف مجموعات منفصلة‪ .‬أدى تطبيق فكرة المجموعات المستقلة‬
‫المتعددة على مجموعة ‪ResNet‬يف الشكل ‪ 8.6.3‬إلى تصميم ‪،.Xie et al( ResNeXt‬‬
‫‪ .)2017‬يختلف ‪ ResNeXt‬عن مجموعة التحوالت ‪transformation‬يف البداية‪ ،‬حيث يتبنى‬
‫نفس التحوليف جميع الفروع‪ ،‬مما يقلل من الحاجة إلى الضبط اليدوي لكل فرع‪.‬‬

‫الشكل ‪ 8.6.5‬كتلة ‪ .ResNeXt‬استخدام االلتفاف المجمّع مع المجموعات 𝑔 أسرع 𝑔 مرة‬


‫من االلتفاف الكثيف ‪ .dense convolution‬إنها كتلة بقايا عنق الزجاجة عندما يكون عدد‬
‫القنوات الوسيطة 𝑏 أقل من 𝑐‪.‬‬

‫يُطلق على تقسيم االلتفاف من القنوات 𝑖𝑐 إلى 𝑜𝑐 مجموعة من مجموعات الحجم 𝑔‪ 𝑐𝑖 /‬التي‬
‫تولد مخرجات الحجم 𝑔‪ ،𝑐𝑜 /‬بشكل مناسب تمامًا‪ ،‬االلتفاف المجمّع ‪grouped‬‬
‫‪ .convolution‬يتم تقليل التكلفة الحسابية (بالتناسب) من ) 𝑜𝑐 ⋅ 𝑖𝑐(𝒪 إلى ⋅ )𝑔‪𝒪(𝑔 ⋅ (𝑐𝑖 /‬‬
‫)𝑔‪ ،(𝑐𝑜 /𝑔)) = 𝒪(𝑐𝑖 ⋅ 𝑐𝑜 /‬أي أنها أسرع 𝑔 مرات‪ .‬واألفضل من ذلك‪ ،‬يتم أيضًا تقليل عدد‬
‫المعلمات الالزمة لتوليد اإلخراج من مصفوفة 𝑜𝑐 × 𝑖𝑐 إلى مصفوفات أصغر حجمًا‬
‫‪151‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫)𝑔‪ ،(𝑐𝑖 /𝑔) × (𝑐𝑜 /‬ومرة أخرى يتم تقليلها 𝑔 مرة أخرى‪ .‬فيما يلي نفترض أن كال 𝑖𝑐 و 𝑜𝑐‬
‫يقبل القسمة على 𝑔‪.‬‬

‫التحدي الوحيديف هذا التصميم هو عدم تبادل أي معلومات بين المجموعات 𝑔‪ .‬تعدل كتلة‬
‫‪ResNeXt‬يف الشكل ‪ 8.6.5‬هذا بطريقتين‪ :‬االلتفاف المجمع مع النواة ‪ 3 × 3‬يقع بين التفافين‬
‫‪ .1 × 1‬الثانية تخدم واجب مزدوجيف تغيير عدد القنوات مرة أخرى‪ .‬وتتمثل الفائدةيف أننا ندفع‬
‫)𝑏 ⋅ 𝑐(𝒪 تكلفة نواة ‪ 1 × 1‬فقط ويمكن أن نتعامل مع تكلفة )𝑔‪ 𝒪(𝑏 2 /‬للنواة ‪ .3 × 3‬على‬
‫غرار تنفيذ الكتلة المتبقيةيف القسم ‪ ،8.6.2‬يتم استبدال االتصال المتبقي (وبالتالي معممة‬
‫‪ )generalized‬بواسطة االلتفاف ‪.1 × 1‬‬

‫يوفر الشكل الصحيحيف الشكل ‪ 8.6.5‬ملخصًا أكثر إيجازًا عن فدرة الشبكة الناتجة‪ .‬ستلعب أيضًا‬
‫دورًا رئيسيًايف تصميم شبكات ‪ CNN‬الحديثة العامةيف القسم ‪ .8.8‬الحظ أن فكرة التالفيف‬
‫المجمعة تعود إلى تطبيق ‪ .)2012,Krizhevsky et al.( ،AlexNet‬عند توزيع الشبكة عبر‬
‫وحدتي ‪ GPU‬بذاكرة محدودة‪ ،‬تعامل التطبيق مع كل وحدة معالجة رسومات كقناة خاصة بها‬
‫دون أي آثار سيئة‪.‬‬

‫يأخذ التنفيذ التالي لفئة ‪ ResNeXtBlock‬مدخالت المجموعات ( 𝑔) ‪ ،‬مع قنوات وسيطة‬


‫)‪( bot_channels (b‬عنق الزجاجة)‪ .‬أخيرًا‪ ،‬عندما نحتاج إلى تقليل ارتفاع العرض‬
‫وعرضه‪ ،‬فإننا نضيف خطوة ‪ 2‬من خالل تعيين ‪.strides=2 ،use_1x1conv=True‬‬

‫‪class ResNeXtBlock(tf.keras.Model): #@save‬‬


‫"""‪"""The ResNeXt block.‬‬
‫‪def __init__(self, num_channels, groups, bot_mul,‬‬
‫‪use_1x1conv=False,‬‬
‫‪strides=1):‬‬
‫)(__‪super().__init‬‬
‫* ‪bot_channels = int(round(num_channels‬‬
‫))‪bot_mul‬‬
‫= ‪self.conv1‬‬
‫)‪tf.keras.layers.Conv2D(bot_channels, 1, strides=1‬‬
‫= ‪self.conv2‬‬
‫‪tf.keras.layers.Conv2D(bot_channels, 3, strides=strides,‬‬

‫‪padding="same",‬‬

‫)‪groups=bot_channels//groups‬‬
‫= ‪self.conv3‬‬
‫)‪tf.keras.layers.Conv2D(num_channels, 1, strides=1‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 152

self.bn1 = tf.keras.layers.BatchNormalization()
self.bn2 = tf.keras.layers.BatchNormalization()
self.bn3 = tf.keras.layers.BatchNormalization()
if use_1x1conv:
self.conv4 =
tf.keras.layers.Conv2D(num_channels, 1,

strides=strides)
self.bn4 =
tf.keras.layers.BatchNormalization()
else:
self.conv4 = None

def call(self, X):


Y =
tf.keras.activations.relu(self.bn1(self.conv1(X)))
Y =
tf.keras.activations.relu(self.bn2(self.conv2(Y)))
Y = self.bn3(self.conv3(Y))
if self.conv4:
X = self.bn4(self.conv4(X))
return tf.keras.activations.relu(Y + X)
‫ على سبيل‬.‫ الذي تمت مناقشته سابقًا‬ResNetBlock ‫استخدامه مشابه تمامًا الستخدام‬
‫ يكون المدخالت‬،)strides=1 ،use_1x1conv=False( ‫ عند استخدام‬،‫المثال‬
،use_1x1conv=True ‫ فإن إعداد‬،‫ وبدالً من ذلك‬.‫والمخرجات من نفس الشكل‬
.‫ ينقص ارتفاع الناتج وعرضه إلى النصف‬strides=2

blk = ResNeXtBlock(32, 16, 1)


X = tf.random.normal((4, 96, 96, 32))
Y = blk(X)
Y.shape
TensorShape([4, 96, 96, 32])

8.6.6
‫ مرغوبة ألنها تسمح لنا بالحصول‬Nested function classes ‫تعتبر فئات الدوال المتداخلة‬
‫ تتمثل إحدى طرق‬.‫على فئات دوال أكثر قوة بدالً من فئات دوال مختلفة بمهارة عند إضافة سعة‬
‫ تسمح الوصالت‬.‫تحقيق ذلكيف السماح لطبقات إضافية بالمرور عبر المدخالت إلى المخرجات‬
‫ يغير هذا التحيز االستقرائي من كون الدوال البسيطة من الشكل‬،‫ نتيجة لذلك‬.‫المتبقية بذلك‬
.𝑓(𝐱) = 𝐱 ‫ = )𝐱(𝑓 إلى دوال بسيطة تبدو وكأنها‬0
‫‪153‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫يمكن أن يتعلم التعيين المتبقي ‪ residual mapping‬دالة الهوية ‪ identity function‬بسهولة‬


‫أكبر‪ ،‬مثل دفع المعلماتيف طبقة الوزن إلى الصفر‪ .‬يمكننا تدريب شبكة عصبية عميقة فعالة من‬
‫خالل وجود الكتل المتبقية ‪ .residual blocks‬يمكن أن تنتشر المدخالت بشكل أسرع من‬
‫خالل الوصالت المتبقية عبر الطبقات ‪ .residual connections across layers‬نتيجة لذلك‪،‬‬
‫يمكننا بالتالي تدريب شبكات أعمق بكثير‪ .‬على سبيل المثال‪ ،‬سمحت ورقة ‪ ResNet‬األصلية‬
‫(‪ )2016 ،He et al.‬بما يصل إلى ‪ 152‬طبقة‪ .‬فائدة أخرى للشبكات المتبقية هي أنها تسمح‬
‫لنا بإضافة طبقات‪ ،‬تمت تهيئتها كدالة هوية‪ ،‬أثناء عملية التدريب‪ .‬بعد كل شيء‪ ،‬السلوك‬
‫االفتراضي للطبقة هو السماح للبيانات بالمرور دون تغيير‪ .‬يمكن أن يؤدي ذلك إلى تسريع تدريب‬
‫الشبكات الكبيرة جدًايف بعض الحاالت‪.‬‬

‫قبل التوصيالت المتبقية ‪ ،residual connections‬تم إدخال تجاوز المسارات ‪bypassing‬‬


‫‪ paths‬بوحدات بوابات لتدريب شبكات الطرق السريعة بشكل فعال مع أكثر من ‪ 100‬طبقة‬
‫(‪ .)2015 ،.Srivastava et al‬باستخدام دوال الهوية كتجاوز المسارات‪ ،‬كان أداء شبكة‬
‫‪ ResNet‬جيدًا بشكل ملحوظيف مهام الرؤية الحاسوبية المتعددة‪ .‬كان للوصالت المتبقية تأثير‬
‫كبير على تصميم الشبكات العصبية العميقة الالحقة‪ ،‬لكل من الطبيعة التالفيفية والمتسلسلة‪.‬‬
‫كما سنقدم الحقًا‪ ،‬تتبنى بنية المحوالت (‪ )2017 ،Vaswani et al.‬اتصاالت متبقية (جنبًا إلى‬
‫جنب مع خيارات التصميم األخرى) وهي منتشرةيف مجاالت متنوعة مثل اللغة والرؤية والكالم‬
‫والتعلم المعزز‪.‬‬

‫يعد ‪ ResNeXt‬مثاالً على كيفية تطور تصميم الشبكات العصبية التالفيفية بمرور الوقت‪ :‬من‬
‫خالل كونه أكثر اقتصادايف الحساب وتداوله مع حجم عمليات التنشيط (عدد القنوات)‪ ،‬فإنه‬
‫يسمح بشبكات أسرع وأكثر دقة بتكلفة أقل‪ .‬طريقة بديلة لعرض التالفيف المجمعة ‪grouped‬‬
‫‪ convolutions‬هي التفكيريف مصفوفة كتلة قطرية ‪ block-diagonal matrix‬لألوزان‬
‫التالفيفية‪ .‬الحظ أن هناك عددًا قليالً جدًا من هذه "الحيل" التي تؤدي إلى شبكات أكثر كفاءة‪.‬‬
‫على سبيل المثال‪ ،‬يحاكي ‪ )2018,Wu et al.(2018 ،ShiftNet‬تأثيرات االلتفاف ‪ ،‬ببساطة‬
‫عن طريق إضافة عمليات تنشيط متغيرة ‪ shifted activations‬إلى القنوات‪ ،‬مما يوفر تعقيدًا‬
‫متزايدًا للدوال‪ ،‬هذه المرة دون أي تكلفة حسابية‪.‬‬

‫من السمات الشائعة للتصميمات التي ناقشناها حتى اآلن أن تصميم الشبكة يدوي إلى حد ما‪،‬‬
‫وي عتمد بشكل أساسي على براعة المصمميف العثور على المعلمات الفائقة للشبكة "الصحيحة"‪.‬‬
‫في حين أنه من الواضح أنه مجدي‪ ،‬إال أنه مكلف للغاية من حيث الوقت البشري وليس هناك ما‬
‫يضمن أن النتيجة مثالية بأي شكل من األشكال‪ .‬سنناقشيف القسم ‪ 8.8‬عددًا من االستراتيجيات‬
‫للحصول على شبكات عالية الجودة بطريقة أكثر آلية‪ .‬على وجه الخصوص‪ ،‬سنراجع فكرة‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪154‬‬

‫مساحات تصميم الشبكة ‪ network design spaces‬التي أدت إلى نماذج ‪،RegNetX / Y‬‬
‫(‪.)2020,Radosavovic et al.‬‬

‫‪8.6.7‬‬
‫‪ .1‬ما هي االختالفات الرئيسية بين كتلة االستهالل ‪Inception block‬يف الشكل ‪8.4.1‬‬
‫والكتلة المتبقية ‪residual block‬؟ كيف يقارنون من حيث الحساب والدقة وفئات‬
‫الدوال التي يمكنهم وصفها؟‬
‫‪ .2‬ارجع إلى الجدول‪1‬يف مقالة ‪ )2016,He et al.( ،ResNet‬لتنفيذ انواع مختلفة‬
‫‪ different variants‬للشبكة‪.‬‬
‫‪ .3‬بالنسبة للشبكات األعمق‪ ،‬تقدم شبكة ‪ ResNet‬بُنية "عنق الزجاجة ‪"bottleneck‬‬
‫لتقليل تعقيد النموذج‪ .‬حاول تنفيذه‪.‬‬
‫‪ .4‬في اإلصدارات الالحقة من ‪ ،ResNet‬قام المؤلفون بتغيير بنية "االلتفاف‪ ،‬وتسوية‬
‫الدفعات‪ ،‬والتفعيل" إلى بُنية "تسوية الدُفعات‪ ،‬والتنشيط‪ ،‬وااللتفاف"‪ .‬قم بإجراء هذا‬
‫التحسين بنفسك‪ .‬انظر الشكل‪1‬يف ‪ )2016( .He et al‬لمزيد من التفاصيل‪.‬‬
‫‪ .5‬لماذا ال يمكننا فقط زيادة تعقيد الدوال دون قيود‪ ،‬حتى لو كانت فئات الدوال متداخلة؟‬

‫‪Densely Connected DenseNet‬‬ ‫‪8.7‬‬


‫‪Networks‬‬
‫غيّرت ‪ ResNet‬بشكل كبير طريقة عرض كيفية تحديد الدواليف الشبكات العميقة‪.‬‬
‫‪( DenseNet‬شبكة تالفيفية كثيفة) هي إلى حد ما االمتداد المنطقي لهذا ( ‪،Huang et al.‬‬
‫‪ .)2017‬تتميز ‪ DenseNet‬بكل من نمط االتصال حيث تتصل كل طبقة بجميع الطبقات‬
‫السابقة وعملية التسلسل ‪( concatenation operation‬بدالً من عامل اإلضافةيف ‪)ResNet‬‬
‫للحفاظ على الميزات من الطبقات السابقة وإعادة استخدامها‪ .‬لفهم كيفية الوصول إليها‪ ،‬دعنا‬
‫نأخذ منعطفًا بسيطًايف الرياضيات‪.‬‬

‫‪DenseNet‬‬ ‫‪ResNet‬‬ ‫‪8.7.1‬‬


‫استدعي توسعة تايلور ‪ Taylor expansion‬للدوال‪ .‬بالنسبة لهذه النقطة ‪ 𝑥 = 0‬يمكن كتابتها‬
‫كـ‬

‫)‪𝑓 ″ (0‬‬ ‫)‪𝑓 ‴ (0‬‬


‫[ ⋅ 𝑥 ‪𝑓(𝑥) = 𝑓(0) + 𝑥 ⋅ [𝑓 ′ (0) +‬‬ ‫[⋅𝑥‪+‬‬ ‫‪+ ⋯ ]]].‬‬
‫!‪2‬‬ ‫!‪3‬‬
‫النقطة األساسية هي أنها تحلل الدالة إلى مصطلحات ذات ترتيب أعلى بشكل متزايد‪ .‬على نفس‬
‫المنوال‪ ،‬تحلل ‪ ResNet‬الدوال إلى‪:‬‬
‫‪155‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪𝑓(𝐱) = 𝐱 + 𝑔(𝐱).‬‬

‫وهذا يعني أن ‪ ResNet‬تتحلل 𝑓 إلى مصطلح خطي بسيط ومصطلح غير خطي أكثر تعقيدًا‪.‬‬
‫ماذا لو أردنا التقاط (وليس بالضرورة إضافة) المعلومات التي تتجاوز المصطلحين؟ أحد هذه‬
‫الحلول هو ‪.)2017,Huang et al.( ،DenseNet‬‬

‫الشكل ‪ 8.7.1‬الفرق الرئيسي بين ‪( ResNet‬يسار) و‪( DenseNet‬يمين)يف التوصيالت عبر‬


‫الطبقات‪ :‬استخدام إالضافة ‪ addition‬واستخدام التسلسل ‪.concatenation‬‬

‫كما هو مبينيف الشكل ‪ ،8.7.1‬فإن االختالف الرئيسي بين ‪ ResNet‬و‪ DenseNet‬هو أنهيف ‬
‫الحالة األخيرة تكون المخرجات متسلسلة (يُشار إليها بـ ] ‪ )[,‬بدالً من إضافتها‪ .‬نتيجة لذلك‪،‬‬
‫نقوم بإجراء تعيين من 𝐱 الى قيمها بعد تطبيق تسلسل معقد بشكل متزايد من الدوال‪:‬‬

‫‪𝐱 → [𝐱, 𝑓1 (𝐱), 𝑓2 ([𝐱, 𝑓1 (𝐱)]), 𝑓3 ([𝐱, 𝑓1 (𝐱), 𝑓2 ([𝐱, 𝑓1 (𝐱)])]), … ].‬‬

‫في النهاية‪ ،‬يتم دمج كل هذه الدواليف ‪ MLP‬لتقليل عدد الميزات مرة أخرى‪ .‬من حيث التنفيذ‪،‬‬
‫هذا بسيط للغاية‪ :‬بدالً من إضافة المصطلحات‪ ،‬نقوم بتجميعها‪ .‬نشأ اسم ‪ DenseNet‬من حقيقة‬
‫أن الرسم البياني للتبعية بين المتغيرات يصبح كثيفًا جدًا‪ .‬ترتبط الطبقة األخيرة من هذه السلسلة‬
‫بكثافة بجميع الطبقات السابقة‪ .‬الوصالت الكثيفة ‪ dense connections‬موضحةيف الشكل‬
‫‪.8.7.2‬‬

‫الشكل ‪ 8.7.2‬اتصاالت كثيفةيف ‪ .DenseNet‬الحظ كيف تزداد األبعاد مع العمق‪.‬‬


‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 156

‫ وطبقات‬dense blocks ‫ هي كتل كثيفة‬DenseNet ‫المكونات الرئيسية التي تتكون منها شبكة‬
‫ بينما يتحكم‬،‫ يحدد األول كيفية تسلسل المدخالت والمخرجات‬.transition layers ‫انتقالية‬
𝐱 → ‫ نظرًا ألن التوسع‬،‫األخيريف عدد القنوات بحيث ال يكون كبيرًا جدًا‬
.‫𝐱[ يمكن أن يكون عالي األبعاد‬, 𝑓1 (𝐱), 𝑓2 ([𝐱, 𝑓1 (𝐱)]), … ]

Dense Blocks 8.7.2


‫ (راجع‬ResNet ‫ والتفاف" المعدلة لـ‬،‫ التنشيط‬،‫ بُنية "تسوية الدُفعات‬DenseNet ‫تستخدم‬
.‫ نقوم بتنفيذ هيكل كتلة االلتفاف‬،ً‫ أوال‬.)8.6 ‫التمرينيف القسم‬

import tensorflow as tf
from d2l import tensorflow as d2l

class ConvBlock(tf.keras.layers.Layer):
def __init__(self, num_channels):
super(ConvBlock, self).__init__()
self.bn = tf.keras.layers.BatchNormalization()
self.relu = tf.keras.layers.ReLU()
self.conv = tf.keras.layers.Conv2D(
filters=num_channels, kernel_size=(3, 3),
padding='same')

self.listLayers = [self.bn, self.relu,


self.conv]

def call(self, x):


y = x
for layer in self.listLayers.layers:
y = layer(y)
y = tf.keras.layers.concatenate([x,y], axis=-1)
return y
‫ ومع‬.‫ كل منها يستخدم نفس عدد قنوات اإلخراج‬،‫تتكون الكتلة الكثيفة من كتل التفاف متعددة‬
.‫ نقوم بربط المدخالت والمخرجات لكل كتلة التفاف على بُعد القناة‬،‫يف االنتشار األمامي‬،‫ذلك‬
.‫ بضبط األبعاد تلقائيًا‬Lazy evaluation ‫يسمح لنا التقييم الكسول‬

class DenseBlock(tf.keras.layers.Layer):
def __init__(self, num_convs, num_channels):
super(DenseBlock, self).__init__()
self.listLayers = []
for _ in range(num_convs):
157 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

self.listLayers.append(ConvBlock(num_channels))

def call(self, x):


for layer in self.listLayers.layers:
x = layer(x)
return x
‫ عند‬.‫ قنوات إخراج‬10 ‫ مع كتلتين التفاف من‬DenseBlock ‫ نحدد مثيل‬،‫في المثال التالي‬
‫ يتحكم‬.3 + 10 + 10 = 23 ‫ سنحصل على إخراج مع قنوات‬،‫استخدام إدخال بثالث قنوات‬
‫ يشار‬.‫عدد قنوات كتلة االلتفافيف النمويف عدد قنوات اإلخراج بالنسبة إلى عدد قنوات اإلدخال‬
.growth rate ‫إلى هذا أيضًا بمعدل النمو‬

blk = DenseBlock(2, 10)


X = tf.random.uniform((4, 8, 8, 3))
Y = blk(X)
Y.shape
TensorShape([4, 8, 8, 23])

Transition Layers 8.7.3


‫ فإن إضافة الكثير منها سيؤدي إلى نموذج معقد‬،‫نظرًا ألن كل كتلة كثيفة ستزيد من عدد القنوات‬
‫ يقلل من‬.‫ للتحكميف مدى تعقيد النموذج‬transition layer ‫ يتم استخدام طبقة انتقالية‬.‫للغاية‬
‫ فإنه يخفض االرتفاع والعرض إلى النصف‬،‫ عالوة على ذلك‬.‫عدد القنوات باستخدام االلتفاف‬
.2 ‫ بخطوة‬average pooling ‫عبر تجميع متوسط‬

class TransitionBlock(tf.keras.layers.Layer):
def __init__(self, num_channels, **kwargs):
super(TransitionBlock, self).__init__(**kwargs)
self.batch_norm =
tf.keras.layers.BatchNormalization()
self.relu = tf.keras.layers.ReLU()
self.conv = tf.keras.layers.Conv2D(num_channels,
kernel_size=1)
self.avg_pool =
tf.keras.layers.AvgPool2D(pool_size=2, strides=2)

def call(self, x):


x = self.batch_norm(x)
x = self.relu(x)
x = self.conv(x)
return self.avg_pool(x)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪158‬‬

‫قم بتطبيق طبقة انتقالية بها ‪ 10‬قنوات على إخراج الكتلة الكثيفةيف المثال السابق‪ .‬هذا يقلل من‬
‫عدد قنوات اإلخراج إلى ‪ ،10‬ويقلل االرتفاع والعرض إلى النصف‪.‬‬

‫)‪blk = TransitionBlock(10‬‬
‫‪blk(Y).shape‬‬
‫)]‪TensorShape([4, 4, 4, 10‬‬

‫‪DenseNet‬‬ ‫‪8.7.4‬‬
‫بعد ذلك‪ ،‬سنقوم ببناء نموذج ‪ .DenseNet‬تستخدم ‪ DenseNet‬أوالً نفس الطبقة التالفيفية‬
‫الفردية وطبقة تجميع الحد االقصى كمايف ‪.ResNet‬‬

‫‪class DenseNet(d2l.Classifier):‬‬
‫‪def b1(self):‬‬
‫[(‪return tf.keras.models.Sequential‬‬
‫(‪tf.keras.layers.Conv2D‬‬
‫‪64, kernel_size=7, strides=2,‬‬
‫‪padding='same'),‬‬
‫‪tf.keras.layers.BatchNormalization(),‬‬
‫‪tf.keras.layers.ReLU(),‬‬
‫(‪tf.keras.layers.MaxPool2D‬‬
‫‪pool_size=3, strides=2,‬‬
‫)])'‪padding='same‬‬
‫بعد ذلك‪ ،‬على غرار الوحدات األربع المكونة من الكتل المتبقية التي تستخدمها ‪،ResNet‬‬
‫تستخدم ‪ DenseNet‬أربع كتل كثيفة‪ .‬على غرار ‪ ،ResNet‬يمكننا تعيين عدد الطبقات‬
‫التالفيفية المستخدمةيف كل كتلة كثيفة‪ .‬هنا‪ ،‬قمنا بتعيينه على ‪ ،4‬بما يتوافق مع نموذج‬
‫‪ResNet-18‬يف القسم ‪ .8.6‬عالوة على ذلك‪ ،‬قمنا بتعيين عدد القنوات (أي معدل النمو)‬
‫للطبقات التالفيفيةيف الكتلة الكثيفة إلى ‪ ،32‬لذلك ستتم إضافة ‪ 128‬قناة إلى كل كتلة كثيفة‪.‬‬

‫في ‪ ،ResNet‬يتم تقليل االرتفاع والعرض بين كل وحدة بواسطة كتلة متبقية بخطوة ‪ .2‬هنا‪،‬‬
‫نستخدم طبقة االنتقال لخفض االرتفاع والعرض إلى النصف وخفض عدد القنوات إلى النصف‪.‬‬
‫على غرار ‪ ،ResNet‬يتم توصيل طبقة تجميع عالمية وطبقة متصلة بالكامليف النهاية إلنتاج‬
‫الناتج‪.‬‬

‫)‪@d2l.add_to_class(DenseNet‬‬
‫‪def __init__(self, num_channels=64, growth_rate=32,‬‬
‫‪arch=(4, 4, 4, 4),‬‬
‫‪lr=0.1, num_classes=10):‬‬
‫)(__‪super(DenseNet, self).__init‬‬
‫)(‪self.save_hyperparameters‬‬
159 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

self.net = tf.keras.models.Sequential(self.b1())
for i, num_convs in enumerate(arch):
self.net.add(DenseBlock(num_convs, growth_rate))
# The number of output channels in the previous
dense block
num_channels += num_convs * growth_rate
# A transition layer that halves the number of
channels is added
# between the dense blocks
if i != len(arch) - 1:
num_channels //= 2
self.net.add(TransitionBlock(num_channels))
self.net.add(tf.keras.models.Sequential([
tf.keras.layers.BatchNormalization(),
tf.keras.layers.ReLU(),
tf.keras.layers.GlobalAvgPool2D(),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(num_classes)]))
Training 8.7.5
224 ‫ سنقوم بتقليل ارتفاع اإلدخال وعرضه من‬،‫يف هذا القسم‬،‫نظرًا ألننا نستخدم شبكة أعمق هنا‬
.‫ لتبسيط الحساب‬96 ‫إلى‬

trainer = d2l.Trainer(max_epochs=10)
data = d2l.FashionMNIST(batch_size=128, resize=(96, 96))
with d2l.try_gpu():
model = DenseNet(lr=0.01)
trainer.fit(model, data)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪160‬‬

‫‪8.7.6‬‬
‫المكونات الرئيسية التي تتكون منها ‪ DenseNet‬هي كتل كثيفة ‪ dense blocks‬وطبقات‬
‫انتقالية ‪ .transition layers‬بالنسبة لألخير‪ ،‬نحتاج إلى إبقاء األبعاد تحت السيطرة عند تكوين‬
‫الشبكة عن طريق إضافة طبقات انتقالية تقلص عدد القنوات مرة أخرى‪ .‬فيما يتعلق باالتصاالت‬
‫عبر الطبقات ‪ ،cross-layer connections‬على عكس شبكة ‪ ،ResNet‬حيث يتم إضافة‬
‫المدخالت والمخرجات معًا‪ ،‬تقوم ‪ DenseNet‬بتجميع المدخالت والمخرجات على بُعد‬
‫القناة‪ .‬على الرغم من أن عمليات التسلسل هذه تعيد استخدام الميزات لتحقيق كفاءة حسابية‪،‬‬
‫إال أنها لألسف تؤدي إلى استهالك كبير لذاكرة وحدة معالجة الرسومات ‪ .GPU‬نتيجة لذلك‪،‬‬
‫قد يتطلب تطبيق ‪ DenseNet‬تطبيقات أكثر كفاءةيف استخدام الذاكرة والتي قد تزيد من وقت‬
‫التدريب (‪.)2017 ،Pleiss et al.‬‬

‫‪8.7.7‬‬
‫‪ .1‬لماذا نستخدم تجميع المتوسط ‪ average pooling‬بدالً من تجميع الحد األقصى‬
‫‪max-pooling‬يف الطبقة االنتقالية؟‬
‫‪ .2‬إحدى المزايا المذكورةيف مقالة ‪ DenseNet‬هي أن معلمات نموذجها أصغر من تلك‬
‫الخاصة بـ ‪ .ResNet‬لماذا هذا هو الحال؟‬
‫‪ .3‬إحدى المشكالت التي تم انتقاد ‪ DenseNet‬بسببها هي استهالكها العالي للذاكرة‪.‬‬
‫‪ .1‬هل هذا هو الحال فعال؟ حاول تغيير شكل اإلدخال الى ‪ 224 × 224‬لرؤية‬
‫االستهالك الفعلي لذاكرة وحدة معالجة الرسومات بشكل تجريبي‪.‬‬
‫‪ .2‬هل يمكنك التفكيريف وسيلة بديلة لتقليل استهالك الذاكرة؟ كيف تريد تغيير‬
‫أطار العمل؟‬
‫‪ .4‬نفذ إصدارات ‪ DenseNet‬المختلفة الواردةيف الجدول ‪ 1‬من مقالة ‪،DenseNet‬‬
‫(‪.)2017,Huang et al.‬‬
‫‪ .3‬صمم نموذجًا قائمًا على ‪ MLP‬من خالل تطبيق فكرة ‪ .DenseNet‬قم بتطبيقه على‬
‫مهمة التنبؤ بسعر السكنيف القسم ‪.5.7‬‬

‫‪Designing Convolution‬‬ ‫‪8.8‬‬


‫‪Network Architectures‬‬
‫شهد العقد األول من القرن الحادي والعشرين تحولًا من هندسة الميزات ‪feature‬‬
‫‪ engineering‬إلى هندسة الشبكات ‪network engineering‬يف الرؤية الحاسوبية‪ .‬نظرًا ألن‬
‫‪( AlexNet‬القسم ‪ )8.1‬تغلب على نماذج الرؤية الحاسوبية التقليدية على ‪ ،ImageNet‬فقد‬
‫تم نشر شبكات عميقة جدًا عن طريق تكديس نفس الكتل‪ ،‬وخاصة التالفيف ‪ ،3 × 3‬بواسطة‬
‫‪161‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫شبكات ‪( VGG‬القسم ‪ .)8.2‬تضيف الشبكةيف الشبكة (القسم ‪ )8.3‬العناصر غير الخطية‬


‫المحلية عبر التالفيف ‪ 1 × 1‬وتستخدم متوسط التجميع العالمي لتجميع المعلومات عبر جميع‬
‫المواقع‪( GoogLeNet .‬القسم ‪ )8.4‬عبارة عن شبكة متعددة الفروع تجمع مزايا شبكة ‪VGG‬‬
‫والشبكة الموجودةيف الشبكة‪ ،‬حيث تتبنى كتلة االستهالل ‪ Inception block‬استراتيجية‬
‫التحويالت المتوازية المتسلسلة‪ .‬تقوم ‪( ResNets‬القسم ‪ )8.6‬بتكديس الكتل المتبقية‪ ،‬وهي‬
‫عبارة عن شبكات فرعية ثنائية الفروع تستخدم تعيين الهوية ‪identity mapping‬يف فرع واحد‪.‬‬
‫تعمم ‪( DenseNets‬القسم ‪ )8.7‬البنى المتبقية‪ .‬تشمل البنى األخرى البارزة ‪MobileNets‬‬
‫التي تستخدم التعلم الشبكي ‪ network learning‬لتحقيق دقة عاليةيف اإلعدادات محدودة‬
‫الموارد (‪ ،)2019 ،Howard et al.‬وشبكات ‪Squeeze-and-Excitation Networks‬‬
‫)‪ (SENets‬التي تسمح بنقل المعلومات بكفاءة بين القنوات (‪)2018 ،Hu et al.‬‬
‫و‪ )2019,Tan and Le( ،EfficientNets‬التي تعمل على توسيع نطاق الشبكات عبر البحث‬
‫عن العمارة العصبية ‪.neural architecture search‬‬

‫على وجه التحديد‪ ،‬البحث عن العمارة العصبية )‪Zoph and ( ،)2018,Liu et al.( ،(NAS‬‬
‫‪ )2016,Le‬هو عملية أتمتة بنى الشبكات العصبية‪ .‬نظرًا لمساحة البحث الثابتة‪ ،‬تستخدم ‪NAS‬‬
‫إستراتيجية بحث لتحديد بُ نية ضمن مساحة البحث تلقائيًا بناءً على تقدير األداء الذي تم إرجاعه‪.‬‬
‫نتيجة ‪ NAS‬هي مثيل شبكة واحد‪.‬‬

‫بدالً من التركيز على تصميم مثل هذه الحاالت الفردية‪ ،‬يتمثل النهج البديليف تصميم مساحات‬
‫تصميم الشبكة ‪ network design spaces‬التي تميز مجموعات الشبكات ( ‪Radosavovic‬‬
‫‪ .)2020 ،et al.‬تجمع هذه الطريقة بين قوة التصميم اليدوي و‪ .NAS‬من خالل اإلجراءات شبه‬
‫اآللية (كما هو الحاليف ‪ ،)NAS‬يستكشف تصميم مساحات تصميم الشبكة الجانب الهيكلي‬
‫لتصميم الشبكة من مساحة تصميم ‪ AnyNet‬األولية‪ .‬ثم يشرعيف اكتشاف مبادئ التصميم (كما‬
‫هو الحاليف التصميم اليدوي) التي تؤدي إلى شبكات بسيطة ومنتظمة‪ .RegNets :‬قبل إلقاء‬
‫الضوء على مبادئ التصميم هذه‪ ،‬دعنا نبدأ بمساحة التصميم األولية‪.‬‬

‫‪AnyNet‬‬ ‫‪8.8.1‬‬
‫تسمى مساحة التصميم األولية ‪ ،AnyNet‬وهي مساحة تصميم غير مقيدة نسبيًا‪ ،‬حيث يمكننا‬
‫التركيز على استكشاف بُنية الشبكة بافتراض الكتل القياسية الثابتة مثل ‪( ResNeXt‬القسم‬
‫‪ .)8.6.5‬على وجه التحديد‪ ،‬تتضمن بُنية الشبكة عناصر مثل عدد الكتل‪number of blocks‬‬
‫وعدد قنوات اإلخراجيف كل مرحلة‪ ،‬وعدد المجموعات ‪( number of groups‬عرض‬
‫المجموعة) ونسبة االختناق ‪ bottleneck ratio‬داخل كل كتلة ‪.ResNeXt‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪162‬‬

‫الشكل ‪ 8.8.1‬مساحة تصميم ‪ .AnyNet‬إلى جانب عدد المجموعات ونسبة االختناق داخل‬
‫كل كتلة‪ ،‬تشمل خيارات التصميم‪ :‬العمق 𝑖𝑑 وعدد قنوات اإلخراج 𝑖𝑤 ألي مرحلة 𝑖‪.‬‬

‫تظهر مساحة تصميم ‪AnyNet‬يف الشكل ‪ .8.8.1‬تبدأ هذه الشبكة بجذع ‪ ،stem‬يتبعها جسم‬
‫‪ body‬بمراحل تحول 𝑛 ‪ ،‬ورأس ‪ head‬نهائي‪ .‬بشكل ملموس‪ ،‬فإن جذع الشبكة عبارة عن‬
‫التفاف ‪ 3 × 3‬مع الخطوة ‪ 2‬التي تقسم ارتفاع وعرض صورة اإلدخال إلى النصف‪ .‬رأس الشبكة‬
‫عبارة عن تجميع متوسط عالمي يتبعه طبقة متصلة بالكامل للتنبؤ بفئة اإلخراج‪ .‬الحظ أن جذع‬
‫الشبكة ورأسها يظالن ثابتًا وبسيطًا‪ ،‬بحيث يركز التصميم على هيكل الشبكة الذي يعد مركزيًا‬
‫لألداء‪ .‬على وجه التحديد‪ ،‬يتكون جسم الشبكة من مراحل التحويل 𝑛 (𝑛 هو معطى)‪ ،‬حيث‬
‫تتكون المرحلة 𝑖 من كتل ‪ 𝑑𝑖 ResNeXt‬مع قنوات اإلخراج 𝑖𝑤 ‪ ،‬وتنخفض بشكل تدريجي‬
‫االرتفاع والعرض إلى النصف عبر الكتلة األولى (إعداد ‪،use_1x1conv=True‬‬
‫‪ strides=2‬يف ‪ d2l.ResNeXtBlock‬يف القسم ‪ .)8.6.5‬دعنا نشير كذلك إلى نسبة‬
‫االختناق وعدد المجموعات (عرض المجموعة) داخل كل كتلة ‪ ResNeXt‬للمرحلة 𝑖 كـ 𝑖𝑏 و‬
‫𝑖𝑔 ‪ ،‬على التوالي‪ .‬بشكل عام‪ ،‬على الرغم من هيكل الشبكة المباشر‪ ،‬تنوع 𝑖𝑏 ‪ 𝑔𝑖 ,‬و 𝑖𝑤 ‪ ،‬و 𝑖𝑑‬
‫ينتج عنه عدد كبير من الشبكات الممكنةيف مساحة تصميم ‪.AnyNet‬‬
163 ‫ الشبكات العصبية االلتفافية الحديثة‬:‫الفصل الثامن‬

.‫ نحدد أوالً جذع شبكتها‬،AnyNet ‫لتنفيذ‬

import tensorflow as tf
from d2l import tensorflow as d2l

class AnyNet(d2l.Classifier):
def stem(self, num_channels):
return tf.keras.models.Sequential([
tf.keras.layers.Conv2D(num_channels,
kernel_size=3, strides=2,
padding='same'),
tf.keras.layers.BatchNormalization(),
tf.keras.layers.Activation('relu')])
.‫ عرض الكتلة‬num_channels ‫ حيث يحدد‬،ResNeXt ‫تتكون كل مرحلة من العمق لكتل‬
.‫الحظ أن الكتلة األولى تقسم ارتفاع وعرض صور اإلدخال إلى النصف‬

@d2l.add_to_class(AnyNet)
def stage(self, depth, num_channels, groups, bot_mul):
net = tf.keras.models.Sequential()
for i in range(depth):
if i == 0:
net.add(d2l.ResNeXtBlock(num_channels,
groups, bot_mul,
use_1x1conv=True, strides=2))
else:
net.add(d2l.ResNeXtBlock(num_channels,
groups, bot_mul))
return net
.AnyNet ‫ نكمل تنفيذ‬،‫من خالل وضع جذع الشبكة والجسم والرأس معًا‬

@d2l.add_to_class(AnyNet)
def __init__(self, arch, stem_channels, lr=0.1,
num_classes=10):
super(AnyNet, self).__init__()
self.save_hyperparameters()
self.net =
tf.keras.models.Sequential(self.stem(stem_channels))
for i, s in enumerate(arch):
self.net.add(self.stage(*s))
self.net.add(tf.keras.models.Sequential([
tf.keras.layers.GlobalAvgPool2D(),
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪164‬‬

‫))])‪tf.keras.layers.Dense(units=num_classes‬‬
‫‪Constraining‬‬ ‫‪8.8.2‬‬
‫‪Design Spaces with Lower Error Distributions‬‬
‫بالنسبة ألي مرحلة من مراحل ‪ ،AnyNet‬تكون خيارات التصميم هي نسبة االختناق 𝑖𝑏 وعدد‬
‫المجموعات 𝑖𝑔 داخل كل كتلة وعرض الكتلة 𝑖𝑤 والعمق 𝑖𝑑‪ .‬تبدأ عملية تصميم مساحات‬
‫الشبكة من بُنية شبكة غير مقيدة نسبيًا تتميز بـ ( 𝑖𝑑 ‪) 𝑏𝑖 ، 𝑔𝑖 ، 𝑤𝑖 ،‬يف مساحة تصميم ‪AnyNet‬‬
‫األولية‪ .‬ثم تقوم هذه العملية باختبار نماذج تدريجية من مساحة تصميم المدخالت لتقييم توزيع‬
‫الخطأ (‪ )2019 ،Radosavovic et al.‬كمؤشر للجودة ‪ quality indicator‬إلخراج مساحة‬
‫تصميم أكثر تقييدًا مع نماذج أبسط قد يكون لها جودة أفضل‪.‬‬

‫دعونا نوضح بالتفصيل مؤشر الجودة هذا لمساحات التصميم‪ .‬بالنظر إلى النماذج المأخوذة من‬
‫بعض مساحات التصميم‪ ،‬تقيس دالة التوزيع التجريبية للخطأ ‪error empirical‬‬
‫‪، 𝐹(𝑒) ،distribution function‬جزء النماذج التي بها أخطاء 𝑖𝑒 أقل من 𝑒‪:‬‬
‫𝑛‬
‫‪1‬‬
‫‪𝐹(𝑒) = ∑ 𝟏 (𝑒𝑖 < 𝑒).‬‬
‫𝑛‬
‫‪𝑖=1‬‬

‫الشكل ‪ 8.8.2‬مقارنة دوال التوزيع التجريبية للخطأ لمساحات التصميم‪ .‬تظهر تسميات الشكل‬
‫خطأ الحد األدنى والخطأ المتوسط‪ .‬تؤدي زيادة عرض الشبكة عبر المراحل ( 𝐶‪AnyNetX‬‬
‫من إلى 𝐷‪ )AnyNetX‬وزيادة عمق الشبكة عبر المراحل (من 𝐷‪ AnyNetX‬إلى‬
‫𝐸‪ )AnyNetX‬إلى تبسيط مساحة التصميم مع توزيعات أخطاء محسّنة (الشكل مأخوذ من‬
‫(‪.))2020 ،Radosavovic et al.‬‬

‫بدءًا من مساحة تصميم ‪ AnyNet‬األولية غير المقيدةيف (‪،)2020 ،Radosavovic et al.‬‬


‫تؤدي مشاركة نسبة شبكة االختناق 𝑏 = 𝑖𝑏 لجميع المراحل 𝑖 إلى مساحة تصميم أكثر تقييدًا‪.‬‬
‫تُظهر نماذج أخذ العينات والتدريب ‪ 𝑛 = 500‬من كلٍ 𝐴‪ AnyNetX‬و 𝐵‪, AnyNetX‬على‬
‫‪165‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫يسار الشكل ‪ 8.8.2‬أن كال مساحات التصميم لهما نفس الجودة‪ .‬نظرًا ألن األبسط هو األفضل‪،‬‬
‫فإننا نواصل البحث من خالل مشاركة عدد المجموعات 𝑔 = 𝑖𝑔 بشكل إضافي‪ .‬وهذا يؤدي إلى‬
‫مزيد من مساحة التصميم المبسطة مع عدم وجود تغيير فعلييف توزيعات الخطأ (يمين الشكل‬
‫‪.)8.8.2‬‬

‫يشير التحقيقيف النماذج الجيدة والسيئة من ان 𝐶‪ AnyNetX‬قد يكون من المفيد زيادة العرض‬
‫عبر المراحل (‪ .)2020 ،Radosavovic et al.‬تجريبيًا‪ ،‬تبسيط 𝐶‪AnyNetX‬و‬
‫𝐷‪ AnyNetX‬مع ‪ 𝑤𝑖 ≤ 𝑤𝑖+1‬لتحسين جودة مساحات التصميم (يسار الشكل ‪.)8.8.3‬‬
‫وبالمثل‪ ،‬فإن إضافة المزيد من القيود ‪ 𝑑𝑖 ≤ 𝑑𝑖+1‬لزيادة عمق الشبكة عبر المراحل يعطي أفضل‬
‫(يمين الشكل ‪.)8.8.3‬‬

‫الشكل ‪ 8.8.3‬مقارنة دوال التوزيع التجريبية للخطأ لمساحات التصميم‪ .‬تظهر تسميات الشكل‬
‫خطأ الحد األدنى والخطأ المتوسط‪ .‬تؤدي زيادة عرض الشبكة عبر المراحل (من‬
‫𝐶‪ AnyNetX‬إلى 𝐷‪ )AnyNetX‬وزيادة عمق الشبكة عبر المراحل (من 𝐷‪ AnyNetX‬إلى‬
‫𝐸‪ ) AnyNetX‬إلى تبسيط مساحة التصميم مع توزيعات أخطاء محسّنة (الشكل مأخوذ من‬
‫(‪.))2020 ،Radosavovic et al.‬‬

‫‪RegNet 8.8.3‬‬
‫تتكون مساحة التصميم 𝐸‪ AnyNetX‬الناتجة من شبكات بسيطة تتبع مبادئ التصميم سهلة‬
‫التفسير‪:‬‬

‫مشاركة نسبة شبكة االختناق 𝑏 = 𝑖𝑏 لجميع المراحل 𝑖؛‬ ‫•‬


‫مشاركة عدد المجموعات 𝑔 = 𝑖𝑔 لجميع المراحل 𝑖؛‬ ‫•‬
‫زيادة عرض الشبكة عبر المراحل ‪ 𝑤𝑖 ≤ 𝑤𝑖+1‬؛‬ ‫•‬
‫زيادة عمق الشبكة عبر المراحل‪.𝑑𝑖 ≤ 𝑑𝑖+1 :‬‬ ‫•‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 166

‫) قيود خطية كمية لـلزيادة‬2020 ،Radosavovic et al.( ‫ اقترح‬،‫باتباع مبادئ التصميم هذه‬
‫ التي تستخدم‬RegNetY‫ و‬ResNeXt ‫ باستخدام كتل‬RegNetX ‫ مما يؤدي إلى‬، 𝑑𝑖 ‫𝑖𝑤 و‬
‫ قمنا بتنفيذ متغير‬،‫ على سبيل المثال‬.)2018,Hu et al.( ،SENets ‫أيضًا مشغلين من‬
‫ طبقة والذي يتميز بـ‬32 ‫ المكون من‬RegNetX

• 𝑏𝑖 = 1;
• 𝑔𝑖 = 16;
• 𝑤1 = 32, 𝑤2 = 80;
• 𝑑1 = 4, 𝑑2 = 6.
class RegNet32(AnyNet):
def __init__(self, lr=0.1, num_classes=10):
stem_channels, groups, bot_mul = 32, 16, 1
depths, channels = (4, 6), (32, 80)
super().__init__(
((depths[0], channels[0], groups, bot_mul),
(depths[1], channels[1], groups, bot_mul)),
stem_channels, lr, num_classes)
‫ تقلل بشكل تدريجي الدقة وتزيد من قنوات‬RegNet ‫يمكننا أن نرى أن كل مرحلة من مراحل‬
.‫اإلخراج‬

RegNet32().layer_summary((1, 96, 96, 1))


Sequential output shape: (1, 48, 48, 32)
Sequential output shape: (1, 24, 24, 32)
Sequential output shape: (1, 12, 12, 80)
Sequential output shape: (1, 10)
Training 8.8.4
‫ هو مثل‬Fashion-MNIST ‫ طبقة على مجموعة بيانات‬32 ‫ المكون من‬RegNet ‫إن تدريب‬
.‫ما كان عليه من قبل‬

trainer = d2l.Trainer(max_epochs=10)
data = d2l.FashionMNIST(batch_size=128, resize=(96, 96))
with d2l.try_gpu():
model = RegNet32(lr=0.01)
trainer.fit(model, data)
‫‪167‬‬ ‫الفصل الثامن‪ :‬الشبكات العصبية االلتفافية الحديثة‬

‫‪8.8.5‬‬
‫مع الخصائص المرغوبة مثل المحلية ‪ locality‬وثبات الترجمة ‪translation invariance‬‬
‫(القسم ‪ )7.1‬للرؤية‪ ،‬كانت شبكات ‪ CNN‬هي ال ُبنى المهيمنةيف هذا المجال‪.‬يف اآلونة األخيرة‪،‬‬
‫أثارت المحوالت (القسم ‪)2021 ،Touvron et al. ،2021 ،Dosovitskiy et al.( )11.7‬‬
‫و ‪ )2021,Tolstikhin et al.( ،MLPs‬أيضًا بحثًا يتجاوز بُنى ‪ CNN‬الراسخة للرؤية‪ .‬على‬
‫وجه التحديد‪ ،‬على الرغم من عدم وجود التحيزات االستقرائية ‪ inductive biases‬المذكورة‬
‫أعاله المالزمة لشبكات ‪ ،CNN‬فقد حققت محوالت الرؤية (القسم ‪ )11.8‬أداءً متطورًايف ‬
‫تصنيف الصور على نطاق واسعيف أوائل عام ‪ ،2020‬مما يدل على أن قابلية التوسع تتفوق على‬
‫التحيزات االستقرائية (‪ .)2021 ،Dosovitskiy et al.‬بمعنى آخر‪ ،‬غالبًا ما يكون من الممكن‬
‫تدريب محوالت كبيرة ‪ large transformers‬لتتفوق على شبكات ‪ CNN‬الكبيرةيف مجموعات‬
‫البيانات الكبيرة‪ .‬مستوحاة من سلوك التحجيم الفائق ‪ superior scaling behavior‬للمحوالت‬
‫(القسم ‪ )11.9‬مع االهتمام الذاتي متعدد الرؤوس ‪( multi-head self-attention‬القسم‬
‫‪ ،)11.5‬تؤدي عملية التحسين التدريجي من بُنية ‪ ResNet‬القياسية نحو تصميم محول الرؤية‬
‫‪ vision transformer‬إلى عائلة من شبكات ‪ CNN‬تسمى ‪ ConvNeXt‬النماذج التي‬
‫تتنافس بشكل إيجابي مع المحوالت من أجل الرؤية (‪ .)2022 ،Liu et al.‬نحيل القراء‬
‫المهتمين إلى مناقشات تصميم ‪CNN‬يف مقالة ‪.)2022,Liu et al.( ،ConvNeXt‬‬

‫‪8.8.6‬‬
‫‪ .1‬قم بزيادة عدد المراحل إلى ‪ .4‬هل يمكنك تصميم ‪ RegNet‬أعمق يعمل بشكل‬
‫أفضل؟‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪168‬‬

‫‪ .2‬استبدل كتلة ‪ ResNeXt‬بكتلة ‪ .ResNet‬كيف يعمل نموذجك الجديد؟‬


‫‪ .3‬نفذ مثيالت متعددة لعائلة "‪ "VioNet‬من خالل انتهاك ‪ violating‬مبادئ تصميم‬
‫‪ .RegNet‬كيف يؤدون؟ أي من ( 𝑖𝑏‪ ) 𝑑𝑖 ،𝑤𝑖 ،𝑔𝑖 ،‬هو العامل األكثر أهمية؟‬
‫الشبكات العصبية المتكررة‬
‫‪9‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪170‬‬

‫‪Recurrent Neural‬‬ ‫‪9‬‬


‫‪Networks‬‬
‫حتى اآلن‪ ،‬ركزنا بشكل أساسي على البيانات ذات الطول الثابت ‪ .fixed-length data‬عند‬
‫تقديم االنحدار الخطي واللوجستييف القسم ‪ 3‬والقسم ‪ 4‬والبيرسيبترون متعددة الطبقاتيف القسم‬
‫‪ ،5‬كان من دواعي سرورنا أن نفترض أن كل متجه للميزات يتكون من عدد ثابت من المكونات‬
‫حيث تتوافق كل ميزة رقمية مع سمة معينة‪ .‬يطلق على مجموعات البيانات هذه أحيانًا اسم‬
‫جدولي ‪ ،tabular‬ألنه يمكن ترتيبهايف جداول‪ ،‬حيث يحصل كل مثال على صف خاص به‪ ،‬وكل‬
‫سمة تحصل على عمودها الخاص‪ .‬بشكل حاسم‪ ،‬مع البيانات المجدولة ‪ ،tabular data‬نادرًا‬
‫ما نفترض أي بُنية معينة فوق األعمدة‪.‬‬

‫بعد ذلك‪،‬يف القسم ‪ ،7‬انتقلنا إلى بيانات الصورة‪ ،‬حيث تتكون المدخالت من قيم البكسل األولية‬
‫في كل إحداثييف الصورة‪ .‬ال تكاد بيانات الصورة تتناسب مع فاتورة مجموعة البيانات الجدولية‬
‫النموذجية‪ .‬هناك‪ ،‬احتجنا إلى استدعاء الشبكات العصبية التالفيفية (‪ )CNN‬للتعامل مع الهيكل‬
‫الهرمي والثوابت‪ .‬ومع ذلك‪ ،‬كانت بياناتنا ال تزال ذات طول ثابت‪ .‬يتم تمثيل كل صورة من صور‬
‫‪ Fashion-MNIST‬كشبكة من قيم البكسل ‪ .28 × 28‬عالوة على ذلك‪ ،‬كان هدفنا تطوير‬
‫نموذج ينظر إلى صورة واحدة فقط ثم ينتج تنبوًا واحدًا‪ .‬ولكن ما الذي يجب أن نفعله عندما‬
‫نواجه سلسلة من الصور‪ ،‬كما هو الحاليف مقطع فيديو‪ ،‬أو عند تكليفنا بإنتاج تنبؤ منظم بشكل‬
‫تسلسلي‪ ،‬كمايف حالة التسميات التوضيحية للصور ‪image captioning‬؟‬

‫تتطلب مهام التعلم التي ال تعد وال تحصى التعامل مع البيانات المتسلسلة ‪.sequential data‬‬
‫يتطلب شرح الصور وتوليف الكالم وتوليد الموسيقى أن تنتج النماذج مخرجات تتكون من‬
‫تسلسالت‪.‬يف المجاالت األخرى‪ ،‬مثل توقع السالسل الزمنية ‪time series prediction‬‬
‫وتحليل الفيديو ‪ video analysis‬واسترجاع المعلومات الموسيقية ‪musical information‬‬
‫‪ ،retrieval‬يجب أن يتعلم النموذج من المدخالت المتسلسلة‪ .‬غالبًا ما تنشأ هذه المطالبيف ‬
‫وقت واحد‪ :‬مهام مثل ترجمة مقاطع نصية من لغة طبيعية إلى أخرى‪ ،‬أو االنخراطيف حوار‪ ،‬أو‬
‫التحكميف روبوت‪ ،‬تتطلب نماذج استيعاب وإخراج بيانات منظمة بالتسلسل‪.‬‬

‫الشبكات العصبية المتكررة (‪ )RNNs‬هي نماذج التعلم العميق التي تلتقط ديناميكيات‬
‫التسلسالت عبر االتصاالت المتكررة ‪ ،recurrent connections‬والتي يمكن اعتبارها دورات‬
‫في شبكة العقد‪ .‬قد يبدو هذا غير منطقييف البداية‪ .‬بعد كل شيء‪ ،‬فإن الطبيعة المغذية‬
‫‪ feedforward nature‬للشبكات العصبية هي التي تجعل ترتيب الحساب واضحًا‪ .‬ومع ذلك‪،‬‬
‫يتم تحديد الحواف المتكررة بطريقة دقيقة تضمن عدم حدوث مثل هذا الغموض‪ .‬يتم إلغاء‬
‫‪171‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫التحكميف الشبكات العصبية المتكررة عبر الخطوات الزمنية ‪( time steps‬أو خطوات التسلسل‬
‫‪ ،)sequence steps‬مع تطبيق نفس المعلمات األساسيةيف كل خطوة‪ .‬بينما يتم تطبيق‬
‫االتصاالت القياسية بشكل متزامن لنشر عمليات تنشيط كل طبقة إلى الطبقة الالحقةيف نفس‬
‫الخطوة الزمنية‪ ،‬تكون االتصاالت المتكررة ديناميكية‪ ،‬وتمرير المعلومات عبر خطوات الوقت‬
‫المجاورة‪ .‬كما يكشف العرض غير المطوي ‪unfolded view‬يف الشكل ‪ ،9.1‬يمكن اعتبار‬
‫شبكات ‪ RNN‬بمثابة شبكات عصبية تلقائية ‪ feedforward neural networks‬حيث تتم‬
‫مشاركة معلمات كل طبقة (التقليدية والمتكررة ‪ )conventional and recurrent‬عبر‬
‫خطوات زمنية‪.‬‬

‫الشكل ‪ 9.1‬على اليسار يتم تصوير الوصالت المتكررة ‪ recurrent connections‬عبر حواف‬
‫دورية ‪ .cyclic edges‬على اليمين‪ ،‬نكشف عن ‪ RNN‬بمرور الوقت‪ .‬هنا‪ ،‬تمتد الحواف‬
‫المتكررة على خطوات زمنية متجاورة ‪ ،adjacent time steps‬بينما يتم حساب االتصاالت‬
‫التقليدية ‪ conventional connections‬بشكل متزامن‪.‬‬

‫مثل الشبكات العصبية على نطاق أوسع‪ ،‬تتمتع شبكات ‪ RNN‬بتاريخ طويل يمتد من االنضباط‪،‬‬
‫حيث نشأت كنماذج للدماغ شاعها علماء اإلدراك وتم تبنيها الحقًا كأدوات نمذجة عملية‬
‫يستخدمها مجتمع التعلم اآللي‪ .‬كما هو الحال مع التعلم العميق على نطاق أوسع‪ ،‬يتبنى هذا‬
‫الكتاب منظور التعلم اآللي‪ ،‬مع التركيز على ‪ RNNs‬كأدوات عملية ارتفعت إلى الشعبيةيف ‪2010‬‬
‫بسبب النتائج المذهلةيف مهام متنوعة مثل التعرف على خط اليد ‪handwriting recognition‬‬
‫(‪ ،)2008 ،Graves et al.‬الترجمة اآللية ‪،.Sutskever et al( machine translation‬‬
‫‪ ،)2014‬والتعرف على التشخيصات الطبية ‪Lipton ( recognizing medical diagnosis‬‬
‫‪ .)2016 ،.et al‬نوجه القارئ المهتم بمزيد من المواد األساسية إلى مراجعة شاملة متاحة‬
‫للجمهور (‪ .)2015 ،.Lipton et al‬نالحظ أيضًا أن التسلسل ليس فريدًا بالنسبة لـ ‪.RNNs‬‬
‫على سبيل المثال‪ ،‬يمكن تكييف شبكات ‪ CNN‬التي قدمناها بالفعل للتعامل مع البيانات ذات‬
‫الطول المتفاوت ‪ ،varying length‬على سبيل المثال‪ ،‬الصور ذات الدقة المتفاوتة ‪varying‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪172‬‬

‫‪ .resolution‬عالوة على ذلك‪ ،‬تنازلت ‪ RNNs‬مؤخرًا عن حصة كبيرة من السوق لنماذج‬


‫المحوالت ‪ ،transformer models‬والتي سيتم تغطيتهايف القسم ‪ .11‬ومع ذلك‪ ،‬ارتفعت‬
‫‪ RNNs‬إلى الصدارة كنماذج افتراضية للتعامل مع البنية المتسلسلة المعقدةيف التعلم العميق‪،‬‬
‫وال تزال نماذج أساسية للنمذجة المتسلسلة ‪ sequential modeling‬حتى يومنا هذا‪ .‬ترتبط‬
‫قصص ‪ RNNs‬ونمذجة التسلسل ارتباطًا وثيقًا‪ ،‬وهذا فصل عن أبجديات مشاكل نمذجة‬
‫التسلسل كما هو فصل حول ‪.RNNs‬‬

‫مهدت إحدى األفكار الرئيسية الطريق لثورةيف نمذجة التسلسل‪.‬يف حين أن المدخالت واألهداف‬
‫للعديد من المهام األساسيةيف التعلم اآللي ال يمكن بسهولة تمثيلها كمتجهات ذات طول ثابت‬
‫‪ ،fixed length vectors‬إال أنه يمكن تمثيلهايف كثير من األحيان على أنها متواليات متغيرة‬
‫الطول لمتجهات الطول الثابت‪ .‬على سبيل المثال‪ ،‬يمكن تمثيل المستندات كتسلسل من‬
‫الكلمات‪ .‬غالبًا ما يمكن تمثيل السجالت الطبية كتسلسل لألحداث (لقاءات‪ ،‬أدوية‪ ،‬إجراءات‪،‬‬
‫اختبارات معملية‪ ،‬تشخيصات)‪ .‬يمكن تمثيل مقاطع الفيديو كتسلسالت متفاوتة الطول للصور‬
‫الثابتة‪.‬‬

‫بينما ظهرت نماذج التسلسليف مجاالت تطبيق ال حصر لها‪ ،‬فإن البحث األساسييف المنطقة كان‬
‫مدفوعًايف الغالب بالتقدميف المهام األساسيةيف معالجة اللغة الطبيعية ‪natural language‬‬
‫‪ .processing‬وبالتالي‪ ،‬خالل هذا الفصل‪ ،‬سنركز عرضنا وأمثلة على البيانات النصية ‪text‬‬
‫‪ .data‬إذا فهمت هذه األمثلة‪ ،‬فإن تطبيق هذه النماذج على أساليب البيانات األخرى يجب أن‬
‫يكون بسيطًا نسبيًا‪.‬يف األقسام القليلة التالية‪ ،‬نقدم تدوينًا أساسيًا للتسلسالت وبعض مقاييس‬
‫التقييم لتقييم جودة مخرجات النموذج المنظم بشكل تسلسلي‪ .‬بعد ذلك‪ ،‬نناقش المفاهيم‬
‫األساسية لنموذج اللغة ونستخدم هذه المناقشة لتحفيز نماذج ‪ RNN‬األولى لدينا‪ .‬أخيرًا‪ ،‬نصف‬
‫طريقة حساب التدرجات عند االنتشار الخلفي من خالل شبكات ‪ RNN‬واستكشاف بعض‬
‫التحديات التي غالبًا ما تتم مواجهتها عند تدريب مثل هذه الشبكات‪ ،‬وتحفيز بُنى ‪RNN‬‬
‫الحديثة التي ستتبعيف القسم ‪.10‬‬

‫‪Working with Sequences‬‬ ‫‪9.1‬‬


‫حتى اآلن‪ ،‬ركزنا على النماذج التي تتكون مدخالتها من متجه ميزة ‪ feature vector‬واحد ∈ 𝐱‬
‫𝑑‪ .ℝ‬يتمثل التغيير الرئيسي للمنظور عند تطوير النماذج القادرة على معالجة التسلسالتيف أننا‬
‫نركز اآلن على المدخالت التي تتكون من قائمة مرتبة من متجهات الميزات 𝑇 𝐱 ‪ ،𝐱1 , … ,‬حيث‬
‫يقع كل متجه ميزة 𝑡𝐱 مفهرسة بخطوة زمنية ‪𝑡 ∈ ℤ+‬يف 𝑑‪.ℝ‬‬

‫تتكون بعض مجموعات البيانات من تسلسل ضخم واحد‪ .‬ضعيف اعتبارك‪ ،‬على سبيل المثال‪،‬‬
‫التدفقات الطويلة للغاية لقراءات أجهزة االستشعار التي قد تكون متاحة لعلماء المناخ‪.‬يف مثل‬
‫‪173‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫هذه الحاالت‪ ،‬قد نقوم بإنشاء مجموعات بيانات تدريبية عن طريق أخذ عينات عشوائية الحقة‬
‫من بعض الطول المحدد مسبقًا‪.‬يف كثير من األحيان‪ ،‬تصل بياناتنا كمجموعة من التسلسالت‬
‫‪ .sequences‬خذ بعين االعتبار األمثلة التالية‪ )1( :‬مجموعة من الوثائق‪ ،‬كل منها يمثل على أنه‬
‫تسلسل كلمات خاص به‪ ،‬ولكل منها طوله الخاص 𝑖𝑇؛ (‪ )2‬التمثيل المتسلسل للمريض الذي‬
‫يبقىيف المستشفى‪ ،‬حيث تتكون كل إقامة من عدد من األحداث ويعتمد طول التسلسل تقريبًا‬
‫على طول مدة اإلقامة‪.‬‬

‫في السابق‪ ،‬عند التعامل مع المدخالت الفردية‪ ،‬افترضنا أنه تم أخذ عينات منها بشكل مستقل‬
‫عن نفس التوزيع األساسي )𝑋(𝑃 ‪ .‬بينما ال نزال نفترض أن التسلسالت بأكملها (على سبيل‬
‫المثال‪ ،‬المستندات الكاملة أو مسارات المريض) يتم أخذ عينات منها بشكل مستقل‪ ،‬ال يمكننا‬
‫افتراض أن البيانات التي تصليف كل خطوة زمنية مستقلة عن بعضها البعض‪ .‬على سبيل المثال‪،‬‬
‫تعتمد الكلمات التي من المحتمل أن تظهر الحقًايف المستند بشكل كبير على الكلمات التي وردت‬
‫س ابقًايف المستند‪ .‬يعتمد الدواء الذي من المحتمل أن يتلقاها المريضيف اليوم العاشر من زيارة‬
‫المستشفى بشكل كبير على ما حدثيف األيام التسعة السابقة‪.‬‬

‫وهذا ينبغي أن يكون مفاجئا‪ .‬إذا لم نكن نعتقد أن العناصريف التسلسل كانت مرتبطة ببعضنا‬
‫البعض‪ ،‬فلن نتكبد عناء تصميمها كسلسلةيف المقام األول‪ .‬ضعيف اعتبارك فائدة ميزات الملء‬
‫التلقائي ‪ auto-fill‬الشائعةيف أدوات البحث وعمالء البريد اإللكتروني الحديث‪ .‬إنها مفيدة على‬
‫وجه التحديد ألنه غالبًا ما يكون من الممكن التنبؤ (بشكل ناقص‪ ،‬ولكن أفضل من التخمين‬
‫العشوائي) ما قد تكون االستمرارية المحتملة للتسلسل‪ ،‬مع إعطاء بعض البادئة األولية‪ .‬بالنسبة‬
‫لمعظم نماذج التسلسل‪ ،‬ال نطلب االستقالل‪ ،‬أو حتى الثبات‪ ،‬لتسلسالتنا‪ .‬بدالً من ذلك‪ ،‬نطلب‬
‫فقط أن يتم أخذ عينات من التسلسالت نفسها من بعض التوزيع األساسي الثابت على‬
‫التسلسالت بأكملها‪.‬‬

‫يسمح هذا النهج المرن بظواهر مثل (‪ )1‬المستندات التي تبدو مختلفة بشكل كبيريف البداية عما‬
‫كانت عليهيف النهاية‪ ،‬أو (‪ ) 2‬تطور حالة المريض إما نحو الشفاء أو نحو الوفاة خالل فترة اإلقامة‬
‫في المستشفى؛ و (‪ ) 3‬تطور ذوق العميل بطرق يمكن التنبؤ بها على مدار التفاعل المستمر مع‬
‫نظام التوصية ‪.recommender system‬‬

‫نرغب أحيانًايف توقع هدف ثابت 𝑦 بالنظر إلى إدخال منظم بشكل تسلسلي (على سبيل المثال‪،‬‬
‫تصنيف المشاعر ‪ sentiment classification‬بناءً على مراجعة فيلم)‪.‬يف أوقات أخرى‪ ،‬نرغب‬
‫في توقع هدف منظم بشكل تسلسلي ( 𝑇𝑦 ‪ )𝑦1 , … ,‬مع األخذيف االعتبار إدخال ثابت (على سبيل‬
‫المثال‪ ،‬تسمية توضيحية للصورة ‪ .)image captioning‬ال يزال هدفنايف أوقات أخرى هو التنبؤ‬
‫باألهداف المنظمة بشكل تسلسلي بناءً على المدخالت المنظمة بالتسلسل (على سبيل المثال‪،‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪174‬‬

‫الترجمة اآللية أو التسميات التوضيحية للفيديو ‪ .)video captioning‬تأخذ مهام التسلسل إلى‬
‫التسلسل شكلين‪ )1( :‬محاذاة ‪ :aligned‬حيث تتم محاذاة اإلدخاليف كل خطوة زمنية مع هدف‬
‫مطابق (على سبيل المثال‪ ،‬جزء من عالمات الكالم)؛ (‪ )2‬غير محاذي ‪ :unaligned‬حيث ال‬
‫يُظهر المدخل والهدف بالضرورة استجابات خطوة بخطوة (على سبيل المثال‪ ،‬الترجمة اآللية)‪.‬‬

‫قبل أن نقلق بشأن التعامل مع األهداف من أي نوع‪ ،‬يمكننا معالجة المشكلة األكثر وضوحًا‪:‬‬
‫نمذجة الكثافة غير الخاضعة لإلشراف ‪( unsupervised density modeling‬وتسمى أيضًا‬
‫نمذجة التسلسل ‪ .)sequence modeling‬هنا‪ ،‬بالنظر إلى مجموعة من المتسلسالت‬
‫‪ ،sequences‬هدفنا هو تقدير دالة الكتلة االحتمالية ‪ probability mass function‬التي تخبرنا‬
‫بمدى احتمالية رؤية أي تسلسل معين‪ ،‬أي ) 𝑇 𝐱 ‪.𝑝(𝐱1 , … ,‬‬

‫‪Autoregressive Models‬‬ ‫‪9.1.1‬‬


‫قبل تقديم الشبكات العصبية المتخصصة المصممة للتعامل مع البيانات المنظمة بشكل تسلسلي‪،‬‬
‫دعنا نلقي نظرة على بعض بيانات التسلسل الفعلي وبناء بعض الحدس األساسي واألدوات‬
‫اإلحصائية‪ .‬على وجه الخصوص‪ ،‬سوف نركز على بيانات أسعار األسهم من مؤشر ‪FTSE 100‬‬
‫(الشكل ‪.)9.1.1‬يف كل خطوة زمنية ‪ ،𝑡 ∈ ℤ+‬نالحظ سعر المؤشريف ذلك الوقت‪ ،‬يُرمز إليه بـ‬
‫𝑡𝑥‪.‬‬

‫الشكل ‪ 9.1.1‬مؤشر ‪ FTSE 100‬على مدار حوالي ‪ 30‬عامًا‪.‬‬

‫افترض اآلن أن المتداول يرغبيف إجراء صفقات قصيرة األجل‪ ،‬والدخول بشكل استراتيجي إلى‬
‫المؤشر أو الخروج منه‪ ،‬اعتمادًا على ما إذا كان يعتقد أنه سيرتفع أو ينخفضيف الخطوة الزمنية‬
‫الالحقة‪.‬يف غياب أي ميزات أخرى (أخبار‪ ،‬بيانات التقارير المالية‪ ،‬إلخ)‪ ،‬فإن اإلشارة الوحيدة‬
‫‪175‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫المتاحة للتنبؤ بالقيمة الالحقة هي تاريخ األسعار حتى اآلن‪ .‬وبالتالي فإن المتداول مهتم بمعرفة‬
‫توزيع االحتماالت‬

‫) ‪𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1‬‬

‫على األسعار التي قد يتخذها المؤشريف الخطوة الزمنية الالحقة‪ .‬بينما قد يكون تقدير التوزيع‬
‫بالكامل على متغير عشوائي ذي قيمة مستمرة أمرًا صعبًا‪ ،‬سيكون من دواعي سرور المتداول‬
‫التركيز على بعض اإلحصائيات الرئيسية للتوزيع‪ ،‬ال سيما القيمة المتوقعة والتباين‪ .‬استراتيجية‬
‫واحدة بسيطة لتقدير التوقع المشروط‬

‫‪𝔼[(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1 )],‬‬

‫سيكون تطبيق نموذج االنحدار الخطي ‪( linear regression‬راجع القسم ‪ .)3.1‬مثل هذه‬
‫النماذج التي تتراجع عن قيمة اإلشارة على القيم السابقة لتلك اإلشارة نفسها تسمى بشكل طبيعي‬
‫نماذج االنحدار الذاتي ‪ .autoregressive models‬هناك مشكلة رئيسية واحدة فقط‪ :‬يختلف‬
‫عدد المدخالت ‪ 𝑥𝑡−1 , … , 𝑥1‬حسب 𝑡‪ .‬أي أن عدد المدخالت يزداد مع كمية البيانات التي‬
‫نواجهها‪ .‬وبالتالي‪ ،‬إذا أردنا التعامل مع بياناتنا التاريخية كمجموعة تدريب‪ ،‬فإننا نواجه مشكلة أن‬
‫كل مثال يحتوي على عدد مختلف من الميزات‪ .‬سوف يدور الكثير مما يلييف هذا الفصل حول‬
‫تقنيات التغلب على هذه التحديات عند االنخراطيف مشاكل نمذجة االنحدار الذاتي حيث يكون‬
‫موضوع االهتمام هو ) ‪𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1‬أو بعض اإلحصائيات الخاصة بهذا التوزيع‪.‬‬

‫تتكرر بعض االستراتيجيات بشكل متكرر‪ .‬أوالً‪ ،‬قد نعتقد أنه على الرغم من توفر التسلسالت‬
‫الطويلة ‪ ،𝑥𝑡−1 , … , 𝑥1‬فقد ال يكون من الضروري الرجوع إلى الوراء حتى اآلنيف التاريخ عند‬
‫التنبؤ بالمستقبل القريب‪.‬يف هذه الحالة‪ ،‬قد نكتفي بشرط بعض النوافذ الطويلة 𝜏 واستخدام‬
‫المالحظات 𝜏‪ 𝑥𝑡−1 , … , 𝑥𝑡−‬فقط‪ .‬الفائدة المباشرة هي أن عدد المدخالت اآلن هو نفسه دائمًا‪،‬‬
‫على األقل بالنسبة لـ 𝜏 > 𝑡‪ .‬هذا يسمح لنا بتدريب أي نموذج خطي أو شبكة عميقة تتطلب‬
‫متجهات ذات طول ثابت كمدخالت‪ .‬ثانيًا‪ ،‬قد نقوم بتطوير نماذج تحافظ على بعض الملخصات‬
‫𝑡‪ ℎ‬للمشاهدات السابقة (انظر الشكل ‪ )9.1.2‬وفي نفس الوقت يتم تحديث 𝑡‪ ℎ‬باإلضافة إلى‬
‫^‬ ‫^‬
‫التنبؤ 𝑡𝑥‪ .‬هذا يؤدي إلى النماذج التي تقدر مع ) 𝑡‪ 𝑥𝑡 = 𝑃(𝑥𝑡 ∣ ℎ‬باإلضافة إلى تحديثات‬
‫النموذج ) ‪ .ℎ𝑡 = 𝑔(ℎ𝑡−1 , 𝑥𝑡−1‬نظرًا لعدم مالحظة 𝑡‪ ℎ‬مطلقًا‪ ،‬فإن هذه النماذج تسمى أيضًا‬
‫نماذج االنحدار الذاتي الكامنة ‪.latent autoregressive models‬‬

‫إلنشاء بيانات التدريب من البيانات التاريخية‪ ،‬يقوم المرء عادة بإنشاء أمثلة عن طريق أخذ‬
‫العينات بشكل عشوائي‪ .‬بشكل عام‪ ،‬ال نتوقع وقتًا للوقوف بال حراك‪ .‬ومع ذلك‪ ،‬فإننا نفترض‬
‫غالبًا أنهيف حين أن القيم المحددة لـ 𝑡𝑥 قد تتغير‪ ،‬فإن الديناميكيات التي يتم وفقًا لها إنشاء كل‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪176‬‬

‫مالحظة الحقة بالنظر إلى المالحظات السابقة ال تتغير‪ .‬يسمي اإلحصائيون الديناميكيات التي ال‬
‫تتغير بالثبات ‪.stationary‬‬

‫الشكل ‪ 9.1.2‬نموذج االنحدار الذاتي الكامن ‪.latent autoregressive model‬‬

‫‪Sequence Models‬‬ ‫‪9.1.2‬‬


‫في بعض األحيان‪ ،‬خاصة عند العمل مع اللغة‪ ،‬نرغبيف تقدير االحتمال المشترك لتسلسل كامل‪.‬‬
‫هذه مهمة شائعة عند العمل مع التسلسالت المكونة من رموز منفصلة ‪ ،discrete tokens‬مثل‬
‫الكلمات‪ .‬بشكل عام‪ ،‬تسمى هذه الدوال المقدرة نماذج التسلسل ‪ sequence models‬وبالنسبة‬
‫لبيانات اللغة الطبيعية‪ ،‬يطلق عليها نماذج اللغة ‪ .language models‬لقد كان مجال نمذجة‬
‫التسلسل مدفوعًا إلى حد كبير بمعالجة اللغة الطبيعية‪ ،‬لدرجة أننا غالبًا ما نصف نماذج التسلسل‬
‫بأنها "نماذج لغة"‪ ،‬حتى عند التعامل مع البيانات غير اللغوية‪ .‬أثبتت النماذج اللغوية أنها مفيدة‬
‫لجميع أنواع األسباب‪.‬يف بعض األحيان نريد تقييم احتمالية الجمل‪ .‬على سبيل المثال‪ ،‬قد نرغب‬
‫في مقارنة الطبيعة الطبيعية لمخرجين مرشحين تم إنشاؤهما بواسطة نظام الترجمة اآللية أو عن‬
‫طريق نظام التعرف على الكالم‪ .‬لكن نمذجة اللغة ال تمنحنا فقط القدرة على تقييم االحتمالية‪،‬‬
‫ولكن أيضًا القدرة على أخذ عينات من التسلسالت‪ ،‬وحتى تحسين التسلسالت األكثر احتمالية‪.‬‬

‫في حين أن نمذجة اللغة قد ال تبدو‪ ،‬للوهلة األولى‪ ،‬كمشكلة االنحدار الذاتي‪ ،‬يمكننا تقليل‬
‫النمذجة اللغوية إلى التنبؤ االنحدار الذاتي عن طريق تحليل كثافة مفصل تسلسل ∣ 𝑡𝑥(𝑝‬
‫) 𝑇𝑥 ‪ 𝑥1 , … ,‬إلى ضرب كثافات شرطية بطريقة من اليسار إلى اليمين عن طريق تطبيق قاعدة‬
‫السلسلة لالحتمالية‪:‬‬
‫𝑇‬

‫∏ ) ‪𝑃(𝑥1 , … , 𝑥𝑇 ) = 𝑃(𝑥1‬‬ ‫‪𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1 ).‬‬


‫‪𝑡=2‬‬
‫‪177‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫الحظ أنه إذا كنا نعمل مع إشارات منفصلة مثل الكلمات‪ ،‬فيجب أن يكون نموذج االنحدار الذاتي‬
‫مصنفًا احتماليًا‪ ،‬مما ينتج عنه توزيع احتمالي كامل على المفردات الخاصة بالكلمات التي ستأتي‬
‫بعد ذلك‪ ،‬بالنظر إلى السياق األيسر‪.‬‬

‫‪Markov Models‬‬ ‫‪9.1.2.1‬‬


‫لنفترض اآلن أننا نرغبيف استخدام االستراتيجية المذكورة أعاله‪ ،‬حيث نشترط فقط على‬
‫الخطوات الزمنية السابقة 𝜏‪ ،‬أي 𝜏‪ ،𝑥𝑡−1 , … , 𝑥𝑡−‬بدالً من سجل التسلسل ‪ 𝑥𝑡−1 , … , 𝑥1‬بأكمله‪.‬‬
‫كلما استطعنا التخلص من التاريخ بعيدًا عن الخطوات الثمينة 𝜏 دون أي خسارةيف القدرة التنبؤية‪،‬‬
‫نقول إن التسلسل يلبي شرط ماركوف ‪ ،Markov condition‬أي أن المستقبل مستقل مشروطًا‬
‫عن الماضي‪ ،‬بالنظر إلى التاريخ الحديث‪ .‬عندما ‪ 𝜏 = 1‬نقول إن البيانات تتميز بنموذج ماركوف‬
‫من الدرجة األولى‪ ،‬و𝑘 = 𝜏 عندما نقول إن البيانات تتميز بنموذج ماركوف من الدرجة 𝑘‪ .‬عندما‬
‫𝑘 = 𝜏 يكون شرط ماركوف من الدرجة األولى (‪ ،)𝜏 = 1‬يصبح عامل احتمالنا المشترك نتاجًا‬
‫الحتماالت كل كلمة بالنظر إلى الكلمة السابقة‪:‬‬
‫𝑇‬

‫‪𝑃(𝑥1 , … , 𝑥𝑇 ) = 𝑃(𝑥1 ) ∏ 𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 ).‬‬


‫‪𝑡=2‬‬

‫غالبًا ما نجد أنه من المفيد العمل مع النماذج التي تستمر كما لو أن شرط ماركوف قد تم استيفائه‪،‬‬
‫حتى عندما نعلم أن هذا صحيح تقريبًا‪ .‬مع المستندات النصية الحقيقية‪ ،‬نستمريف الحصول على‬
‫المعلومات حيث نقوم بتضمين المزيد والمزيد من سياق اليسار‪ .‬لكن هذه المكاسب تتضاءل‬
‫بسرعة‪ .‬وبالتالي‪ ،‬فإننايف بعض األحيان نتنازل عن الصعوبات الحسابية واإلحصائية ونتجنبها من‬
‫خالل نماذج التدريب التي تعتمد صالحيتها على شرط ماركوف من الدرجة 𝑘‪ .‬حتى النماذج‬
‫اللغوية الضخمة القائمة على ‪ RNN‬والتي تعتمد على المحوالتيف الوقت الحاضر نادرًا ما‬
‫تتضمن أكثر من آالف كلمات السياق‪.‬‬

‫باستخدام البيانات المنفصلة ‪ ،discrete data‬يحسب نموذج ماركوف الحقيقي ببساطة عدد‬
‫المرات التي حدثت فيها كل كلمةيف كل سياق‪ ،‬مما ينتج عنه تقدير التردد النسبي لـ ∣ 𝑡𝑥(𝑃‬
‫) ‪ .𝑥𝑡−1‬عندما تفترض البيانات قيمًا منفصلة فقط (كمايف اللغة)‪ ،‬يمكن حساب التسلسل األكثر‬
‫احتماالً للكلمات بكفاءة باستخدام البرمجة الديناميكية ‪.dynamic programming‬‬

‫‪The Order of Decoding‬‬ ‫‪9.1.2.2‬‬


‫قد تتساءل‪ ،‬لماذا يتعين علينا تمثيل تحليل تسلسل نصي ) 𝑇𝑥 ‪ 𝑃(𝑥1 , … ,‬إلى عوامل كسلسلة من‬
‫االحتماالت الشرطية من اليسار إلى اليمين‪ .‬لماذا ال يكون ترتيبًا من اليمين إلى اليسار أو ترتيبًا‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪178‬‬

‫عشوائيًا آخر على ما يبدو؟ من حيث المبدأ‪ ،‬ال حرجيف ظهور ) 𝑇𝑥 ‪ 𝑃(𝑥1 , … ,‬بترتيب عكسي‪.‬‬
‫النتيجة هي التفكيك الى العوامل صالح ‪:valid factorization‬‬
‫‪1‬‬

‫∏ = ) 𝑇𝑥 ‪𝑃(𝑥1 , … ,‬‬ ‫‪𝑃(𝑥𝑡 ∣ 𝑥𝑡+1 , … , 𝑥𝑇 ).‬‬


‫𝑇=𝑡‬

‫ومع ذلك‪ ،‬هناك العديد من األسباب التي تجعل تحليل النص إلى عوامليف نفس االتجاهات التي‬
‫نقرأها (من اليسار إلى اليمين لمعظم اللغات‪ ،‬ولكن من اليمين إلى اليسار للعربية والعبرية)‬
‫مفضلًا لمهمة نمذجة اللغة‪ .‬أوالً‪ ،‬هذا مجرد اتجاه طبيعي أكثر بالنسبة لنا للتفكير فيه‪ .‬بعد كل‬
‫شيء نقرأ النص كل يوم‪ ،‬وتسترشد هذه العملية بقدرتنا على توقع الكلمات والعبارات التي من‬
‫المحتمل أن تأتي بعد ذلك‪ .‬فكر فقطيف عدد المرات التي أكملت فيها جملة شخص آخر‪.‬‬
‫وبالتالي‪ ،‬حتى لو لم يكن لدينا سبب آخر لتفضيل مثل هذه فك التشفير بالترتيب‪ ،‬فإنها ستكون‬
‫مفيدة فقط إذا كان لدينا حدس أفضل لما يجب أن يكون مرجحًا عند التنبؤ بهذا الترتيب‪.‬‬

‫ثانيًا‪ ،‬من خالل التحليل بالترتيب ‪ ،factorizing in order‬يمكننا تعيين احتماالت للتسلسالت‬
‫الطويلة بشكل تعسفي باستخدام نفس نموذج اللغة‪ .‬لتحويل االحتمالية عبر الخطوات ‪ 1‬من‬
‫خالل 𝑡 إلى احتمال يمتد إلى كلمة ‪ ،𝑡 + 1‬فإننا ببساطة نضربيف االحتمال الشرطي للرمز ‪token‬‬
‫المعطى اإلضافي بالنظر إلى االحتمالية السابقة‪𝑃(𝑥𝑡+1 , … , 𝑥1 ) = 𝑃(𝑥𝑡 , … , 𝑥1 ) ⋅ :‬‬
‫) ‪.𝑃(𝑥𝑡+1 ∣ 𝑥𝑡 , … , 𝑥1‬‬

‫ثالثًا‪ ،‬لدينا نماذج تنبؤية أقوى للتنبؤ بالكلمات المجاورة مقابل الكلمات الموجودةيف مواقع أخرى‬
‫عشوائية‪.‬يف حين أن جميع أوامر التحليل إلى العوامل صحيحة‪ ،‬فإنها ال تمثل بالضرورة جميعًا‬
‫مشاكل النمذجة التنبؤية السهلة على حد سواء‪ .‬ال ينطبق هذا على اللغة فحسب‪ ،‬بل ينطبق أيضًا‬
‫على أنواع البيانات األخرى‪ ،‬على سبيل المثال‪ ،‬عندما تكون البيانات منظمة سببيًا‪ .‬نعتقد أن‬
‫األحداث المستقبلية ال يمكن أن تؤثر على الماضي‪ .‬ومن ثم‪ ،‬إذا غيرنا 𝑡𝑥‪ ،‬فقد نتمكن من التأثير‬
‫على ما يحدث لـ ‪ 𝑥𝑡+1‬للمضي قدمًا ولكن ليس العكس‪ .‬أي‪ ،‬إذا غيرنا 𝑡𝑥‪ ،‬فإن التوزيع على‬
‫األحداث الماضية لن يتغير‪.‬يف بعض السياقات‪ ،‬يجعل هذا من السهل التنبؤ بـ ) 𝑡𝑥 ∣ ‪𝑃(𝑥𝑡+1‬‬
‫بدالً من التنبؤ بـ ) ‪ .𝑃(𝑥𝑡 ∣ 𝑥𝑡+1‬على سبيل المثال‪،‬يف بعض الحاالت‪ ،‬يمكننا أن نجد = ‪𝑥𝑡+1‬‬
‫𝜖 ‪ 𝑓(𝑥𝑡 ) +‬لبعض الضوضاء المضافة 𝜖‪ ،‬بينما العكس ليس صحيحًا (‪.)2009 ،Hoyer et al.‬‬
‫هذه أخبار رائعة‪ ،‬نظرًا ألنه عادةً ما يكون االتجاه األمامي هو الذي نهتم بتقديره‪ .‬كتاب بيترز‬
‫وآخرون (‪ ) 2017( .)Peters et al‬أوضح المزيد حول هذا الموضوع‪ .‬نحن بالكاد نخدش‬
‫سطحه‪.‬‬
‫‪179‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫‪Training‬‬ ‫‪9.1.3‬‬
‫قبل أن نركز اهتمامنا على البيانات النصية‪ ،‬دعنا نجرب ذلك أوالً باستخدام بعض البيانات‬
‫التركيبية ذات القيمة المستمرة ‪.continuous-valued synthetic data‬‬

‫‪%matplotlib inline‬‬
‫‪import tensorflow as tf‬‬
‫‪from d2l import tensorflow as d2l‬‬
‫هنا‪ ،‬ستتبع ‪ 1000‬بيانات تركيبية دالة المثلثية ‪ ،sin‬مطبقة على ‪ 0.01‬مرة من الخطوة الزمنية‪.‬‬
‫لجعل المشكلة أكثر إثارة لالهتمام‪ ،‬قمنا بإفساد كل عينة بضوضاء مضافة‪ .‬من هذا التسلسل‬
‫نستخرج أمثلة تدريبية‪ ،‬كل منها يتكون من ميزات وتسمية‪.‬‬

‫‪class Data(d2l.DataModule):‬‬
‫‪def __init__(self, batch_size=16, T=1000,‬‬
‫‪num_train=600, tau=4):‬‬
‫)(‪self.save_hyperparameters‬‬
‫)‪self.time = tf.range(1, T + 1, dtype=tf.float32‬‬
‫‪self.x = tf.sin(0.01 * self.time) +‬‬
‫‪tf.random.normal([T]) * 0.2‬‬

‫)(‪data = Data‬‬
‫‪d2l.plot(data.time, data.x, 'time', 'x', xlim=[1, 1000],‬‬
‫))‪figsize=(6, 3‬‬

‫للبدء‪ ،‬نجرب نموذجًا يعمل كما لو أن البيانات استوفت شرط ماركوف ذات الرتبة 𝜏 ‪ ،‬وبالتالي‬
‫يتنبأ باستخدام المالحظات السابقة 𝜏 فقط‪ .‬وبالتالي لكل خطوة زمنية لدينا مثال مع التسمية = 𝑦‬
‫𝑡𝑥 والميزات ] ‪ .𝐱𝑡 = [𝑥𝑡−𝜏 , … , 𝑥𝑡−1‬قد يكون القارئ الذكي قد الحظ أن هذه النتائجيف أمثلة‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪180‬‬

‫𝜏 ‪ ،1000 −‬ألننا نفتقر إلى التاريخ الكافي 𝜏𝑦 ‪ 𝑦1 , … ,‬لها‪ .‬بينما يمكننا وضع المتتاليات األولى‬
‫𝜏 باألصفار‪ ،‬إلبقاء األمور بسيطة‪ ،‬نقوم بإسقاطهايف الوقت الحالي‪ .‬تحتوي مجموعة البيانات‬
‫الناتجة على أمثلة 𝜏 ‪ ، 𝑇 −‬حيث يكون لكل إدخاليف النموذج طول تسلسل 𝜏‪ .‬نقوم بإنشاء مكرر‬
‫بياناتيف أول ‪ 600‬مثال‪ ،‬يغطي فترة دالة ‪.sin‬‬

‫)‪@d2l.add_to_class(Data‬‬
‫‪def get_dataloader(self, train):‬‬
‫‪features = [self.x[i : self.T-self.tau+i] for i in‬‬
‫])‪range(self.tau‬‬
‫)‪self.features = tf.stack(features, 1‬‬
‫))‪self.labels = tf.reshape(self.x[self.tau:], (-1, 1‬‬
‫‪i = slice(0, self.num_train) if train else‬‬
‫)‪slice(self.num_train, None‬‬
‫‪return self.get_tensorloader([self.features,‬‬
‫)‪self.labels], train, i‬‬
‫في هذا المثال سيكون نموذجنا انحدارًا خطيًا قياسيًا‪.‬‬

‫)‪model = d2l.LinearRegression(lr=0.01‬‬
‫)‪trainer = d2l.Trainer(max_epochs=5‬‬
‫)‪trainer.fit(model, data‬‬

‫‪Prediction‬‬ ‫‪9.1.4‬‬
‫لتقييم نموذجنا‪ ،‬نتحقق أوالً من مدى جودة أداء نموذجنا عند التنبؤ بخطوة واحدة لألمام ‪one-‬‬
‫‪.step-ahead prediction‬‬
‫‪181‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫)(‪onestep_preds = model(data.features).numpy‬‬
‫‪d2l.plot(data.time[data.tau:], [data.labels,‬‬
‫‪onestep_preds], 'time', 'x',‬‬
‫‪legend=['labels', '1-step preds'], figsize=(6,‬‬
‫))‪3‬‬

‫تبدو التوقعات بخطوة واحدة جيدة‪ ،‬حتى قرب النهاية ‪.𝑡 = 1000‬‬

‫فكر اآلن‪ ،‬ماذا لو الحظنا فقط بيانات التسلسل حتى الخطوة الزمنية ‪604‬‬
‫(‪ )n_train + tau‬ولكننا نرغبيف عمل تنبؤات عدة خطواتيف المستقبل‪ .‬لسوء الحظ‪ ،‬ال‬
‫يمكننا حساب التنبؤ بخطوة واحدة للخطوة الزمنية ‪ 609‬مباشرة‪ ،‬ألننا ال نعرف المدخالت‬
‫المقابلة‪ ،‬بعد أن رأينا فقط حتى ‪ .𝑥604‬يمكننا معالجة هذه المشكلة عن طريق إدخال توقعاتنا‬
‫السابقة كمدخالت لنموذجنا لعمل تنبؤات الحقة‪ ،‬والتوقع لألمام‪ ،‬خطوة واحدةيف كل مرة‪ ،‬حتى‬
‫الوصول إلى الخطوة الزمنية المطلوبة‪:‬‬
‫^‬
‫‪𝑥605 = 𝑓(𝑥601 , 𝑥602 , 𝑥603 , 𝑥604 ),‬‬
‫^‬ ‫^‬
‫‪𝑥606 = 𝑓(𝑥602 , 𝑥603 , 𝑥604 , 𝑥605 ),‬‬
‫^‬ ‫^‬ ‫^‬
‫‪𝑥607 = 𝑓(𝑥603 , 𝑥604 , 𝑥605 , 𝑥606 ),‬‬
‫^‬ ‫^‬ ‫^‬ ‫^‬
‫‪𝑥608 = 𝑓(𝑥604 , 𝑥605 , 𝑥606 , 𝑥607 ),‬‬
‫^‬ ‫^‬ ‫^‬ ‫^‬ ‫^‬
‫‪𝑥609 = 𝑓(𝑥605 , 𝑥606 , 𝑥607 , 𝑥608 ),‬‬
‫…‬
‫^‬
‫بشكل عام‪ ،‬بالنسبة للتسلسل المرصود 𝑡𝑥 ‪ ،𝑥1 , … ,‬خرجه المتوقع 𝑘‪𝑥𝑡+‬يف الخطوة الزمنية ‪𝑡 +‬‬
‫𝑘 يسمى بالتنبؤ بـ 𝑘 خطوة إلى األمام ‪ .k-step-ahead prediction‬منذ أن الحظنا حتى ‪،𝑥604‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪182‬‬

‫^‬
‫التنبؤ بخطوة 𝑘 لألمام هو 𝑘‪ . 𝑥604+‬بمعنى آخر‪ ،‬سيتعين علينا االستمراريف استخدام تنبؤاتنا‬
‫الخاصة لعمل تنبؤات متعددة الخطوات‪ .‬دعونا نرى كيف تسير األمور على ما يرام‪.‬‬

‫))‪multistep_preds = tf.Variable(tf.zeros(data.T‬‬
‫)‪multistep_preds[:].assign(data.x‬‬
‫‪for i in range(data.num_train + data.tau, data.T):‬‬
‫(‪multistep_preds[i].assign(tf.reshape(model‬‬
‫‪tf.reshape(multistep_preds[i-data.tau : i], (1,‬‬
‫)))( ‪-1))),‬‬

‫‪d2l.plot([data.time[data.tau:],‬‬
‫‪data.time[data.num_train+data.tau:]],‬‬
‫‪[onestep_preds,‬‬
‫‪multistep_preds[data.num_train+data.tau:]], 'time',‬‬
‫‪'x', legend=['1-step preds', 'multistep‬‬
‫))‪preds'], figsize=(6, 3‬‬

‫لسوء الحظ‪،‬يف هذه الحالة نفشل بشكل مذهل‪ .‬تتحلل التنبؤات إلى ثابت بسرعة كبيرة بعد بضع‬
‫خطوات تنبؤ‪ .‬لماذا كان أداء الخوارزمية أسوأ بكثير عند توقع المزيديف المستقبل؟يف النهاية‪ ،‬يرجع‬
‫هذا إلى حقيقة أن األخطاء تتراكم‪ .‬لنفترض أنه بعد الخطوة ‪ 1‬لدينا بعض الخطأ 𝜖 = ‪ . 𝜖1‬اآلن‬
‫مدخالت الخطوة ‪ 2‬مضطربة بواسطة ‪ ،𝜖1‬وبالتالي نعاني من بعض الخطأيف ترتيب ‪𝜖2 = 𝜖 +‬‬
‫‪ 𝑐𝜖1‬لبعض الثابت 𝑐‪ ،‬وما إلى ذلك‪ .‬يمكن أن تتباعد التنبؤات بسرعة عن المالحظات الحقيقية‪.‬‬
‫قد تكون بالفعل على دراية بهذه الظاهرة الشائعة‪ .‬على سبيل المثال‪ ،‬تنبؤات الطقس خالل الـ‬
‫‪ 24‬ساعة القادمة تميل إلى أن تكون دقيقة جدًا ولكن بعد ذلك‪ ،‬تنخفض الدقة بسرعة‪ .‬سنناقش‬
‫طرق تحسين هذا خالل هذا الفصل وما بعده‪.‬‬
183 ‫ الشبكات العصبية المتكررة‬:‫الفصل التاسع‬

‫دعونا نلقي نظرة فاحصة على الصعوباتيف بالتنبؤات بـ 𝑘 خطوة إلى األمام عن طريق حساب‬
𝑘 = 1,4,16,64 ‫التنبؤات على التسلسل الكامل لـ‬

def k_step_pred(k):
features = []
for i in range(data.tau):
features.append(data.x[i : i+data.T-data.tau-
k+1])
# The (i+tau)-th element stores the (i+1)-step-ahead
predictions
for i in range(k):
preds = model(tf.stack(features[i : i+data.tau],
1))
features.append(tf.reshape(preds, -1))
return features[data.tau:]

steps = (1, 4, 16, 64)


preds = k_step_pred(steps[-1])
d2l.plot(data.time[data.tau+steps[-1]-1:],
[preds[k - 1].numpy() for k in steps], 'time',
'x',
legend=[f'{k}-step preds' for k in steps],
figsize=(6, 3))

‫يف حين أن‬.‫يوضح هذا بوضوح كيف تتغير جودة التنبؤ بينما نحاول التنبؤ أكثريف المستقبل‬
‫ فإن أي شيء‬،‫ ال تزال تبدو جيدة‬4-step-ahead predictions ‫التنبؤات ذات األربع خطوات‬
.‫يتجاوز ذلك يكون عديم الفائدة تقريبًا‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪184‬‬

‫‪9.1.5‬‬
‫هناك اختالف كبيريف الصعوبة بين االستيفاء ‪interpolation‬واالستقراء ‪.interpolation‬‬
‫وبالتالي‪ ،‬إذا كان لديك تسلسل ‪ ،sequence‬فاحترم دائمًا الترتيب الزمني للبيانات عند التدريب‪،‬‬
‫أي ال تتدرب أبدًا على البيانات المستقبلية‪ .‬بالنظر إلى هذا النوع من البيانات‪ ،‬تتطلب نماذج‬
‫التسلسل أدوات إحصائية متخصصة للتقدير‪ .‬هناك خياران شائعان هما نماذج االنحدار الذاتي‬
‫‪ autoregressive models‬ونماذج االنحدار التلقائي المتغيرة الكامنة ‪latent-variable‬‬
‫‪ .autoregressive models‬بالنسبة للنماذج السببية ‪( causal models‬على سبيل المثال‪،‬‬
‫الوقتيف المضي قدمًا ‪ ،)time going forward‬يكون تقدير االتجاه األمامي أسهل كثيرًا من‬
‫االتجاه العكسي‪ .‬بالنسبة للتسلسل المرصود حتى الخطوة الزمنية‪ ،‬فإن ناتجها المتوقعيف الخطوة‬
‫الزمنية هو التنبؤ بالخطوة إلى األمام‪ .‬كلما توقعنا مزيدًا من الوقت من خالل الزيادة‪ ،‬تتراكم‬
‫األخطاء وتتدهور جودة التنبؤ‪ ،‬غالبًا بشكل كبير‪.‬‬

‫‪9.1.6‬‬
‫‪ .1‬قم بتحسين النموذج في تجربة هذا القسم‪.‬‬
‫‪ .1‬هل تدمج أكثر من المشاهدات ‪ observations‬األربع الماضية؟ كم تحتاج حقا؟‬
‫‪ .2‬كم عدد المشاهدات السابقة التي ستحتاجها إذا لم يكن هناك ضوضاء؟ تلميح‪:‬‬
‫يمكنك الكتابة كمعادلة تفاضلية ‪.cos‬‬
‫‪ .3‬هل يمكنك دمج المشاهدات القديمة مع الحفاظ على العدد اإلجمالي للسمات‬
‫ثابتًا؟ هل هذا يحسن الدقة؟ لماذا؟‬
‫‪ .4‬قم بتغيير بُ نية الشبكة العصبية وتقييم األداء‪ .‬يمكنك تدريب النموذج الجديد‬
‫بمزيد من الفترات ‪ .epochs‬ماذا تالحظ؟‬
‫‪ .2‬يرغب المستثمر في العثور على ورقة مالية جيدة للشراء‪ .‬ينظر إلى العوائد السابقة ليقرر‬
‫أيها من المرجح أن يكون جيدًا‪ .‬ما الذي يمكن أن يحدث خطأ في هذه االستراتيجية؟‬
‫‪ .3‬هل السببية ‪ causality‬تنطبق أيضا على النص؟ إلى أي مدى؟‬
‫‪ .4‬أعط مثاالً عندما قد تكون هناك حاجة إلى نموذج االنحدار التلقائي الكامن اللتقاط‬
‫ديناميكية البيانات‪.‬‬

‫‪Converting Raw Text‬‬ ‫‪9.2‬‬


‫‪into Sequence Data‬‬
‫خالل هذا الكتاب‪ ،‬سنعمل غالبًا مع بيانات نصية ممثلةيف شكل تسلسالت من الكلمات أو‬
‫األحرف أو مقاطع الكلمات‪ .‬للبدء‪ ،‬سنحتاج إلى بعض األدوات األساسية لتحويل النص الخام‬
‫‪185‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫‪ raw text‬إلى تسلسالت ‪ sequences‬بالشكل المناسب‪ .‬تنفذ خطوط األنابيب النموذجية‬


‫المعالجة المسبقة ‪ Typical preprocessing pipelines‬الخطوات التالية‪:‬‬

‫‪ .1‬تحميل النص كسالسل ‪ strings‬في الذاكرة‪.‬‬


‫‪ .2‬قسّم السالسل إلى رموز ‪( tokens‬مثل الكلمات أو األحرف)‪.‬‬
‫‪ .3‬قم ببناء قاموس مفردات لربط كل عنصر من عناصر المفردات بفهرس رقمي‪.‬‬
‫‪ .4‬تحويل النص إلى متسلسالت ‪ sequences‬من المؤشرات الرقمية‪.‬‬

‫‪5.‬‬ ‫‪import collections‬‬


‫‪6.‬‬ ‫‪import random‬‬
‫‪7.‬‬ ‫‪import re‬‬
‫‪8.‬‬ ‫‪import tensorflow as tf‬‬
‫‪9.‬‬ ‫‪from d2l import tensorflow as d2l‬‬
‫‪Reading the Dataset‬‬ ‫‪9.2.1‬‬
‫هنا ‪ ،‬سنعمل مع كتاب ‪ The Time Machine‬لـ ‪ ،H.G Wells‬وهو كتاب يحتوي على ما‬
‫يزيد قليالً عن ‪ 30000‬كلمة‪ .‬في حين أن التطبيقات الحقيقية ستشمل عادةً مجموعات بيانات‬
‫أكبر بكثير‪ ،‬فإن هذا يكفي إلثبات خط أنابيب المعالجة المسبقة‪ .‬تقرأ طريقة ‪_download‬‬
‫التالية النص الخام في سلسلة نصية‪.‬‬

‫‪class TimeMachine(d2l.DataModule): #@save‬‬


‫‪def _download(self):‬‬
‫‪fname = d2l.download(d2l.DATA_URL +‬‬
‫‪'timemachine.txt', self.root,‬‬

‫)'‪'090b5e7e70c295757f55df93cb0a180b9691891a‬‬
‫‪with open(fname) as f:‬‬
‫)(‪return f.read‬‬

‫)(‪data = TimeMachine‬‬
‫)(‪raw_text = data._download‬‬
‫]‪raw_text[:60‬‬
‫‪'The Time Machine, by H. G. Wells‬‬
‫'‪[1898]nnnnnInnnThe Time Tra‬‬
‫للتبسيط ‪ ،‬نتجاهل عالمات الترقيم والكتابة باألحرف الكبيرة عند المعالجة المسبقة للنص الخام‬
‫‪.raw text‬‬

‫‪@d2l.add_to_class(TimeMachine) #@save‬‬
‫‪def _preprocess(self, text):‬‬
‫)(‪return re.sub('[^A-Za-z]+', ' ', text).lower‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪186‬‬

‫)‪text = data._preprocess(raw_text‬‬
‫]‪text[:60‬‬
‫‪'the time machine by h g wells i the time traveller for‬‬
‫'‪so it‬‬
‫‪Tokenization‬‬ ‫‪9.2.2‬‬
‫الرموز ‪ Tokens‬هي الوحدات الذرية (غير القابلة للتجزئة) للنص‪ .‬تتوافق كل خطوة زمنية مع‬
‫رمز ‪ Token‬واحد‪ ،‬ولكن ما يشكل رمزًا على وجه التحديد هو اختيار التصميم‪ .‬على سبيل‬
‫المثال ‪ ،‬يمكننا تمثيل الجملة "‪ " Baby needs a new pair of shoes‬على شكل سلسلة من‬
‫‪ 7‬كلمات ‪ ،‬حيث تشتمل مجموعة كل الكلمات على مفردات كبيرة (عادةً عشرات أو مئات‬
‫اآلالف من الكلمات)‪ .‬أو قد نمثل نفس الجملة كتسلسل أطول بكثير من ‪ 30‬حرفًا ‪ ،‬باستخدام‬
‫مفردات أصغر بكثير( ال يوجد سوى ‪ 256‬حرف ‪ ASCII‬مميز ‪).‬أدناه ‪ ،‬نقوم بترميز نصنا المعالج‬
‫مسبقًا إلى سلسلة من األحرف‪.‬‬

‫)‪@d2l.add_to_class(TimeMachine‬‬ ‫‪#@save‬‬
‫‪def _tokenize(self, text):‬‬
‫)‪return list(text‬‬

‫)‪tokens = data._tokenize(text‬‬
‫)]‪','.join(tokens[:30‬‬
‫‪'t,h,e, ,t,i,m,e, ,m,a,c,h,i,n,e, ,b,y, ,h, ,g,‬‬
‫' ‪,w,e,l,l,s,‬‬
‫‪Vocabulary‬‬ ‫‪9.2.3‬‬
‫هذه الرموز ‪ tokens‬ال تزال سالسل ‪ .strings‬ومع ذلك ‪ ،‬يجب أن تتكون مدخالت نماذجنا في‬
‫النهاية من مدخالت رقمية‪ .‬بعد ذلك ‪ ،‬نقدم فئة إلنشاء المفردات ‪ ،vocabularies‬أي الكائنات‬
‫التي تربط كل قيمة رمزية مميزة بفهرس فريد ‪ .unique index‬أوالً‪ ،‬نحدد مجموعة الرموز‬
‫الفريدة في مجموعة التدريب الخاصة بنا‪ .‬ثم نقوم بتعيين فهرس رقمي لكل رمز فريد ‪unique‬‬
‫‪ . token‬غالبًا ما يتم حذف عناصر المفردات النادرة للراحة‪ .‬عندما نواجه رمزًا مميزًا في وقت‬
‫التدريب أو االختبار لم يسبق رؤيته أو تم إسقاطه من المفردات‪ ،‬فإننا نقوم بتمثيله برمز‬
‫”>‪ ،“<unk‬مما يدل على أن هذه قيمة غير معروفة ‪.unknown value‬‬

‫‪class Vocab: #@save‬‬


‫"""‪"""Vocabulary for text.‬‬
‫‪def __init__(self, tokens=[], min_freq=0,‬‬
‫‪reserved_tokens=[]):‬‬
‫‪# Flatten a 2D list if needed‬‬
‫‪if tokens and isinstance(tokens[0], list):‬‬
187 ‫ الشبكات العصبية المتكررة‬:‫الفصل التاسع‬

tokens = [token for line in tokens for token


in line]
# Count token frequencies
counter = collections.Counter(tokens)
self.token_freqs = sorted(counter.items(),
key=lambda x: x[1],
reverse=True)
# The list of unique tokens
self.idx_to_token = list(sorted(set(['<unk>'] +
reserved_tokens + [
token for token, freq in self.token_freqs if
freq >= min_freq])))
self.token_to_idx = {token: idx
for idx, token in
enumerate(self.idx_to_token)}

def __len__(self):
return len(self.idx_to_token)

def __getitem__(self, tokens):


if not isinstance(tokens, (list, tuple)):
return self.token_to_idx.get(tokens,
self.unk)
return [self.__getitem__(token) for token in
tokens]

def to_tokens(self, indices):


if hasattr(indices, '__len__') and len(indices)
> 1:
return [self.idx_to_token[int(index)] for
index in indices]
return self.idx_to_token[indices]

@property
def unk(self): # Index for the unknown token
return self.token_to_idx['<unk>']
‫ وتحويل تسلسل السالسل إلى قائمة من‬، ‫نقوم اآلن ببناء مفردات لمجموعة البيانات الخاصة بنا‬
‫ الحظ أننا لم نفقد أي معلومات ويمكننا بسهولة‬.numerical indices ‫المؤشرات الرقمية‬
.)string ‫تحويل مجموعة البيانات الخاصة بنا إلى تمثيلها األصلي (سلسلة‬

vocab = Vocab(tokens)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪188‬‬

‫]]‪indices = vocab[tokens[:10‬‬
‫)‪print('indices:', indices‬‬
‫))‪print('words:', vocab.to_tokens(indices‬‬
‫]‪indices: [21, 9, 6, 0, 21, 10, 14, 6, 0, 14‬‬
‫‪words: ['t', 'h', 'e', ' ', 't', 'i', 'm', 'e', ' ',‬‬
‫]'‪'m‬‬
‫‪Putting It All Together‬‬ ‫‪9.2.4‬‬
‫باستخدام الفئات والطرق المذكورة أعاله ‪ ،‬نقوم بتجميع كل شيء في طريقة اإلنشاء التالية لفئة‬
‫‪ ، TimeMachine‬والتي تُرجع المجموعة ‪ ، corpus‬وقائمة من المؤشرات المرمزة ‪token‬‬
‫‪ ، indices‬والمفردات ‪ ، vocab‬وهي مفردات مجموعة ‪ .The Time Machine‬التعديالت‬
‫التي أجريناها هنا هي‪ ) 1( :‬نقوم بترميز النص إلى أحرف ‪ ،‬وليس كلمات ‪ ،‬لتبسيط التدريب في‬
‫أقسام الحقة ؛ (‪ ) 2‬المجموعة عبارة عن قائمة واحدة‪ ،‬وليست قائمة بقوائم الرموز ‪ ،‬نظرًا ألن كل‬
‫سطر نص في مجموعة بيانات ‪ The Time Machine‬ليس بالضرورة جملة أو فقرة‪.‬‬

‫‪@d2l.add_to_class(TimeMachine) #@save‬‬
‫‪def build(self, raw_text, vocab=None):‬‬
‫))‪tokens = self._tokenize(self._preprocess(raw_text‬‬
‫)‪if vocab is None: vocab = Vocab(tokens‬‬
‫]‪corpus = [vocab[token] for token in tokens‬‬
‫‪return corpus, vocab‬‬

‫)‪corpus, vocab = data.build(raw_text‬‬


‫)‪len(corpus), len(vocab‬‬
‫)‪(173428, 28‬‬
‫‪Exploratory Language Statistics‬‬ ‫‪9.2.5‬‬
‫باستخدام المجموعة الحقيقية وكالس ‪ Vocab‬المحدد عبر الكلمات‪ ،‬يمكننا فحص‬
‫اإلحصائيات األساسية المتعلقة باستخدام الكلمات في مجموعتنا‪ .‬أدناه ‪ ،‬نبني مفردات من‬
‫الكلمات المستخدمة في ‪ The Time Machine‬ونطبع أكثر ‪ 10‬كلمات تكرارا‪.‬‬

‫)(‪words = text.split‬‬
‫)‪vocab = Vocab(words‬‬
‫]‪vocab.token_freqs[:10‬‬
‫‪[('the', 2261),‬‬
‫‪('i', 1267),‬‬
‫‪('and', 1245),‬‬
‫‪('of', 1155),‬‬
‫‪('a', 816),‬‬
‫‪('to', 695),‬‬
‫‪189‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫‪('was', 552),‬‬
‫‪('in', 541),‬‬
‫‪('that', 443),‬‬
‫])‪('my', 440‬‬
‫الحظ أن الكلمات العشر األكثر شيوعًا ليست كلها وصفية ‪ .descriptive‬قد تتخيل أننا قد نرى‬
‫قائمة مشابهة جدًا إذا اخترنا أي كتاب عشوائيًا‪ .‬مقاالت مثل "‪ "the‬و "‪ ، "a‬ضمائر مثل "‪ "i‬و‬
‫"‪ ، "my‬وحروف الجر مثل "‪ "of‬و "‪ "to‬و "‪ "in‬تحدث غالبًا ألنها تخدم أدوارًا نحوية مشتركة‪.‬‬
‫غالبًا ما تسمى هذه الكلمات الشائعة في آن واحد ولكنها وصفية بشكل خاص كلمات التوقف‬
‫‪ ، stop words‬وفي األجيال السابقة من مصنفات النص التي تستند إلى تمثيالت كيس من‬
‫الكلمات ‪ ، bag-of-words‬غالبًا ما يتم تصفيتها‪ .‬ومع ذلك ‪ ،‬فهي تحمل معنى وليس من‬
‫الضروري تصفيتها عند العمل مع النماذج العصبية الحديثة القائمة على ‪ RNN‬والمحول‪ .‬إذا‬
‫نظرت إلى أسفل القائمة‪ ،‬ستالحظ أن تردد الكلمات يتالشى بسرعة‪ .‬الكلمة العاشرة األكثر شيوعًا‬
‫هي أقل من ‪ 1/5‬مثل الكلمة األكثر شيوعًا‪ .‬يميل تردد الكلمات إلى اتباع توزيع قانون السلطة‬
‫‪( power law distribution‬تحديدًا ‪ )Zipfian‬أثناء نزولنا في المراتب ‪ .ranks‬للحصول‬
‫على فكرة أفضل‪ ،‬نرسم رقم تكرار الكلمة ‪.word frequency‬‬

‫]‪freqs = [freq for token, freq in vocab.token_freqs‬‬


‫‪d2l.plot(freqs, xlabel='token: x', ylabel='frequency:‬‬
‫‪n(x)',‬‬
‫)'‪xscale='log', yscale='log‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪190‬‬

‫بعد التعامل مع الكلمات القليلة األولى كاستثناءات‪ ،‬تتبع جميع الكلمات المتبقية تقريبًا خطًا‬
‫مستقيمًا في رسم ‪ .log-log‬يلتقط قانون ‪ Zipf‬هذه الظاهرة ‪ ،‬والذي ينص على أن تكرار 𝑖𝑛‬
‫الكلمة األكثر شيوعًا هو‪:‬‬

‫‪1‬‬
‫∝ 𝑖𝑛‬ ‫‪,‬‬
‫𝛼𝑖‬
‫وهو ما يعادل‪:‬‬

‫‪log 𝑛𝑖 = −𝛼log 𝑖 + 𝑐,‬‬

‫حيث 𝛼 هو األس الذي يميز التوزيع وهو ثابت‪ .‬يجب أن يمنحنا هذا بالفعل وقفة إذا أردنا نمذجة‬
‫الكلمات عن طريق حساب اإلحصائيات‪ .‬بعد كل شيء‪ ،‬سنبالغ في تقدير تكرار الذيل‪،‬‬
‫والمعروف أيضًا باسم الكلمات النادرة ‪ .infrequent words‬ولكن ماذا عن تركيبات الكلمات‬
‫األخرى ‪ ،‬مثل كلمتين متتاليتين (‪ ، )bigrams‬وثالث كلمات متتالية (‪ ، )trigrams‬وما بعدها؟‬
‫دعونا نرى ما إذا كان تردد ‪ bigram‬يتصرف بنفس طريقة تكرار الكلمة المفردة (‪.)unigram‬‬

‫‪bigram_tokens = ['--'.join(pair) for pair in‬‬


‫])]‪zip(words[:-1], words[1:‬‬
‫)‪bigram_vocab = Vocab(bigram_tokens‬‬
‫]‪bigram_vocab.token_freqs[:10‬‬
‫‪[('of--the', 309),‬‬
‫‪('in--the', 169),‬‬
‫‪('i--had', 130),‬‬
‫‪('i--was', 112),‬‬
‫‪('and--the', 109),‬‬
‫‪('the--time', 102),‬‬
‫‪('it--was', 99),‬‬
‫‪('to--the', 85),‬‬
‫‪('as--i', 78),‬‬
‫])‪('of--a', 73‬‬
‫شيء واحد ملحوظ هنا‪ .‬من بين أزواج الكلمات العشرة األكثر شيوعًا ‪ ،‬تتكون تسعة من كلتا‬
‫كلمات التوقف وواحدة فقط ذات صلة بالكتاب الفعلي ‪ ." the time" -‬عالوة على ذلك ‪ ،‬دعنا‬
‫نرى ما إذا كان تردد الشكل الثالثي ‪ trigram‬يتصرف بنفس الطريقة‪.‬‬

‫(‪trigram_tokens = ['--'.join(triple) for triple in zip‬‬


‫])]‪words[:-2], words[1:-1], words[2:‬‬
‫)‪trigram_vocab = d2l.Vocab(trigram_tokens‬‬
‫]‪trigram_vocab.token_freqs[:10‬‬
‫‪[('the--time--traveller', 59),‬‬
191 ‫ الشبكات العصبية المتكررة‬:‫الفصل التاسع‬

('the--time--machine', 30),
('the--medical--man', 24),
('it--seemed--to', 16),
('it--was--a', 15),
('here--and--there', 15),
('seemed--to--me', 14),
('i--did--not', 14),
('i--saw--the', 13),
('i--began--to', 13)]
‫ األحادي‬:‫ بين هذه النماذج الثالثة‬token frequency ‫ دعنا نتخيل معدل تكرار الرمز‬، ‫أخيرًا‬
.trigrams‫ و‬، bigrams‫ و‬، unigrams

bigram_freqs = [freq for token, freq in


bigram_vocab.token_freqs]
trigram_freqs = [freq for token, freq in
trigram_vocab.token_freqs]
d2l.plot([freqs, bigram_freqs, trigram_freqs],
xlabel='token: x',
ylabel='frequency: n(x)', xscale='log',
yscale='log',
legend=['unigram', 'bigram', 'trigram'])

‫ يبدو أيضًا أن تسلسل الكلمات يتبع‬، unigram ‫ بخالف كلمات‬، ً‫ أوال‬.‫هذا الرقم مثير للغاية‬
n- ‫ عدد‬، ‫ ثانيًا‬.‫ اعتمادًا على طول التسلسل‬، )9.2.1( ‫ وإن كان بأس أصغر 𝛼 في‬، Zipf ‫قانون‬
.‫ هذا يعطينا األمل في أن هناك قدرًا كبيرًا من ال ُبنية في اللغة‬.‫ المميزة ليس بهذه الضخامة‬grams
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪192‬‬

‫ثالثًا ‪ ،‬نادرًا ما تحدث العديد من ‪ .n-grams‬هذا يجعل بعض األساليب غير مناسبة لنمذجة‬
‫اللغة ويحفز استخدام نماذج التعلم العميق‪ .‬سنناقش هذا في القسم التالي‪.‬‬

‫‪9.2.6‬‬
‫يعتبر النص من أكثر أشكال بيانات التسلسل شيوعًايف التعلم العميق‪ .‬الخيارات الشائعة لما يشكل‬
‫رمزًا ‪ token‬هي األحرف والكلمات وقطع الكلمات‪ .‬لمعالجة النص‪ ،‬نقوم عادةً (‪ )1‬بتقسيم‬
‫النص إلى رموز ‪tokens‬؛ (‪ )2‬بناء مفردات لتعيين سالسل الرموز ‪ token strings‬إلى مؤشرات‬
‫رقمية ‪numerical indices‬؛ و (‪ )3‬تحويل البيانات النصية إلى مؤشرات رمزية ‪token‬‬
‫‪ indices‬للنماذج للتالعب بها‪ .‬من الناحية العملية‪ ،‬فإن تكرار الكلمات يميل إلى اتباع قانون‬
‫‪ .Zipf‬هذا صحيح ليس فقط للكلمات الفردية (‪ ،)unigrams‬ولكن أيضًا بالنسبة إلى ‪n-‬‬
‫‪.grams‬‬

‫‪9.2.7‬‬
‫‪ .1‬في تجربة هذا القسم‪ ،‬قم بترميز ‪ tokenize‬النص إلى كلمات وقم بتغيير قيمة وسيطة‬
‫‪ min_freq‬لمثيل ‪ .Vocab‬صف نوعياً كيف تؤثر التغييراتيف ‪ min_freq‬على‬
‫حجم المفردات الناتجة‪.‬‬
‫‪ .2‬قدر اُس توزيع ‪ Zipfian‬لـ ‪ unigrams‬و‪ bigrams‬و‪trigrams‬يف هذه المجموعة‬
‫‪.corpus‬‬
‫‪ .3‬ابحث عن بعض مصادر البيانات األخرى (قم بتنزيل مجموعة بيانات قياسية للتعلم‬
‫اآللي‪ ،‬واختر كتابًا آخريف مجال عام اخر‪ ،‬واكتشف موقعًا إلكترونيًا‪ ،‬وما إلى ذلك)‪.‬‬
‫لكل منها‪ ،‬قم بترميز البيانات على مستوى الكلمة والحرف‪ .‬كيف تقارن أحجام‬
‫المفردات مع مجموعة ‪ The Time Machine‬بقيم مكافئة لـ ‪ .min_freq‬قدر‬
‫األس لتوزيع ‪ Zipfian‬المقابل لتوزيعات ‪ unigram‬و‪ bigram‬لهذه المجموعات‪.‬‬
‫كيف تتم مقارنتها بالقيم التي الحظتها لمجموعة ‪The Time Machine‬؟‬

‫‪Language Models‬‬ ‫‪9.3‬‬


‫في القسم ‪ ،9.2‬رأينا كيفية تعيين تسلسالت نصية ‪ text sequences‬إلى رموز ‪ ،tokens‬حيث‬
‫يمكن عرض هذه الرموز على أنها سلسلة من المشاهدات المنفصلة‪ ،‬مثل الكلمات أو األحرف‪.‬‬
‫افترض أن الرموزيف تسلسل نصي للطول 𝑇 هي بدورها 𝑇𝑥 ‪ .𝑥1 , 𝑥2 , … ,‬الهدف من النماذج‬
‫اللغوية هو تقدير االحتمال المشترك للتسلسل بأكمله‪:‬‬

‫‪𝑃(𝑥1 , 𝑥2 , … , 𝑥𝑇 ),‬‬

‫حيث يمكن تطبيق األدوات اإلحصائية في القسم ‪.9.1‬‬


‫‪193‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫النماذج اللغوية ‪ Language models‬مفيدة بشكل ال يصدق‪ .‬على سبيل المثال ‪ ،‬سيكون نموذج‬
‫اللغة المثالي قادرًا على إنشاء نص طبيعي بمفرده ‪ ،‬وذلك ببساطة عن طريق رسم رمز واحد في‬
‫كل مرة ) ‪ .𝑥𝑡 ∼ 𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1‬على عكس القرد الذي يستخدم آلة كاتبة ‪ ،‬فإن كل النص‬
‫الخارج من هذا النموذج سيمر كلغة طبيعية ‪ ،‬على سبيل المثال ‪ ،‬نص إنجليزي‪ .‬عالوة على ذلك‪،‬‬
‫سيكون كافيًا إلنشاء حوار هادف ‪ ،‬ببساطة عن طريق تكييف النص على أجزاء الحوار السابقة‪.‬‬
‫من الواضح أننا ما زلنا بعيدين جدًا عن تصميم مثل هذا النظام ‪ ،‬ألنه سيحتاج إلى فهم النص‬
‫بدالً من مجرد إنشاء محتوى معقول نحويًا‪.‬‬

‫ومع ذلك ‪ ،‬فإن النماذج اللغوية تقدم خدمة رائعة حتى في شكلها المحدود‪ .‬على سبيل المثال ‪،‬‬
‫الجملتان "‪ "to recognize speech‬و "‪ "to wreck a nice beach‬تبدو متشابهة جدًا‪ .‬يمكن‬
‫أن يتسبب هذا في الغموض في التعرف على الكالم ‪ ،‬والذي يمكن حله بسهولة من خالل نموذج‬
‫لغ وي يرفض الترجمة الثانية باعتبارها غريبة‪ .‬وبالمثل ‪ ،‬في خوارزمية تلخيص المستندات‬
‫‪ ،document summarization‬من المفيد معرفة أن "‪ "dog bites man‬أكثر تكرارًا من‬
‫"‪ ، "man bites dog‬أو أن عبارة "‪ "I want to eat grandma‬هي عبارة مزعجة إلى حد ما ‪،‬‬
‫بينما "‪"I want to eat, grandma‬أكثر اعتدالًا‪.‬‬

‫‪Learning Language Models‬‬ ‫‪9.3.1‬‬


‫السؤال الواضح هو كيف يجب أن نمثل مستندًا ‪ ،‬أو حتى سلسلة من الرموز ‪ .tokens‬افترض‬
‫أننا نقوم بترميز ‪ tokenize‬البيانات النصية على مستوى الكلمة‪ .‬لنبدأ بتطبيق قواعد االحتمال‬
‫األساسية‪:‬‬
‫𝑇‬

‫∏ = ) 𝑇𝑥 ‪𝑃(𝑥1 , 𝑥2 , … ,‬‬ ‫‪𝑃(𝑥𝑡 ∣ 𝑥1 , … , 𝑥𝑡−1 ).‬‬


‫‪𝑡=1‬‬

‫على سبيل المثال ‪ ،‬يمكن إعطاء احتمال وجود تسلسل نصي يحتوي على أربع كلمات على النحو‬
‫التالي‪:‬‬

‫‪𝑃(deep,learning,is,fun) = 𝑃(deep)𝑃(learning ∣ deep)𝑃(is ∣ deep,learning)𝑃(fun ∣ deep,learning,is).‬‬

‫‪Markov Models and 𝑛-grams‬‬ ‫‪n‬‬ ‫‪9.3.1.1‬‬


‫من بين تحليل نموذج التسلسليف القسم ‪ ،9.1‬دعنا نطبق نماذج ماركوف على نمذجة اللغة‪.‬‬
‫التوزيع على التسلسالت يلبي خاصية ماركوف من الدرجة األولى إذا = ) ‪𝑃(𝑥𝑡+1 ∣ 𝑥𝑡 , … , 𝑥1‬‬
‫) 𝑡𝑥 ∣ ‪ .𝑃(𝑥𝑡+1‬تتوافق الطلبات األعلى مع التبعيات األطول ‪ .longer dependencies‬يؤدي‬
‫هذا إلى عدد من التقديرات التقريبية التي يمكن أن نطبقها لنمذجة تسلسل‪:‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪194‬‬

‫) ‪𝑃(𝑥1 , 𝑥2 , 𝑥3 , 𝑥4‬‬ ‫‪= 𝑃(𝑥1 )𝑃(𝑥2 )𝑃(𝑥3 )𝑃(𝑥4 ),‬‬


‫) ‪𝑃(𝑥1 , 𝑥2 , 𝑥3 , 𝑥4‬‬ ‫‪= 𝑃(𝑥1 )𝑃(𝑥2 ∣ 𝑥1 )𝑃(𝑥3 ∣ 𝑥2 )𝑃(𝑥4 ∣ 𝑥3 ),‬‬
‫‪𝑃(𝑥1 , 𝑥2 , 𝑥3 , 𝑥4 ) = 𝑃(𝑥1 )𝑃(𝑥2 ∣ 𝑥1 )𝑃(𝑥3 ∣ 𝑥1 , 𝑥2 )𝑃(𝑥4 ∣ 𝑥2 , 𝑥3 ).‬‬

‫يُشار عادةً إلى صيغ االحتمال التي تتضمن متغير واحد‪ ،‬ومتغيرين‪ ،‬وثالثة متغيرات على أنها‬
‫نماذج ‪ ،unigram‬و‪ ،bigram‬و‪ ،trigram‬على التوالي‪ .‬من أجل حساب نموذج اللغة‪ ،‬نحتاج‬
‫إلى حساب احتمال الكلمات واالحتمال الشرطي للكلمة بالنظر إلى الكلمات القليلة السابقة‪.‬‬
‫الحظ أن هذه االحتماالت هي معلمات نموذج اللغة ‪.language model parameters‬‬

‫‪Word Frequency‬‬ ‫‪9.3.1.2‬‬


‫هنا‪ ،‬نفترض أن مجموعة بيانات التدريب عبارة عن مجموعة نصية كبيرة‪ ،‬مثل جميع إدخاالت‬
‫‪ Wikipedia‬و ‪ Project Gutenberg‬وجميع النصوص المنشورة على الويب‪ .‬يمكن حساب‬
‫احتمال الكلمات من تكرار الكلمات النسبي ‪ relative word frequency‬لكلمة معينةيف ‬
‫^‬
‫مجموعة بيانات التدريب‪ .‬على سبيل المثال‪ ،‬التقدير )‪𝑃(deep‬يمكن حسابه على أنه احتمال أي‬
‫جملة تبدأ بكلمة "‪ ."deep‬قد يكون النهج األقل دقة هو حساب جميع تكرارات كلمة "‪"deep‬‬
‫وتقسيمها على العدد اإلجمالي للكلماتيف المجموعة‪ .‬هذا يعمل بشكل جيد إلى حد ما‪ ،‬خاصة‬
‫مع الكلمات المتكررة‪ .‬للمضي قدمًا‪ ،‬يمكننا محاولة التقدير‪:‬‬

‫^‬ ‫)‪𝑛(deep, learning‬‬


‫= )‪𝑃(learning ∣ deep‬‬ ‫‪,‬‬
‫)‪𝑛(deep‬‬

‫حيث )𝑥(𝑛 و) ‪ 𝑛(𝑥, 𝑥 ′‬عدد تكرارات المفردات وأزواج الكلمات المتتالية‪ ،‬على التوالي‪ .‬لسوء‬
‫الحظ‪ ،‬يعد تقدير احتمال وجود زوج من الكلمات أكثر صعوبة إلى حد ما ‪ ،‬نظرًا ألن حدوث‬
‫"‪ " deep learning‬أقل تكرارًا‪ .‬على وجه الخصوص ‪ ،‬بالنسبة لبعض تركيبات الكلمات غير‬
‫المعتادة ‪ ،‬قد يكون من الصعب العثور على تكرارات كافية للحصول على تقديرات دقيقة‪ .‬كما‬
‫هو مقترح من النتائج التجريبية في القسم ‪ ، 9.2.5‬تأخذ األمور منعطفًا نحو األسوأ بالنسبة‬
‫لتركيبات مكونة من ثالث كلمات وما بعدها‪ .‬سيكون هناك العديد من التركيبات المعقولة المكونة‬
‫من ثالث كلمات والتي من المحتمل أال نراها في مجموعة البيانات الخاصة بنا‪ .‬ما لم نقدم بعض‬
‫الحلول لتعيين مثل هذه المجموعات من الكلمات عددًا غير صفري ‪ ،‬فلن نتمكن من استخدامها‬
‫في نموذج اللغة‪ .‬إذا كانت مجموعة البيانات صغيرة أو كانت الكلمات نادرة جدًا ‪ ،‬فقد ال نعثر‬
‫حتى على واحدة منها‪.‬‬

‫‪Laplace Smoothing‬‬ ‫‪9.3.1.3‬‬


‫تتمثل اإلستراتيجية الشائعة في إجراء بعض أشكال تجانس البالس ‪.Laplace Smoothing‬‬
‫إلى‬ ‫باإلشارة‬ ‫قم‬ ‫األعداد‪.‬‬ ‫لجميع‬ ‫صغير‬ ‫ثابت‬ ‫إضافة‬ ‫هو‬ ‫الحل‬
‫‪195‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫𝑛 ك عدد إجمالي للكلمات في مجموعة التدريب وعدد الكلمات الفريدة‪ .‬يساعد هذا الحل مع‬
‫الفردي ‪ ،‬على سبيل المثال ‪ ،‬عبر‬

‫^‬ ‫𝑚‪𝑛(𝑥) + 𝜖1 /‬‬


‫)𝑥(𝑃‬ ‫=‬ ‫‪,‬‬
‫‪𝑛 + 𝜖1‬‬
‫^‬
‫^‬ ‫) ‪𝑛(𝑥, 𝑥 ′ ) + 𝜖2 𝑃(𝑥 ′‬‬
‫)𝑥 ∣ ‪𝑃(𝑥 ′‬‬ ‫=‬ ‫‪,‬‬
‫‪𝑛(𝑥) + 𝜖2‬‬
‫^‬
‫^‬
‫‪″‬‬
‫) ‪𝑛(𝑥, 𝑥 ′ , 𝑥 ″ ) + 𝜖3 𝑃(𝑥 ″‬‬
‫‪′‬‬
‫= ) 𝑥 ‪𝑃(𝑥 ∣ 𝑥,‬‬ ‫‪.‬‬
‫‪𝑛(𝑥, 𝑥 ′ ) + 𝜖3‬‬

‫هنا ‪ ،𝜖1 , 𝜖2‬و ‪ 𝜖3‬المعلمات الفائقة‪ .‬خذ ‪ 𝜖1‬كمثال‪ :‬عندما ‪ 𝜖1 = 0‬ال يتم تطبيق أي تجانس ‪no‬‬
‫^‬
‫‪smoothing‬؛ عندما ‪ 𝜖1‬تقترب من الالنهاية الموجبة‪ 𝑃(𝑥) ،‬يقترب من االحتمال الموحد‬
‫𝑚‪ . 1/‬ما ورد أعاله هو البديل البدائي إلى حد ما لما يمكن أن تحققه التقنيات األخرى ( ‪Wood‬‬
‫‪.)2011 ،et al.‬‬

‫لسوء الحظ‪ ،‬تصبح مثل هذه النماذج غير عملية إلى حد ما بسرعة لألسباب التالية‪ .‬أوالً‪ ،‬كما‬
‫تمت مناقشتهيف القسم ‪ ،9.2.5‬نادرًا ما تحدث العديد من القواعد اللغوية‪ ،‬مما يجعل تجانس‬
‫البالس غير مناسب إلى حد ما لنمذجة اللغة‪ .‬ثانيًا‪ ،‬نحتاج إلى تخزين كل التواتر ‪ .counts‬ثالثًا‪،‬‬
‫هذا يتجاهل تمامًا معنى الكلمات‪ .‬على سبيل المثال‪ ،‬يجب أن تحدث "القط ‪ "cat‬و" القطط‬
‫‪" feline‬يف السياقات ذات الصلة‪ .‬من الصعب للغاية تعديل مثل هذه النماذج لسياقات إضافية‪،‬‬
‫في حين أن نماذج اللغة القائمة على التعلم العميق مناسبة تمامًا ألخذ ذلكيف االعتبار‪ .‬يكاد يكون‬
‫من المؤكد أن تكون تسلسالت الكلمات الطويلة األخيرة جديدة‪ ،‬ومن ثم فإن النموذج الذي‬
‫يحسب ببساطة تواتر تسلسالت الكلمات التي شوهدت سابقًا ال بد أن يؤدي أداءً ضعيفًا هناك‪.‬‬
‫لذلك‪ ،‬فإننا نركز على استخدام الشبكات العصبية لنمذجة اللغةيف بقية الفصل‪.‬‬

‫‪Perplexity‬‬ ‫‪9.3.2‬‬
‫بعد ذلك‪ ،‬دعنا نناقش كيفية قياس جودة نموذج اللغة‪ ،‬والتي سيتم استخدامها لتقييم نماذجنايف ‬
‫األقسام التالية‪ .‬إحدى الطرق هي التحقق من مدى دهشة النص ‪ .surprising the text‬نموذج‬
‫اللغة الجيد قادر على التنبؤ برموز عالية الدقة بما سنراه بعد ذلك‪ .‬تأمل االستمرارية التالية لعبارة‬
‫"إنها تمطر ‪ ،”It is raining‬على النحو الذي اقترحته نماذج لغوية مختلفة‪:‬‬

‫‪1.‬‬ ‫"‪"It is raining outside‬‬


‫"‪2. " It is raining banana tree‬‬
‫"‪3. "It is raining piouw;kcj pwepoiut‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪196‬‬

‫من حيث الجودة‪ ،‬من الواضح أن المثال ‪ 1‬هو األفضل‪ .‬الكلمات منطقية ومتماسكة منطقيًا‪.‬يف ‬
‫حين أنه قد ال يعكس بدقة الكلمة التي تليها معنوية (كان من الممكن أن تكون " ‪in San‬‬
‫‪ "Francisco‬و "‪ "in winter‬امتدادات معقولة تمامًا)‪ ،‬إال أن النموذج قادر على التقاط أي نوع‬
‫من الكلمات التالية‪ .‬المثال ‪ 2‬أسوأ بكثير من خالل إنتاج امتداد غير منطقي‪ .‬ومع ذلك‪ ،‬فقد تعلم‬
‫النموذج على األقل كيفية تهجئة الكلمات ودرجة معينة من االرتباط بين الكلمات‪ .‬أخيرًا‪ ،‬يشير‬
‫المثال ‪ 3‬إلى نموذج سيئ التدريب ال يناسب البيانات بشكل صحيح‪.‬‬

‫قد نقيس جودة النموذج عن طريق حساب احتمالية التسلسل ‪.likelihood of the sequence‬‬
‫لسوء الحظ‪ ،‬هذا رقم يصعب فهمه ويصعب مقارنته‪ .‬بعد كل شيء‪ ،‬من المرجح أن تحدث‬
‫التسلسالت األقصر بكثير من التسلسالت األطول‪ ،‬وبالتالي فإن تقييم النموذج على ماغنوم أوبس‬
‫تولستوي الحرب والسالم سينتج حتمًا احتمالية أقل بكثير من‪ ،‬على سبيل المثال‪،‬يف رواية األمير‬
‫الصغير لسانت إكزوبيري‪ .‬ما ينقص هو ما يعادل المتوسط‪.‬‬

‫نظرية المعلومات ‪ Information theory‬تأتييف متناول اليد هنا‪ .‬لقد حددنا االنتروبيا‬
‫‪ ،entropy‬والمفاجأة ‪ ،surprisal‬واالنتروبيا المتقاطعة ‪ cross-entropy‬عندما قدمنا انحدار‬
‫‪( softmax‬القسم ‪ .)4.1.3‬إذا أردنا ضغط النص‪ ،‬فيمكننا أن نسأل عن توقع الرمز ‪ token‬التالي‬
‫في ضوء المجموعة الحالية من الرموز‪ .‬يجب أن يسمح لنا نموذج اللغة األفضل بالتنبؤ بالرمز‬
‫التالي بشكل أكثر دقة‪ .‬وبالتالي‪ ،‬يجب أن يسمح لنا بإنفاق عدد أقل من البتاتيف ضغط التسلسل‪.‬‬
‫لذلك يمكننا قياسه من خالل متوسط خسارة االنتروبيا على جميع الرموز للتسلسل‪:‬‬
‫𝑛 ‪1‬‬
‫∑‬
‫‪𝑛 𝑡=1‬‬
‫‪− log 𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1 ),‬‬ ‫)‪(9.3.7‬‬

‫حيث 𝑃 يتم تقديمه بواسطة نموذج اللغة وهو الرمز الفعلي الذي يتم مالحظتهيف الخطوة الزمنية‬
‫𝑡 من التسلسل‪ .‬هذا يجعل األداءيف المستندات ذات األطوال المختلفة قابالً للمقارنة‪ .‬ألسباب‬
‫تاريخية‪ ،‬يفضل العلماءيف معالجة اللغة الطبيعية استخدام كمية تسمى االرتباك ‪.perplexity‬‬
‫باختصار‪ ،‬هو اُس لـ (‪:)9.3.7‬‬
‫𝑛‬
‫‪1‬‬
‫∑ ‪exp (−‬‬ ‫‪log 𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1 )).‬‬
‫𝑛‬
‫‪𝑡=1‬‬

‫يمكن فهم االرتباك ‪ Perplexity‬بشكل أفضل على أنها المتوسط الهندسي لعدد الخيارات‬
‫الحقيقية التي لدينا عند تحديد الرمز ‪ token‬الذي نختاره بعد ذلك‪ .‬دعونا نلقي نظرة على عدد‬
‫من الحاالت‪:‬‬
‫‪197‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫في أفضل سيناريو‪ ،‬يقوم النموذج دائمًا بتقدير احتمالية الرمز المستهدف تمامًا مثل ‪.1‬‬ ‫•‬
‫في هذه الحالة‪ ،‬يكون ارتباك النموذج هو ‪.1‬‬
‫في أسوأ السيناريوهات‪ ،‬يتنبأ النموذج دائمًا باحتمالية الرمز على أنه ‪.0‬يف هذه الحالة‪،‬‬ ‫•‬
‫يكون االرتباك هو الالنهاية الموجبة ‪.positive infinity‬‬
‫في األساس‪ ،‬يتنبأ النموذج بتوزيع موحد على جميع الرموز المتاحة للمفردات‪.‬يف هذه‬ ‫•‬
‫الحالة‪ ،‬االرتباك تساوي عدد الرموز الفريدة ‪ unique tokens‬للمفردات‪.‬يف الواقع‪،‬‬
‫إذا قمنا بتخزين التسلسل دون أي ضغط‪ ،‬فسيكون هذا أفضل ما يمكننا فعله لتشفيره‪.‬‬
‫ومن ثم‪ ،‬فإن هذا يوفر حدًا أعلى غير بديهي يجب أن يتغلب عليه أي نموذج مفيد‪.‬‬
‫•‬ ‫‪import tensorflow as tf‬‬
‫•‬ ‫‪from d2l import tensorflow as d2l‬‬
‫‪Partitioning Sequences‬‬ ‫‪9.3.3‬‬
‫سنصمم نماذج لغوية باستخدام الشبكات العصبية ونستخدم االرتباك ‪ perplexity‬لتقييم مدى‬
‫جودة النموذجيف توقع الرمز التالي بالنظر إلى المجموعة الحالية من الرموزيف التسلسالت النصية‪.‬‬
‫قبل تقديم النموذج‪ ،‬لنفترض أنه يعالج دفعة صغيرة من التسلسالت بطول محدد مسبقًايف كل‬
‫مرة‪ .‬السؤال اآلن هو كيف تقرأ الدفعات الصغيرة من تسلسالت اإلدخال والتسلسالت المستهدفة‬
‫بشكل عشوائي‪.‬‬

‫افترض أن مجموعة البيانات ‪ dataset‬تتخذ شكل سلسلة من مؤشرات الرمز‬


‫𝑇 يف ‪ .corpus‬سنقوم بتقسيمها إلى تكرارات الحقة‪ ،‬حيث يكون لكل منها‬
‫𝑛 رموز (خطوات زمنية)‪ .‬لتكرار (تقريبًا) جميع الرموز لمجموعة البيانات بأكملها لكل فترة‬
‫‪ epoch‬والحصول على جميع األطوال𝑛 الممكنة‪ ،‬يمكننا تقديم العشوائية ‪.randomness‬‬
‫بشكل أكثر تحديدًا‪،‬يف بداية كل فترة‪ ،‬تجاهل الرموز األولى 𝑑‪ ،‬حيث )𝑛 ‪ 𝑑 ∈ [0,‬يتم أخذ عينات‬
‫بشكل موحد عشوائيًا‪ .‬ثم يتم تقسيم بقية التسلسل إلى تسلسالت الحقة ⌋𝑛‪.𝑚 = ⌊(𝑇 − 𝑑)/‬‬
‫قم باإلشارة إلى ] ‪ 𝐱𝑡 = [𝑥𝑡 , … , 𝑥𝑡+𝑛−1‬ك𝑛طول للتسلسالت التي تبدأ من الرمز 𝑡𝑥يف الخطوة‬
‫الزمنية 𝑡‪ .‬النتائج 𝑚 الالحقة المقسمة الناتجة هي ‪ 𝐱𝑑 , 𝐱𝑑+𝑛 , … , 𝐱𝑑+𝑛(𝑚−1) .‬كل نتيجة الحقة‬
‫سيتم استخدامها كتسلسل إدخاليف نموذج اللغة‪.‬‬

‫الشكل ‪ 9.3.1‬الحصول على ‪ 5‬أزواج من متواليات اإلدخال والتسلسالت المستهدفة من الطول‬


‫المقسم ‪ 5 -‬المتتاليات الالحقة‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪198‬‬

‫بالنسبة لنمذجة اللغة‪ ،‬يتمثل الهدفيف التنبؤ بالرمز التالي بناءً على الرموز التي رأيناها حتى اآلن‪،‬‬
‫ومن ثم فإن األهداف (التسميات) هي التسلسل األصلي‪ ،‬والتي تم إزاحتها بواسطة رمز واحد‪.‬‬
‫التسلسل المستهدف ألي تسلسل 𝑡𝐱 إدخال يكون ‪ 𝐱𝑡+1‬بطول𝑛‪.‬‬

‫يوضح الشكل ‪ 9.3.1‬مثاالً للحصول على ‪ 5‬أزواج من متواليات اإلدخال والتسلسالت المستهدفة‬
‫مع ‪ 𝑛 = 5‬و ‪.𝑑 = 2‬‬

‫‪@d2l.add_to_class(d2l.TimeMachine) #@save‬‬
‫‪def __init__(self, batch_size, num_steps,‬‬
‫‪num_train=10000, num_val=5000):‬‬
‫)(__‪super(d2l.TimeMachine, self).__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫))(‪corpus, self.vocab = self.build(self._download‬‬
‫]‪array = tf.constant([corpus[i:i+num_steps+1‬‬
‫‪for i in range(0, len(corpus)-‬‬
‫)])‪num_steps-1‬‬
‫]‪self.X, self.Y = array[:,:-1], array[:,1:‬‬
‫لتدريب نماذج اللغة‪ ،‬سنقوم بأخذ عينات عشوائية من أزواج من تسلسالت اإلدخال والتسلسالت‬
‫المستهدفةيف الدفعات الصغيرة‪ .‬يُنشئ مُحمل البيانات ‪ data loader‬التالي بشكل عشوائي دفعة‬
‫صغيرة من مجموعة البياناتيف كل مرة‪ .‬تحدد الوسيطة ‪ batch_size‬عدد األمثلة الالحقة‬
‫(‪)self.b‬يف كل الدفعة الصغيرة و ‪ num_steps‬هو الطول التالييف الرموز (‪.)self.n‬‬

‫‪@d2l.add_to_class(d2l.TimeMachine) #@save‬‬
‫‪def get_dataloader(self, train):‬‬
‫(‪idx = slice(0, self.num_train) if train else slice‬‬
‫)‪self.num_train, self.num_train + self.num_val‬‬
‫‪return self.get_tensorloader([self.X, self.Y],‬‬
‫)‪train, idx‬‬
‫كما نرىيف ما يلي ‪ ،‬يمكن الحصول على دفعة صغيرة من التسلسالت المستهدفة عن طريق‬
‫تحويل تسلسالت اإلدخال بواسطة رمز واحد‪.‬‬

‫)‪data = d2l.TimeMachine(batch_size=2, num_steps=10‬‬


‫‪for X, Y in data.train_dataloader():‬‬
‫)‪print('X:', X, '\nY:', Y‬‬
‫‪break‬‬
‫(‪X: tf.Tensor‬‬
‫]‪[[26 0 2 5 14 10 19 6 5 0‬‬
‫‪[14 0 21 9 6 0 4 19 2 5]], shape=(2, 10),‬‬
‫)‪dtype=int32‬‬
‫(‪Y: tf.Tensor‬‬
‫‪199‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫‪[[ 0 2 5 14 10 19 6‬‬ ‫‪5‬‬ ‫]‪0 9‬‬


‫‪[ 0 21 9 6 0 4 19‬‬ ‫‪2‬‬ ‫‪5 13]], shape=(2, 10),‬‬
‫)‪dtype=int32‬‬
‫‪9.3.4‬‬
‫نماذج اللغة تقدر االحتمال المشترك لتسلسل نصي‪ .‬بالنسبة للتسلسالت الطويلة‪ ،‬توفر ‪n-gram‬‬
‫نموذجًا مناسبًا عن طريق اقتطاع التبعية‪ .‬ومع ذلك‪ ،‬هناك الكثير من المعمارية ولكن ليس هناك‬
‫تردد كافٍ للتعامل مع مجموعات الكلمات النادرة بكفاءة عبر تجانس البالس‪ .‬وبالتالي‪ ،‬سوف‬
‫نركز على نمذجة اللغة العصبيةيف األقسام الالحقة‪ .‬لتدريب نماذج اللغة‪ ،‬يمكننا عشوائيًا أخذ‬
‫عينات من أزواج من تسلسالت اإلدخال والتسلسالت المستهدفةيف الدفعات الصغيرة‪ .‬بعد‬
‫التدريب‪ ،‬سوف نستخدم االرتباك ‪ perplexity‬لقياس جودة النموذج اللغوي‪.‬‬

‫‪9.3.5‬‬
‫‪ .1‬افترض أن هناك ‪ 100,000‬كلمات في مجموعة بيانات التدريب‪ .‬ما مقدار تكرار‬
‫الكلمات والتكرار المجاور متعدد الكلمات التي يحتاجها أربعة غرام للتخزين؟‬
‫‪ .2‬كيف يمكنك أن تكون نموذجا للحوار ‪dialogue‬؟‬
‫‪ .3‬ما الطرق األخرى التي يمكنك التفكير بها لقراءة بيانات التسلسل الطويل ‪long‬‬
‫‪sequence data‬؟‬
‫‪ .4‬ضع في اعتبارك طريقتنا للتخلص من عدد عشوائي منتظم من الرموز ‪ tokens‬القليلة‬
‫األولى في بداية كل فترة‪.‬‬
‫‪ .1‬هل يؤدي حقًا إلى توزيع منتظم ‪ uniform distribution‬تمامًا على‬
‫التسلسالت الموجودة في المستند؟‬
‫‪ .2‬ما الذي يجب عليك فعله لجعل األشياء أكثر انتظاماً ‪uniform‬؟‬
‫‪ .5‬إذا أردنا أن يكون المثال المتسلسل جملة كاملة‪ ،‬فما نوع المشكلة التي يقدمها هذا في‬
‫أخذ الدفعات الصغيرة؟ كيف يمكننا حل المشكلة؟‬

‫‪Recurrent Neural Networks‬‬ ‫‪9.4‬‬


‫وصفنايف القسم ‪ 9.3‬نماذج ماركوف و 𝑛‪-‬غرام لنمذجة اللغة‪ ،‬حيث يعتمد االحتمال الشرطي‬
‫للرمز 𝑡𝑥يف الخطوة الزمنية 𝑡 فقط على الرموز السابقة ‪ .𝑛 − 1‬إذا أردنا دمج التأثير المحتمل‬
‫للرموزيف وقت أبكر من الوقت )‪ ،𝑡 − (𝑛 − 1‬فنحن بحاجة إلى زيادة 𝑛‪ .‬ومع ذلك‪ ،‬فإن عدد‬
‫معلمات النموذج سيزداد أيضًا بشكل كبير معه‪ ،‬حيث نحتاج إلى تخزين 𝑛|𝒱| أرقام لمجموعة‬
‫مفردات 𝒱‪ .‬وبالتالي‪ ،‬بدالً من نمذجة ) ‪ ،𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥𝑡−𝑛+1‬من األفضل استخدام‬
‫نموذج متغير كامن ‪:latent variable model‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪200‬‬

‫‪𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1 ) ≈ 𝑃(𝑥𝑡 ∣ ℎ𝑡−1 ),‬‬ ‫(‪)9.4.1‬‬

‫حيث ‪ ℎ𝑡−1‬هي حالة مخفية ‪ hidden state‬تخزن معلومات التسلسل حتى خطوة زمنية ‪.𝑡 − 1‬‬
‫بشكل عام‪ ،‬يمكن حساب الحالة المخفيةيف أي خطوة زمنية 𝑡 بناءً على كل من اإلدخال الحالي‬
‫𝑡𝑥 والحالة المخفية السابقة ‪:ℎ𝑡−1‬‬

‫‪ℎ𝑡 = 𝑓(𝑥𝑡 , ℎ𝑡−1 ).‬‬ ‫(‪)9.4.2‬‬

‫بالنسبة لدالة قوية بدرجة كافيةيف (‪ ،)9.4.2‬فإن نموذج المتغير الكامن ليس تقريبيًا‪ .‬بعد كل هذا‪،‬‬
‫يمكن 𝑡‪ ℎ‬ببساطة تخزين جميع البيانات التي الحظتها حتى اآلن‪ .‬ومع ذلك‪ ،‬فمن المحتمل أن‬
‫يجعل كالً من الحساب والتخزين باهظ التكلفة‪.‬‬

‫تذكر أننا ناقشنا الطبقات المخفية مع الوحدات المخفيةيف القسم ‪ .5‬ومن الجدير بالذكر أن‬
‫الطبقات المخفية والحاالت المخفية تشير إلى مفهومين مختلفين تمامًا‪ .‬الطبقات المخفية‪ ،‬كما‬
‫هو موضح‪ ،‬هي طبقات مخفية عن العرض على المسار من اإلدخال إلى اإلخراج‪ .‬الحاالت‬
‫المخفية هي مدخالت تحدث تقنيًا لكل ما نقوم بهيف خطوة معينة‪ ،‬وال يمكن حسابها إال من‬
‫خالل النظر إلى البياناتيف خطوات زمنية سابقة‪.‬‬

‫الشبكات العصبية المتكررة )‪ (RNNs‬هي شبكات عصبية ذات حاالت مخفية‪ .‬قبل تقديم‬
‫نموذج‪ ، RNN‬نعيد أوالً زيارة نموذج ‪ MLP‬المقدميف القسم ‪.5.1‬‬

‫‪Neural Networks‬‬ ‫‪9.4.1‬‬


‫‪without Hidden States‬‬
‫دعونا نلقي نظرة على ‪ MLP‬بطبقة واحدة مخفية‪ .‬دع دالة تنشيط الطبقة المخفية تكون 𝜙‪.‬‬
‫بالنظر إلى دفعة صغيرة من األمثلة 𝑑×𝑛‪ 𝐗 ∈ ℝ‬مع حجم الدُفعة 𝑛 والمدخالت 𝑑‪ ،‬يتم حساب‬
‫ناتج الطبقة المخفية كـ‬

‫‪𝐇 = 𝜙(𝐗𝐖𝑥ℎ + 𝐛ℎ ).‬‬ ‫(‪)9.4.3‬‬

‫في (‪ )9.4.3‬لدينا معامل الوزن ‪ 𝐖𝑥ℎ ∈ ℝ𝑑×ℎ‬ومعامل التحيز ‪ 𝐛ℎ ∈ ℝ1×ℎ‬وعدد الوحدات‬


‫المخفية ‪ ℎ‬للطبقة المخفية‪ .‬وبالتالي‪ ،‬يتم تطبيق البث ‪( broadcasting‬انظر القسم ‪ )2.1.4‬أثناء‬
‫عملية الجمع ‪ .summation‬بعد ذلك‪ ،‬يتم استخدام إخراج الطبقة المخفية 𝐇 كمدخل لطبقة‬
‫اإلخراج‪ .‬يتم إعطاء طبقة اإلخراج بواسطة‬

‫‪𝐎 = 𝐇𝐖ℎ𝑞 + 𝐛𝑞 ,‬‬


‫‪201‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫حيث 𝑞×𝑛‪ 𝐎 ∈ ℝ‬هو متغير اإلخراج‪ 𝐖ℎ𝑞 ∈ ℝℎ×𝑞 ،‬هو معلمة الوزن‪ ،‬و 𝑞×‪ 𝐛𝑞 ∈ ℝ1‬هو‬
‫معلمة التحيز لطبقة اإلخراج‪ .‬إذا كانت مشكلة تصنيف‪ ،‬فيمكننا استخدام )𝐎(‪ softmax‬لحساب‬
‫التوزيع االحتمالي لفئات المخرجات‪.‬‬

‫هذا مشابه تمامًا لمشكلة االنحدار التي حللناها سابقًايف القسم ‪ ،9.1‬ومن ثم قمنا بحذف‬
‫التفاصيل‪ .‬يكفي أن نقول إنه يمكننا اختيار أزواج تسمية الميزات عشوائيًا وتعلم معلمات شبكتنا‬
‫عبر التمايز التلقائي ‪ automatic differentiation‬والتدرج االشتقاقي العشوائي ‪.SGD‬‬

‫‪Recurrent‬‬ ‫‪9.4.2‬‬
‫‪Neural Networks with Hidden States‬‬
‫تختلف األمور تمامًا عندما تكون لدينا حاالت مخفية‪ .‬دعونا نلقي نظرة على الهيكل ببعض‬
‫التفاصيل‪.‬‬

‫افترض أن لدينا دفعة صغيرة من المدخالت 𝑑×𝑛‪𝐗 𝑡 ∈ ℝ‬يف الخطوة الزمنية 𝑡‪ .‬بمعنى آخر‪،‬‬
‫بالنسبة لدفعة صغيرة من أمثلة التسلسل 𝑛 ‪ ،‬يتوافق كل صف مع مثال واحديف خطوة زمنية 𝑡 من‬
‫التسلسل‪ .‬بعد ذلك‪ ،‬قم باإلشارة إلى ‪ 𝐇𝑡 ∈ ℝ𝑛×ℎ‬كإخراج الطبقة المخفية للخطوة الزمنية 𝑡‪.‬‬
‫على عكس ‪ ،MLP‬نحفظ هنا إخراج الطبقة المخفية من الخطوة الزمنية السابقة ونقدم معلمة‬
‫وزن جديدة ‪ 𝐖ℎℎ ∈ ℝℎ×ℎ‬لوصف كيفية استخدام إخراج الطبقة المخفية لخطوة الوقت السابقة‬
‫في الخطوة الزمنية الحالية‪ .‬على وجه التحديد‪ ،‬يتم تحديد حساب ناتج الطبقة المخفية لخطوة‬
‫الوقت الحالية من خالل إدخال خطوة الوقت الحالي مع إخراج الطبقة المخفية لخطوة الوقت‬
‫السابقة‪:‬‬

‫)‪𝐇𝑡 = 𝜙(𝐗 𝑡 𝐖𝑥ℎ + 𝐇𝑡−1 𝐖ℎℎ + 𝐛ℎ ). (9.5.4‬‬

‫بالمقارنة مع (‪ ،)9.4.3‬يضيف (‪ )9.4.5‬مصطلحًا آخر ‪ ،𝐇𝑡−1 𝐖ℎℎ‬وبالتالي يُنشئ (‪.)9.4.2‬‬


‫من العالقة بين مخرجات الطبقة المخفية 𝑡𝐇 و ‪ 𝐇𝑡−1‬للخطوات الزمنية المجاورة‪ ،‬نعلم أن هذه‬
‫المتغيرات تلتقط وتحتفظ بالمعلومات التاريخية للتسلسل حتى الخطوة الزمنية الحالية‪ ،‬تمامًا‬
‫مثل حالة أو ذاكرة الخطوة الزمنية الحالية للشبكة العصبية‪ .‬لذلك‪ ،‬يُطلق على إخراج الطبقة‬
‫المخفية هذا الحالة المخفية ‪ .hidden state‬نظرًا ألن الحالة المخفية تستخدم نفس تعريف‬
‫الخطوة الزمنية السابقةيف الخطوة الزمنية الحالية‪ ،‬فإن حساب (‪ )9.4.5‬متكرر ‪ .recurrent‬ومن‬
‫ثم‪ ،‬كما قلنا‪ ،‬الشبكات العصبية ذات الحاالت المخفية القائمة على الحساب المتكرر‬
‫‪ recurrent computation‬تسمى الشبكات العصبية المتكررة ‪recurrent neural‬‬
‫‪ .networks‬تسمى الطبقات التي تقوم بحساب (‪)9.4.5‬يف ‪ RNNs‬الطبقات المتكررة‬
‫‪.recurrent layers‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪202‬‬

‫هناك العديد من الطرق المختلفة لبناء ‪ RNNs. RNNs‬ذات الحالة المخفية المحددة بواسطة‬
‫(‪ )9.4.5‬شائعة جدًا‪ .‬بالنسبة للخطوة الزمنية 𝑡‪ ،‬يكون إخراج طبقة اإلخراج مشابهًا للحسابيف ‬
‫‪:MLP‬‬

‫‪𝐎𝑡 = 𝐇𝑡 𝐖ℎ𝑞 + 𝐛𝑞 .‬‬

‫تتضمن معلمات ‪ RNN‬األوزان ‪ 𝐖𝑥ℎ ∈ ℝ𝑑×ℎ , 𝐖ℎℎ ∈ ℝℎ×ℎ‬وانحياز ‪𝐛ℎ ∈ ℝ1×ℎ‬‬


‫الطبقة المخفية‪ ،‬جنبًا إلى جنب مع األوزان 𝑞×‪ 𝐖ℎ𝑞 ∈ ℝℎ‬وانحياز 𝑞×‪ 𝐛𝑞 ∈ ℝ1‬طبقة اإلخراج‪.‬‬
‫من الجدير بالذكر أنه حتىيف الخطوات الزمنية المختلفة‪ ،‬تستخدم ‪ RNN‬دائمًا معلمات‬
‫النموذج هذه‪ .‬لذلك‪ ،‬ال تنمو تكلفة المعلمات لـ ‪ RNN‬مع زيادة عدد الخطوات الزمنية‪.‬‬

‫يوضح الشكل ‪ 9.4.1‬المنطق الحسابي ‪ computational logic‬لشبكة ‪RNN‬يف ثالث‬


‫خطوات زمنية متجاورة‪.‬يف أي خطوة زمنية 𝑡‪ ،‬يمكن التعامل مع حساب الحالة المخفية ‪𝐇𝑡−1‬‬
‫على النحو التالي‪ )1( :‬ربط اإلدخال 𝑡 𝐗يف الخطوة الزمنية الحالية 𝑡 والحالة المخفية ‪𝐇𝑡−1‬يف ‬
‫الخطوة الزمنية السابقة ‪𝑡 − 1‬؛ (‪ )2‬تغذية نتيجة التسلسليف طبقة متصلة بالكامل بدالة التنشيط‬
‫𝜙‪ .‬ناتج هذه الطبقة المتصلة بالكامل هو الحالة المخفية 𝑡𝐇 لخطوة الوقت الحالية 𝑡‪.‬يف هذه‬
‫الحالة‪ ،‬معلمات النموذج هي تسلسل ‪ 𝐖𝑥ℎ‬و ‪ ، 𝐖ℎℎ‬وانحياز ‪ ،𝐛ℎ‬الكل من (‪ .)9.4.5‬ستشارك‬
‫الحالة المخفية 𝑡𝐇 للخطوة الزمنية الحالية 𝑡يف حساب الحالة المخفية ‪ 𝐇𝑡+1‬للخطوة الزمنية‬
‫التالية ‪ .𝑡 + 1‬عالوة على ذلك‪ 𝐇𝑡 ،‬سيتم إدخالها أيضًايف طبقة اإلخراج المتصلة بالكامل لحساب‬
‫ناتج 𝑡𝐎 الخطوة الزمنية الحالية 𝑡‪.‬‬

‫لقد ذكرنا للتو أن حساب ‪ 𝐗 𝑡 𝐖𝑥ℎ + 𝐇𝑡−1 𝐖ℎℎ‬للحالة المخفية يعادل ضرب المصفوفة‬
‫لتسلسل 𝑡 𝐗 و ‪ 𝐇𝑡−1‬وتسلسل ‪ 𝐖𝑥ℎ‬و ‪ .𝐖ℎℎ‬على الرغم من أنه يمكن إثبات ذلكيف الرياضيات‪،‬‬
‫إال أننا فيما يلي نستخدم مقتطفًا بسيطًا من التعليمات البرمجية إلظهار ذلك‪ .‬بادئ ذي بدء‪ ،‬نحدد‬
‫المصفوفات ‪ X‬و ‪ W_xh‬و ‪ H‬و ‪ ، W_hh‬والتي تكون أشكالها )‪(4, ، (3, 4) ، (1, 4) ،(3, 1‬‬
‫)‪ 4‬على التوالي‪ .‬بضرب ‪ X‬يف ‪ ، W_xh‬و ‪ H‬يف ‪ ، W_hh‬على التوالي ‪ ،‬ثم إضافة هذين المضاعفين‪،‬‬
‫نحصل على مصفوفة الشكل )‪.(3, 4‬‬
203 ‫ الشبكات العصبية المتكررة‬:‫الفصل التاسع‬

.‫ مع حالة مخفية‬RNN 9.4.1 ‫شكل‬

import tensorflow as tf
from d2l import tensorflow as d2l

X, W_xh = tf.random.normal((3, 1)), tf.random.normal((1,


4))
H, W_hh = tf.random.normal((3, 4)), tf.random.normal((4,
4))
tf.matmul(X, W_xh) + tf.matmul(H, W_hh)
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[-2.7432978 , -2.2042181 , -4.0852065 , 2.702191
],
[ 3.1250827 , 0.27091736, 1.192738 ,
0.39742705],
[ 3.429378 , 1.6246774 , 2.52065 , -
0.16307715]],
dtype=float32)>
‫ و‬W_xh ‫ والمصفوفات‬،)1 ‫ على طول األعمدة (المحور‬H ‫ و‬X ‫اآلن نقوم بتجميع المصفوفات‬
(3, 5) ‫ ينتج عن هاتين السلسلتين مصفوفات الشكل‬.) 0 ‫ على طول الصفوف (المحور‬W_hh
‫ نحصل على نفس‬،‫ بضرب هاتين المصفوفتين المتسلسلتين‬.‫ على التوالي‬،(5, 4) ‫والشكل‬
.‫( على النحو الوارد أعاله‬3, 4) ‫مصفوفة اإلخراج للشكل‬

tf.matmul(tf.concat((X, H), 1), tf.concat((W_xh, W_hh),


0))
<tf.Tensor: shape=(3, 4), dtype=float32, numpy=
array([[-2.7432978 , -2.2042184 , -4.0852065 ,
2.7021914 ],
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪204‬‬

‫‪[ 3.1250825 , 0.27091733,‬‬ ‫‪1.192738‬‬ ‫‪,‬‬


‫‪0.39742705],‬‬
‫‪[ 3.429378 , 1.6246774 ,‬‬ ‫‪2.52065‬‬ ‫‪, -‬‬
‫‪0.16307715]],‬‬
‫>)‪dtype=float32‬‬
‫‪RNN-based RNN‬‬ ‫‪9.4.3‬‬
‫‪Character-Level Language Models‬‬
‫تذكر أنه بالنسبة لنمذجة اللغةيف القسم ‪ ،9.3‬فإننا نهدف إلى التنبؤ بالرمز التالي بناءً على الرموز‬
‫الحالية والسابقة‪ ،‬وبالتالي نقوم بتحويل التسلسل األصلي برمز واحد كأهداف (تسميات)‪ .‬بنجيو‬
‫وآخرون‪ .‬اقترح أوالً استخدام شبكة عصبية لنمذجة اللغة (‪ .)2003 ،Bengio et al.‬فيما يلي‬
‫نوضح كيف يمكن استخدام ‪ RNNs‬لبناء نموذج لغوي‪ .‬دع حجم الدفعات الصغيرة يكون‬
‫واحدًا‪ ،‬وتسلسل النص يكون "‪ ."machine‬لتبسيط التدريبيف األقسام الالحقة‪ ،‬نقوم بترميز‬
‫‪ tokenize‬النص إلى أحرف بدالً من الكلمات والنظريف نموذج لغة على مستوى الحرف‪ .‬يوضح‬
‫الشكل ‪ 9.4.2‬كيفية التنبؤ بالحرف التالي بناءً على األحرف الحالية والسابقة عبر ‪ RNN‬لنمذجة‬
‫اللغة على مستوى الحرف ‪.RNN for character-level language modeling‬‬

‫الشكل ‪ 9.4.2‬نموذج لغة على مستوى الحرف يعتمد على ‪ .RNN‬تسلسل المدخالت‬
‫والهدف هما "‪ "machin‬و "‪ ،"achine‬على التوالي‪.‬‬

‫أثناء عملية التدريب‪ ،‬نقوم بتشغيل عملية ‪ softmax‬على اإلخراج من طبقة اإلخراج لكل خطوة‬
‫زمنية‪ ،‬ثم نستخدم خطأ االنتروبيا المتقاطعة لحساب الخطأ بين إخراج النموذج والهدف‪ .‬بسبب‬
‫الحساب المتكرر للحالة المخفيةيف الطبقة المخفية‪ ،‬يتم تحديد ناتج الخطوة الزمنية ‪3‬يف الشكل‬
‫‪ ،9.4.2‬من خالل تسلسل النص "‪ "m‬و "‪ "a‬و "‪ ."c‬نظرًا ألن الحرف التالي للتسلسليف بيانات‬
‫التدريب هو "‪ ،”h‬فإن خطأ الوقت الخطوة ‪ 3‬ستعتمد على توزيع االحتمالية للحرف التالي الذي‬
‫تم إنشاؤه بناءً على تسلسل الميزات "‪ "m‬و "‪ "a‬و "‪ "c‬والهدف "‪ "h‬لهذه الخطوة الزمنية‪.‬‬
‫‪205‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫في الممارسة العملية‪ ،‬يتم تمثيل كل رمز من خالل متجه ذو األبعاد 𝑑‪ ،‬ونستخدم حجم الدُفعة‬
‫‪ .𝑛 > 1‬لذلك‪ ،‬ستكون المدخالت 𝑡 𝐗يف الخطوة الزمنية 𝑡 عبارة عن مصفوفة 𝑑 × 𝑛 مطابقة‬
‫لما ناقشناهيف القسم ‪.9.4.2‬‬

‫في األقسام التالية‪ ،‬سنقوم بتنفيذ ‪ RNNs‬لنماذج اللغة على مستوى األحرف‪.‬‬

‫‪9.4.4‬‬
‫تسمى الشبكة العصبية التي تستخدم الحساب المتكرر ‪ recurrent computation‬للحاالت‬
‫المخفية ‪ hidden states‬الشبكة العصبية المتكررة (‪ .)RNN‬يمكن للحالة المخفية لـ ‪RNN‬‬
‫التقاط المعلومات التاريخية للتسلسل حتى الخطوة الزمنية الحالية‪ .‬مع الحساب المتكرر‪ ،‬ال يزداد‬
‫عدد معلمات نموذج ‪ RNN‬مع زيادة عدد الخطوات الزمنية‪ .‬بالنسبة للتطبيقات‪ ،‬يمكن‬
‫استخدام ‪ RNN‬إلنشاء نماذج لغة على مستوى األحرف ‪character-level language‬‬
‫‪.models‬‬

‫‪9.4.5‬‬
‫‪ .1‬إذا استخدمنا ‪ RNN‬للتنبؤ بالحرف التالييف تسلسل نصي‪ ،‬فما هو ال ُبعد المطلوب‬
‫ألي إخراج؟‬
‫‪ .2‬لماذا يمكن لـ ‪ RNN‬التعبير عن االحتمال الشرطي لرمزيف خطوة زمنية معينة بناءً على‬
‫جميع الرموز السابقةيف تسلسل النص؟‬
‫‪ .3‬ماذا يحدث للتدرج ‪ gradient‬إذا قمت بالنشر الخلفي من خالل تسلسل طويل ‪long‬‬
‫‪sequence‬؟‬
‫‪ .4‬ما هي بعض المشاكل المرتبطة بنموذج اللغة الموصوفيف هذا القسم؟‬

‫‪Recurrent Neural‬‬ ‫‪9.5‬‬


‫‪Network Implementation from Scratch‬‬
‫نحن اآلن جاهزون لتنفيذ ‪ RNN‬من البداية‪ .‬على وجه الخصوص‪ ،‬سنقوم بتدريب ‪ RNN‬هذا‬
‫للعمل كنموذج لغة على مستوى األحرف (انظر القسم ‪ )9.4‬وتدريبه على مجموعة تتكون من‬
‫النص الكامل لـ ""‪ "'The Time Machine‬لـ ‪ ،H.G Wells‬باتباع خطوات معالجة البيانات‬
‫الموضحةيف القسم ‪ .9.2‬نبدأ بتحميل مجموعة البيانات‪.‬‬

‫‪%matplotlib inline‬‬
‫‪import math‬‬
‫‪import tensorflow as tf‬‬
‫‪from d2l import tensorflow as d2l‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 206

RNN 9.5.1
‫ الحظ أن عدد الوحدات المخفية‬.)9.4.2 ‫ (القسم‬RNN ‫نبدأ بتحديد فئة لتنفيذ نموذج‬
.tunable hyperparameter ‫ عبارة عن معلمة فائقة قابلة للضبط‬num_hiddens

class RNNScratch(d2l.Module): #@save


def __init__(self, num_inputs, num_hiddens,
sigma=0.01):
super().__init__()
self.save_hyperparameters()
self.W_xh = tf.Variable(tf.random.normal(
(num_inputs, num_hiddens)) * sigma)
self.W_hh = tf.Variable(tf.random.normal(
(num_hiddens, num_hiddens)) * sigma)
self.b_h = tf.Variable(tf.zeros(num_hiddens))
،‫ أدناه كيفية حساب المخرجات والحالة المخفيةيف أي خطوة زمنية‬forward ‫تحدد طريقة‬
RNN ‫ الحظ أن نموذج‬.‫بالنظر إلى اإلدخال الحالي وحالة النموذجيف الخطوة الزمنية السابقة‬
.‫ محدثًا الحالة المخفية خطوة واحدةيف كل مرة‬،inputs ‫يمر عبر ال ُبعد الخارجي للمدخالت‬
.)5.1.2.3 ‫ (القسم‬tanh ‫النموذج هنا يستخدم دالة التنشيط‬

@d2l.add_to_class(RNNScratch) #@save
def forward(self, inputs, state=None):
if state is not None:
state, = state
state = tf.reshape(state, (-1,
self.W_hh.shape[0]))
outputs = []
for X in inputs: # Shape of inputs: (num_steps,
batch_size, num_inputs)
state = tf.tanh(tf.matmul(X, self.W_xh) + (
tf.matmul(state, self.W_hh) if state is not
None else 0)
+ self.b_h)
outputs.append(state)
return outputs, state
‫ على النحو‬RNN ‫ من تسلسل اإلدخاليف نموذج‬minibatch ‫يمكننا تغذية الدفعة الصغيرة‬
.‫التالي‬

batch_size, num_inputs, num_hiddens, num_steps = 2, 16,


32, 100
rnn = RNNScratch(num_inputs, num_hiddens)
207 ‫ الشبكات العصبية المتكررة‬:‫الفصل التاسع‬

X = tf.ones((num_steps, batch_size, num_inputs))


outputs, state = rnn(X)
‫ ينتج نتائج األشكال الصحيحة للتأكد من بقاء أبعاد‬RNN ‫دعنا نتحقق مما إذا كان نموذج‬
.‫الحالة المخفية دون تغيير‬

def check_len(a, n): #@save


assert len(a) == n, f'list\'s len {len(a)} !=
expected length {n}'

def check_shape(a, shape): #@save


assert a.shape == shape, \
f'tensor\'s shape {a.shape} != expected
shape {shape}'

d2l.check_len(outputs, num_steps)
d2l.check_shape(outputs[0], (batch_size, num_hiddens))
d2l.check_shape(state, (batch_size, num_hiddens))
RNN-based Language Model RNN 9.5.2
‫ عبر‬RNN ‫ حيث نمرريف‬، RNN ‫ التالية نموذج لغة قائم على‬RNNLMScratch ‫تحدد فئة‬
‫ تكون المدخالت‬،‫ عند تدريب النماذج اللغوية‬.__init__ ‫ للطريقة‬rnn ‫الوسيطة‬
‫ والذي يساوي حجم‬،‫ فإنهما لهما نفس البعد‬،‫ ومن ثم‬.‫والمخرجات من نفس المفردات‬
‫ كما‬.‫ لتقييم النموذج‬perplexity ‫ الحظ أننا نستخدم االرتباك‬.vocabulary size ‫المفردات‬
.‫ يضمن هذا إمكانية مقارنة التسلسالت ذات األطوال المختلفة‬،9.3.2 ‫تمت مناقشتهيف القسم‬

class RNNLMScratch(d2l.Classifier): #@save


def __init__(self, rnn, vocab_size, lr=0.01):
super().__init__()
self.save_hyperparameters()
self.init_params()

def init_params(self):
self.W_hq = tf.Variable(tf.random.normal(
(self.rnn.num_hiddens, self.vocab_size)) *
self.rnn.sigma)
self.b_q =
tf.Variable(tf.zeros(self.vocab_size))

def training_step(self, batch):


l = self.loss(self(*batch[:-1]), batch[-1])
self.plot('ppl', tf.exp(l), train=True)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪208‬‬

‫‪return l‬‬

‫‪def validation_step(self, batch):‬‬


‫)]‪l = self.loss(self(*batch[:-1]), batch[-1‬‬
‫)‪self.plot('ppl', tf.exp(l), train=False‬‬
‫‪One-Hot Encoding‬‬ ‫‪9.5.2.1‬‬
‫تذكر أن كل رمز يتم تمثيله بمؤشر رقمي يشير إلى الموضعيف مفردات الكلمة ‪ /‬الحرف ‪ /‬قطعة‬
‫الكلمة المقابلة‪ .‬قد تميل إلى بناء شبكة عصبية مع عقدة إدخال واحدة (في كل خطوة زمنية)‪،‬‬
‫حيث يمكن تغذية الفهرس كقيمة عددية‪ .‬يعمل هذا عندما نتعامل مع مدخالت عددية مثل السعر‬
‫أو درجة الحرارة‪ ،‬حيث يجب التعامل مع أي قيمتين قريبتين بشكل كافٍ من بعضهما البعض‬
‫بالمثل‪ .‬لكن هذا ليس منطقيًا تمامًا‪ .‬تصادف أن تكون الكلمات ‪ 45th‬والكلمات ‪46th‬يف ‬
‫مفرداتنا "‪ " their‬و "‪ ،“ said‬والتي ال تتشابه معانيها عن بُعد‪.‬‬

‫عند التعامل مع مثل هذه البيانات الفئوية ‪ ،categorical data‬فإن اإلستراتيجية األكثر شيوعًا‬
‫هي تمثيل كل عنصر بترميز واحد ساخن ‪( ne-hot encoding‬استدعاء من القسم ‪.)4.1.1‬‬
‫ترميز واحد ساخن هو متجه يتم تحديد طوله من خالل حجم المفردات 𝑁 ‪ ،‬حيث يتم تعيين‬
‫جميع اإلدخاالت على ‪ ، 0‬باستثناء اإلدخال المقابل للرمز المميز الخاص بنا‪ ،‬والذي تم تعيينه‬
‫على ‪ .1‬على سبيل المثال‪ ،‬إذا كانت المفردات تحتوي على ‪ 5‬عناصر‪ ،‬فإن المتجهات الساخنة‬
‫الواحدة المقابلة للمؤشرات ‪ 0‬و ‪ 2‬ستكون على النحو التالي‪.‬‬

‫)‪tf.one_hot(tf.constant([0, 2]), 5‬‬


‫=‪<tf.Tensor: shape=(2, 5), dtype=float32, numpy‬‬
‫‪array([[1., 0., 0., 0., 0.],‬‬
‫>)‪[0., 0., 1., 0., 0.]], dtype=float32‬‬
‫سوف تأخذ الدفعات الصغيرة التي نختبرهايف كل تكرار الشكل (حجم الدُفعة ‪ ،batch size‬عدد‬
‫الخطوات الزمنية ‪ .)number of time steps‬بمجرد تمثيل كل إدخال على أنه متجه واحد‬
‫ساخن‪ ،‬يمكننا التفكيريف كل دفعة صغيرة على أنه موتر ثالثي األبعاد‪ ،‬حيث يتم إعطاء الطول على‬
‫طول المحور الثالث من خالل حجم المفردات ()‪ .)len(vocab‬غالبًا ما نحول المدخالت‬
‫حتى نحصل على ناتج من الشكل (عدد الخطوات الزمنية‪ ،‬حجم الدفعة‪ ،‬حجم المفردات‬
‫‪ .) vocabulary size‬سيتيح لنا ذلك إجراء حلقة أكثر مالءمة عبر البعد الخارجي لتحديث‬
‫الحاالت المخفية للدفعة الصغيرة‪ ،‬والوقت خطوة بخطوة (على سبيل المثال‪،‬يف طريقة‬
‫‪ forward‬أعاله)‪.‬‬

‫‪@d2l.add_to_class(RNNLMScratch) #@save‬‬
‫‪def one_hot(self, X):‬‬
‫)‪# Output shape: (num_steps, batch_size, vocab_size‬‬
‫‪209‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫)‪return tf.one_hot(tf.transpose(X), self.vocab_size‬‬


‫‪Transforming RNN Outputs RNN‬‬ ‫‪9.5.2.2‬‬
‫يستخدم نموذج اللغة طبقة إخراج متصلة بالكامل لتحويل مخرجات ‪ RNN‬إلى تنبؤات رمزية‬
‫‪token predictions‬يف كل خطوة زمنية‪.‬‬

‫‪@d2l.add_to_class(RNNLMScratch) #@save‬‬
‫‪def output_layer(self, rnn_outputs):‬‬
‫‪outputs = [tf.matmul(H, self.W_hq) + self.b_q for H‬‬
‫]‪in rnn_outputs‬‬
‫)‪return tf.stack(outputs, 1‬‬

‫‪@d2l.add_to_class(RNNLMScratch) #@save‬‬
‫‪def forward(self, X, state=None):‬‬
‫)‪embs = self.one_hot(X‬‬
‫)‪rnn_outputs, _ = self.rnn(embs, state‬‬
‫)‪return self.output_layer(rnn_outputs‬‬
‫دعنا نتحقق مما إذا كان الحساب األمامي ‪ forward computation‬ينتج مخرجات بالشكل‬
‫الصحيح‪.‬‬

‫)‪model = RNNLMScratch(rnn, num_inputs‬‬


‫‪outputs = model(tf.ones((batch_size, num_steps),‬‬
‫))‪dtype=tf.int64‬‬
‫‪d2l.check_shape(outputs, (batch_size, num_steps,‬‬
‫))‪num_inputs‬‬
‫‪Gradient Clipping‬‬ ‫‪9.5.3‬‬
‫بينما كنت معتادًا بالفعل على التفكيريف الشبكات العصبية على أنها "عميقة" بمعنى أن العديد من‬
‫الطبقات تفصل بين المدخالت والمخرجات حتىيف غضون خطوة زمنية واحدة‪ ،‬فإن طول‬
‫التسلسل يقدم مفهومًا جديدًا للعمق‪ .‬باإلضافة إلى المرور عبر الشبكةيف اتجاه اإلدخال إلى‬
‫اإلخراج‪ ،‬يجب أن تمر المدخالتيف الخطوة األولى عبر سلسلة من الطبقات 𝑇 على طول‬
‫الخطوات الزمنية للتأثير على إخراج النموذجيف الخطوة الزمنية النهائية‪ .‬بأخذ وجهة النظر‬
‫العكسية‪،‬يف كل تكرار‪ ،‬نقوم بإعادة نشر التدرجات عبر الزمن‪ ،‬مما ينتج عنه سلسلة من ضرب‬
‫المصفوفة ذات الطول )𝑇(𝒪‪ .‬كما هو مذكوريف القسم ‪ ،5.4‬يمكن أن يؤدي هذا إلى عدم‬
‫االستقرار العددي‪ ،‬مما يتسببيف انفجار التدرجات أو اختفائها اعتمادًا على خصائص مصفوفات‬
‫الوزن‪.‬‬

‫يعد التعامل مع التدرجات المتالشية والمتفجرة مشكلة أساسية عند تصميم شبكات ‪RNN‬‬
‫وقد ألهمت بعضًا من أكبر التطوراتيف هياكل الشبكات العصبية الحديثة‪.‬يف الفصل التالي‪،‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪210‬‬

‫سنتحدث عن ال ُبنى ال متخصصة التي تم تصميمها على أمل التخفيف من مشكلة التدرج‬
‫المتالشي ‪ .vanishing gradient‬ومع ذلك‪ ،‬حتى ‪ RNNs‬الحديثة ال تزال تعانييف كثير من‬
‫األحيان من انفجار التدرجات ‪ .exploding gradients‬أحد الحلول غير األنيقة ولكنه موجود‬
‫في كل مكان هو قص التدرجات ‪ Gradients Clipping‬ببساطة إلجبار التدرجات "المقطوعة‬
‫‪ " clipped‬الناتجة على أخذ قيم أصغر‪.‬‬

‫بشكل عام‪ ،‬عند تحسين بعض األهداف عن طريق التدرج االشتقاقي ‪ ،gradient descent‬نقوم‬
‫بتحديث متكرر للمعامل موضع االهتمام‪ ،‬على سبيل المثال متجه 𝐱 ‪ ،‬ولكن ندفعهيف اتجاه التدرج‬
‫السلبي 𝐠 (في التدرج االشتقاقي العشوائي ‪ ،SGD‬نحسب هذا التدرج على عينة عشوائية من‬
‫الدفعات الصغيرة)‪ .‬على سبيل المثال‪ ،‬مع معدل التعلم ‪ ، 𝜂 > 0‬يأخذ كل تحديث النموذج‬
‫الشكل 𝐠𝜂 ‪ .𝐱 ← 𝐱 −‬لنفترض كذلك أن الدالة الموضوعية 𝑓 سلسة بدرجة كافية‪ .‬رسميًا‪ ،‬نقول‬
‫إن الهدف هو ‪ Lipschitz‬مستمر مع ثابت 𝐿 ‪ ،‬وهذا يعني أنه بالنسبة ألي 𝐱 و 𝐲 ‪ ،‬لدينا‬

‫‪|𝑓(𝐱) − 𝑓(𝐲)| ≤ 𝐿‖𝐱 − 𝐲‖.‬‬

‫كما ترى‪ ،‬عندما نقوم بتحديث متجه المعلمة عن طريق طرح 𝐠𝜂 ‪ ،‬فإن التغييريف قيمة الهدف‬
‫يعتمد على معدل التعلم ومعيار التدرج و𝐿 على النحو التالي‪:‬‬

‫‪|𝑓(𝐱) − 𝑓(𝐱 − 𝜂𝐠)| ≤ 𝐿𝜂‖𝐠‖.‬‬

‫بمعنى آخر‪ ،‬ال يمكن أن يتغير الهدف بأكثر من ‖𝐠‖𝜂𝐿‪ .‬قد يُنظر إلى وجود قيمة صغيرة لهذا‬
‫الحد األعلى على أنه أمر جيد أو سيء‪ .‬على الجانب السلبي‪ ،‬نحن نحد من السرعة التي يمكننا‬
‫بها تقليل قيمة الهدف‪ .‬على الجانب المشرق‪ ،‬يحد هذا من مقدار الخطأ الذي يمكن أن نخطئ‬
‫فيهيف أي خطوة من خطوات االنحدار‪.‬‬

‫عندما نقول إن التدرجات تنفجر‪ ،‬فإننا نعني أن ‖𝐠‖ يصبح كبيرًا للغاية‪.‬يف هذه الحالة األسوأ‪ ،‬قد‬
‫نحدث الكثير من الضرريف خطوة متدرجة واحدة بحيث يمكننا التراجع عن كل التقدم الذي تم‬
‫إحرازه على مدار آالف التكرارات التدريبية‪ .‬عندما يمكن أن تكون التدرجات كبيرة جدًا‪ ،‬غالبًا ما‬
‫يتباعد تدريب الشبكة العصبية‪ ،‬ويفشليف تقليل قيمة الهدف‪.‬يف أوقات أخرى‪ ،‬يتقارب التدريبيف ‬
‫النهاية ولكنه غير مستقر بسبب االرتفاع الهائليف الخطأ‪.‬‬

‫تتمثل إحدى طرق الحد من حجم ‖𝐠‖𝜂𝐿يف تقليص معدل التعلم 𝜂 إلى قيم صغيرة‪ .‬تتمثل‬
‫إحدى الميزات هنايف أننا ال نحيز التحديثات‪ .‬لكن ماذا لو نادرًا ما نحصل على تدرجات كبيرة؟‬
‫هذه الخطوة الجذرية تبطئ تقدمنايف جميع الخطوات‪ ،‬فقط للتعامل مع أحداث التدرج المتفجر‬
‫النادرة‪ .‬البديل الشائع هو تبني قص التدرج اإلرشادي ‪ gradient clipping heuristic‬إلسقاط‬
‫التدرجات 𝐠 على كرة من نصف قطر 𝜃 معين على النحو التالي‪:‬‬
‫‪211‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫𝜃‬
‫‪𝐠 ← 𝑚𝑖𝑛(1,‬‬ ‫‪)𝐠.‬‬
‫‖𝐠‖‬

‫هذا يضمن ان معيار التدرج ال يتجاوز 𝜃 أبدًا وأن التدرج المحدث يتماشى تمامًا مع االتجاه‬
‫األصلي لـ 𝐠‪ .‬كما أن لها أيضًا تأثير جانبي مرغوب فيه للحد من التأثير الذي يمكن أن تمارسه أي‬
‫دفعة صغيرة (وداخله أي عينة معينة) على متجه المعلمة‪ .‬هذا يمنح درجة معينة من المتانة‬
‫للنموذج‪ .‬لنكون واضحين‪ ،‬إنه اختراق‪ .‬يعني قص التدرج ‪ Gradient clipping‬أننا ال نتبع دائمًا‬
‫التدرج الحقيقي ومن الصعب التفكير بشكل تحليلييف اآلثار الجانبية المحتملة‪ .‬ومع ذلك‪ ،‬فهو‬
‫اختراق مفيد للغاية‪ ،‬ويتم اعتماده على نطاق واسعيف تطبيقات ‪RNN‬يف معظم أطر التعلم‬
‫العميق‪.‬‬

‫نحدد أدناه طريقة لقص التدرجات‪ ،‬والتي يتم استدعاؤها بواسطة طريقة ‪ fit_epoch‬لفئة‬
‫‪( d2l.Trainer‬انظر القسم ‪ .)3.4‬الحظ أنه عند حساب معيار التدرج ‪،gradient norm‬‬
‫فإننا نجمع جميع معلمات النموذج‪ ،‬ونتعامل معها على أنها متجه معلمة عمالق واحد‪.‬‬

‫‪@d2l.add_to_class(d2l.Trainer) #@save‬‬
‫‪def clip_gradients(self, grad_clip_val, grads):‬‬
‫‪grad_clip_val = tf.constant(grad_clip_val,‬‬
‫)‪dtype=tf.float32‬‬
‫‪new_grads = [tf.convert_to_tensor(grad) if‬‬
‫(‪isinstance‬‬
‫‪grad, tf.IndexedSlices) else grad for grad in‬‬
‫]‪grads‬‬
‫))‪norm = tf.math.sqrt(sum((tf.reduce_sum(grad ** 2‬‬
‫))‪for grad in new_grads‬‬
‫‪if tf.greater(norm, grad_clip_val):‬‬
‫‪for i, grad in enumerate(new_grads):‬‬
‫‪new_grads[i] = grad * grad_clip_val / norm‬‬
‫‪return new_grads‬‬
‫‪return grads‬‬
‫‪Training‬‬ ‫‪9.5.4‬‬
‫باستخدام مجموعة بيانات (بيانات) ‪ ،The Time Machine‬نقوم بتدريب نموذج لغة على‬
‫مستوى األحرف (‪ )model‬بناءً على )‪ RNN (rnn‬المنفذ من البداية‪ .‬الحظ أننا نحسب‬
‫التدرجات أوالً‪ ،‬ثم نقصها (نقطعها)‪ ،‬ونقوميف النهاية بتحديث معلمات النموذج باستخدام‬
‫التدرجات المقطوعة ‪.clipped gradients‬‬

‫)‪data = d2l.TimeMachine(batch_size=1024, num_steps=32‬‬


‫‪with d2l.try_gpu():‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪212‬‬

‫‪rnn = RNNScratch(num_inputs=len(data.vocab),‬‬
‫)‪num_hiddens=32‬‬
‫‪model = RNNLMScratch(rnn,‬‬
‫)‪vocab_size=len(data.vocab), lr=1‬‬
‫‪trainer = d2l.Trainer(max_epochs=100,‬‬
‫)‪gradient_clip_val=1‬‬
‫)‪trainer.fit(model, data‬‬

‫‪Decoding‬‬ ‫‪9.5.5‬‬
‫بمجرد تعلم نموذج اللغة‪ ،‬يمكننا استخدامه ليس فقط للتنبؤ بالرمز التالي ولكن لمواصلة التنبؤ‬
‫بكل رمز الحق‪ ،‬والتعامل مع الرمز المتوقع مسبقًا كما لو كان الرمز التالييف اإلدخال‪.‬يف بعض‬
‫األحيان نرغب فقطيف إنشاء نص كما لو كنا نبدأيف بداية المستند‪ .‬ومع ذلك‪ ،‬غالبًا ما يكون من‬
‫المفيد شرط نموذج اللغة على بادئة يوفرها المستخدم‪ .‬على سبيل المثال‪ ،‬إذا كنا نطور ميزة‬
‫اإلكمال التلقائي لمحرك البحث أو لمساعدة المستخدمينيف كتابة رسائل البريد اإللكتروني‪،‬‬
‫فنحن نرغبيف تغذية ما كتبوه حتى اآلن (البادئة ‪ ،)the prefix‬ثم إنشاء استمرار محتمل‪.‬‬

‫تولد دالة التنبؤ ‪ predict‬التالية استمرارًا ‪ ،‬حرفًا واحدًايف كل مرة ‪ ،‬بعد إدخال بادئة ‪prefix‬‬
‫مقدمة من المستخدم ‪ ،‬عند المرور عبر األحرف الموجودةيف البادئة ‪ ،prefix‬نستمريف تمرير‬
‫الحالة المخفية إلى الخطوة التالية ولكن ال يتم إنشاء أي ناتج‪ .‬وهذا ما يسمى بفترة اإلحماء‬
‫‪ .warm-up period‬بعد استيعاب البادئة‪ ،‬نحن اآلن على استعداد لبدء إرسال األحرف التالية‪،‬‬
‫والتي سيتم إعادة إدخال كل منهايف النموذج كمدخليف الخطوة الزمنية الالحقة‪.‬‬
‫‪213‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫‪@d2l.add_to_class(RNNLMScratch) #@save‬‬
‫‪def predict(self, prefix, num_preds, vocab,‬‬
‫‪device=None):‬‬
‫]]]‪state, outputs = None, [vocab[prefix[0‬‬
‫‪for i in range(len(prefix) + num_preds - 1):‬‬
‫)]]]‪X = tf.constant([[outputs[-1‬‬
‫)‪embs = self.one_hot(X‬‬
‫)‪rnn_outputs, state = self.rnn(embs, state‬‬
‫‪if i < len(prefix) - 1: # Warm-up period‬‬
‫)]]‪outputs.append(vocab[prefix[i + 1‬‬
‫‪else: # Predict `num_preds` steps‬‬
‫)‪Y = self.output_layer(rnn_outputs‬‬
‫‪outputs.append(int(tf.reshape(tf.argmax(Y,‬‬
‫)))‪axis=2), 1‬‬
‫‪return ''.join([vocab.idx_to_token[i] for i in‬‬
‫)]‪outputs‬‬
‫فيما يلي‪ ،‬نحدد البادئة ونجعلها تولد ‪ 20‬حرفًا إضافيًا‪.‬‬

‫)‪model.predict('it has', 20, data.vocab‬‬


‫'‪'it has hathe the peat he a‬‬

‫في حين أن تنفيذ نموذج ‪ RNN‬أعاله من البداية مفيد‪ ،‬إال أنه ليس مناسبًا‪.‬يف القسم التالي‪،‬‬
‫سنرى كيفية االستفادة من أطر التعلم العميق لتوجيه ‪ RNNs‬باستخدام البنى القياسية‪ ،‬وجني‬
‫مكاسبيف األداء من خالل االعتماد على دوال المكتبة المحسنة للغاية‪.‬‬

‫‪9.5.6‬‬

‫يمكننا تدريب نماذج اللغة المستندة إلى ‪ RNN‬إلنشاء نص يتبع بادئة النص المقدمة من‬
‫المستخدم ‪ .user-provided text prefix‬يتكون نموذج لغة ‪ RNN‬البسيط من ترميز‬
‫اإلدخال ونمذجة ‪ RNN‬وتوليد اإلخراج‪ .‬أثناء التدريب‪ ،‬يمكن لقص التدرج ‪gradient‬‬
‫‪ clipping‬أن يخفف من مشكلة انفجار التدرجات ولكنه ال يعالج مشكلة تالشي التدرجات‪.‬يف ‬
‫التجربة‪ ،‬قمنا بتنفيذ نموذج بسيط للغة ‪ RNN‬وقمنا بتدريبه باستخدام قص التدرج على‬
‫تسلسالت نصية‪ ،‬تم ترميزها على مستوى الحرف‪ .‬من خالل التكييف على بادئة‪ ،‬يمكننا استخدام‬
‫نموذج اللغة إلنشاء عمليات استمرارية محتملة‪ ،‬والتي تثبت فائدتهايف العديد من التطبيقات‪،‬‬
‫على سبيل المثال‪ ،‬ميزات اإلكمال التلقائي‪.‬‬

‫‪9.5.7‬‬
‫‪ .1‬هل يتنبأ نموذج اللغة المطبق بالرمز التالي بناءً على جميع الرموز السابقة حتى أول رمز‬
‫في ‪The Time Machine‬؟‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪214‬‬

‫‪ .2‬ما هي المعلمة الفائقة التي تتحكميف طول السجل المستخدم للتنبؤ؟‬


‫‪ .3‬أظهر أن الترميز الساخن يعادل اختيار تضمين مختلف لكل كائن‪.‬‬
‫‪ .4‬اضبط المعلمات الفائقة (على سبيل المثال‪ ،‬عدد الفترات‪ ،‬عدد الوحدات المخفية‪،‬‬
‫عدد الخطوات الزمنيةيف الدفعات الصغيرة‪ ،‬ومعدل التعلم) لتحسين االرتباك‬
‫‪ .perplexity‬إلى أي مدى يمكن أن تنخفض بينما تتمسك بهذه ال ُبنية البسيطة؟‬
‫‪ .5‬استبدل الترميز الواحد الساخن ‪ one-hot encoding‬بالتضمينات القابل للتعلم‬
‫‪ .learnable embeddings‬هل هذا يؤدي إلى أداء أفضل؟‬
‫‪ .6‬قم بإجراء تجربة لتحديد مدى جودة عمل نموذج اللغة هذا الذي تم تدريبه على ‪The‬‬
‫‪ Time Machine‬على كتب أخرى من تأليف ‪ ،H.G Wells‬على سبيل المثال‪،‬‬
‫‪.The War of the Worlds‬‬
‫‪ .7‬قم بإجراء تجربة أخرى لتقييم مدى ارتباك هذا النموذجيف الكتب التي كتبها مؤلفون‬
‫آخرون‪.‬‬
‫‪ .8‬قم بتعديل دالة التنبؤ مثل استخدام أخذ العينات بدالً من اختيار الحرف التالي األكثر‬
‫احتماالً‪.‬‬
‫ماذا يحدث؟‬ ‫‪o‬‬
‫قم بتحيز النموذج نحو المخرجات األكثر احتمالية‪ ،‬على سبيل المثال‪ ،‬عن طريق‬ ‫‪o‬‬
‫أخذ العينات من ) ‪.𝑞(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1 ) ∝ 𝑃(𝑥𝑡 ∣ 𝑥𝑡−1 , … , 𝑥1‬‬
‫𝛼‬

‫‪ .9‬قم بتشغيل الكوديف هذا القسم دون قص التدرج‪ .‬ماذا يحدث؟‬


‫‪ .10‬استبدل دالة التنشيط المستخدمةيف هذا القسم بـ ‪ ReLU‬وكرر التجاربيف هذا القسم‪.‬‬
‫هل ما زلنا بحاجة إلى قص التدرج؟ لماذا؟‬

‫‪Concise‬‬ ‫‪9.6‬‬
‫‪Implementation of Recurrent Neural Networks‬‬
‫مثل معظم تطبيقاتنا من البداية‪ ،‬تم تصميم القسم ‪ 9.5‬لتوفير نظرة ثاقبة حول كيفية عمل كل‬
‫مكون‪ .‬ولكن عندما تستخدم ‪ RNNs‬كل يوم أو تكتب رمز اإلنتاج‪ ،‬سترغبيف االعتماد أكثر‬
‫على المكتبات التي تقلل من وقت التنفيذ (من خالل توفير كود المكتبة للنماذج والدوال الشائعة)‬
‫ووقت الحساب (عن طريق تحسين الخروج من تطبيقات المكتبة هذه)‪ .‬سيوضح لك هذا القسم‬
‫كيفية تنفيذ نموذج اللغة نفسه بشكل أكثر كفاءة باستخدام واجهة برمجة التطبيقات عالية‬
‫المستوى التي يوفرها إطار عمل التعلم العميق الخاص بك‪ .‬نبدأ‪ ،‬كمايف السابق‪ ،‬بتحميل مجموعة‬
‫بيانات ‪.The Time Machine‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
215 ‫ الشبكات العصبية المتكررة‬:‫الفصل التاسع‬

Defining the Model 9.6.1


‫ المنفذة بواسطة واجهات برمجة التطبيقات عالية المستوى‬RNN ‫نحدد الفئة التالية باستخدام‬
.API

class RNN(d2l.Module): #@save


def __init__(self, num_inputs, num_hiddens):
super().__init__()
self.save_hyperparameters()
self.rnn = nn.RNN(num_inputs, num_hiddens)

def forward(self, inputs, H=None):


return self.rnn(inputs, H)
‫ التالية نموذجًا للغة‬RNNLM ‫ تحدد فئة‬،9.5 ‫يف القسم‬RNNLMScratch ‫موروثًا من فئة‬
.‫ الحظ أننا بحاجة إلى إنشاء طبقة إخراج منفصلة متصلة بالكامل‬.RNN ‫قائمًا على‬

class RNNLM(d2l.RNNLMScratch): #@save


def init_params(self):
self.linear =
tf.keras.layers.Dense(self.vocab_size)

def output_layer(self, hiddens):


return tf.transpose(self.linear(hiddens), (1, 0,
2))
Training and Predicting 9.6.2
‫ نظرًا‬.‫ دعنا نتوقع باستخدام نموذج تمت تهيئته باستخدام أوزان عشوائية‬،‫قبل تدريب النموذج‬
.‫ فسوف تولد تنبؤات ال معنى لها‬،‫ألننا لم ندرب الشبكة‬

data = d2l.TimeMachine(batch_size=1024, num_steps=32)


rnn = RNN(num_hiddens=32)
model = RNNLM(rnn, vocab_size=len(data.vocab), lr=1)
model.predict('it has', 20, data.vocab)
'it hasicaj<unk>zbjqyzttxte<unk>con'

.API ‫ واالستفادة من واجهة برمجة التطبيقات عالية المستوى‬، ‫ نقوم بتدريب نموذجنا‬،‫بعد ذلك‬

with d2l.try_gpu():
trainer = d2l.Trainer(max_epochs=100,
gradient_clip_val=1)
trainer.fit(model, data)
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪216‬‬

‫بالمقارنة مع القسم ‪ ،9.5‬يحقق هذا النموذج ارتباكًا مشابهًا ‪ ،comparable perplexity‬ولكنه‬


‫يعمل بشكل أسرع بسبب عمليات التنفيذ المحسّنة‪ .‬كمايف السابق‪ ،‬يمكننا إنشاء الرموز المتوقعة‬
‫‪ predicted tokens‬بعد سلسلة البادئة المحددة‪.‬‬

‫)‪model.predict('it has', 20, data.vocab‬‬


‫'‪'it has and the thice the t‬‬

‫‪9.6.3‬‬
‫توفر واجهات برمجة التطبيقات عالية المستوى ‪ API‬في أطر التعلم العميق تطبيقات ‪RNNs‬‬
‫القياسية‪ .‬تساعدك هذه المكتبات على تجنب إضاعة الوقتيف إعادة تنفيذ النماذج القياسية‪.‬‬
‫عالوة على ذلك‪ ،‬غالبًا ما يتم تحسين تطبيقات إطار العمل بشكل كبير‪ ،‬مما يؤدي إلى مكاسب‬
‫كبيرةيف األداء (الحسابي) مقارنة بالتطبيقات من البداية‪.‬‬

‫‪9.6.4‬‬
‫‪ .1‬هل يمكنك جعل نموذج ‪ RNN‬يعاني من الضبط الزائد ‪ overfitting‬باستخدام‬
‫واجهات برمجة التطبيقات عالية المستوى ‪API‬؟‬
‫‪ .2‬نفذ نموذج االنحدار الذاتي ‪ autoregressive model‬للقسم ‪ 9.1‬باستخدام‬
‫‪.RNN‬‬

‫‪Backpropagation Through Time‬‬ ‫‪9.7‬‬


‫إذا أكملت التمارين الواردة في القسم ‪ ، 9.5‬فستالحظ أن قص التدرج ‪ gradient clipping‬أمر‬
‫حيوي لمنع التدرجات الضخمة العرضية من التدريب المزعزع لالستقرار‪ .‬لقد ألمحنا إلى أن‬
‫‪217‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫التدرجات المتفجرة تنبع من االنتشار الخلفي عبر تسلسالت طويلة‪ .‬قبل تقديم عدد كبير من بنى‬
‫‪ RNN‬الحديثة ‪ ،‬دعنا نلقي نظرة فاحصة على كيفية عمل االنتشار الخلفي‬
‫‪ backpropagation‬في نماذج التسلسل بتفاصيل رياضية‪ .‬نأمل أن تجلب هذه المناقشة بعض‬
‫الدقة لمفهوم التالشي وانفجار التدرجات‪ .‬إذا كنت تتذكر مناقشتنا حول االنتشار األمامي والخلفي‬
‫من خالل الرسوم البيانية الحسابية عندما قدمنا ‪ MLPs‬في القسم ‪ ، 5.3‬فيجب أن يكون االنتشار‬
‫األمامي في ‪ RNNs‬مباشرًا نسبيًا‪ .‬يسمى تطبيق االنتشار الخلفي في ‪RNNs‬االنتشار الخلفي‬
‫عبر الزمن ‪ .)1990 ،Werbos ( backpropagation through time‬يتطلب هذا اإلجراء‬
‫منا توسيع ‪( expand‬أو ‪ )unroll‬الرسم البياني الحسابي لخطوة واحدة في وقت واحد في كل‬
‫مرة‪ .‬إن ‪ RNN‬الموسعة هو أساسًا ش بكة عصبية تلقائية ذات خاصية خاصة تتكرر فيها نفس‬
‫المعلمات في جميع أنحاء الشبكة غير المنضبطة ‪ ،‬وتظهر في كل خطوة زمنية‪ .‬بعد ذلك ‪ ،‬تمامًا‬
‫كما هو الحال في أي شبكة عصبية امامية التغذية ‪ ،‬يمكننا تطبيق قاعدة السلسلة ‪ ،‬االنتشار الخلفي‬
‫للتدرجات عبر ‪ .unrolled net‬يجب جمع التدرج ‪ gradient‬فيما يتعلق بكل معلمة عبر جميع‬
‫األماكن التي تحدث فيها المعلمة في ‪ .unrolled net‬يجب أن يكون التعامل مع مثل هذا الربط‬
‫بالوزن مألوفًا في فصولنا حول الشبكات العصبية التالفيفية‪.‬‬

‫تنشأ المضاعفات ألن التسلسالت يمكن أن تكون طويلة نوعًا ما‪ .‬ليس من غير المعتاد العمل مع‬
‫تسلسالت نصية تتكون من أكثر من ألف رمز‪ .‬الحظ أن هذا يطرح مشاكل من وجهة نظر حسابية‬
‫(الكثير من الذاكرة) والتحسين (عدم االستقرار العددي)‪ .‬المدخالت من الخطوة األولى تمر عبر‬
‫أكثر من ‪ 1000‬ضرب مصفوفة قبل الوصول إلى المخرجات ‪ ،‬وهناك حاجة إلى ‪ 1000‬ضرب‬
‫مصفوفة أخرى لحساب التدرج‪ .‬نقوم اآلن بتحليل الخطأ الذي يمكن أن يحدث وكيفية معالجته‬
‫في الممارسة العملية‪.‬‬

‫‪RNNs‬‬ ‫‪9.7.1‬‬
‫نبدأ بنموذج مبسط لكيفية عمل ال ‪ .RNN‬يتجاهل هذا النموذج تفاصيل حول تفاصيل الحالة‬
‫المخفية وكيفية تحديثها‪ .‬ال يميز الترميز الرياضي هنا بشكل صريح بين القيم القياسية ‪scalars‬‬
‫والمتجهات ‪ vectors‬والمصفوفات ‪ .matrices‬نحن نحاول فقط تطوير بعض الحدس‪ .‬في‬
‫هذا النموذج المبسط ‪ ،‬نشير إلى الحالة المخفية 𝑡‪ ℎ‬و 𝑡𝑥كمدخالت و 𝑡𝑜كمخرج في الخطوة‬
‫الزمنية 𝑡‪ .‬تذكر مناقشاتنا في القسم ‪ 9.4.2‬أن اإلدخال والحالة المخفية يمكن تسلسلهما قبل‬
‫ضربهما بمتغير وزن واحد في الطبقة المخفية‪ .‬وبالتالي ‪ ،‬فإننا نستخدم ‪ 𝑤ℎ‬و 𝑜𝑤 لنؤشر أوزان‬
‫الطبقة المخفية وطبقة المخرجات ‪ ،‬على التوالي‪ .‬نتيجة لذلك ‪ ،‬فإن الحاالت المخفية‬
‫والمخرجات في كل مرة من الخطوات هي‬

‫𝑡‪ℎ‬‬ ‫‪= 𝑓(𝑥𝑡 , ℎ𝑡−1 , 𝑤ℎ ),‬‬


‫)‪(9.7.1‬‬
‫𝑡𝑜‬ ‫‪= 𝑔(ℎ𝑡 , 𝑤𝑜 ),‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪218‬‬

‫حيث 𝑓 و𝑔 هي تحويالت الطبقة المخفية وطبقة اإلخراج ‪ ،‬على التوالي‪ .‬ومن ثم ‪ ،‬لدينا سلسلة‬
‫من القيم } … ‪ {… , (𝑥𝑡−1 , ℎ𝑡−1 , 𝑜𝑡−1 ), (𝑥𝑡 , ℎ𝑡 , 𝑜𝑡 ),‬التي تعتمد على بعضها البعض من‬
‫‪forward‬‬ ‫خالل الحساب المتكرر ‪ .recurrent computation‬االنتشار األمامي‬
‫‪ propagation‬واضح إلى حد ما‪ .‬كل ما نحتاجه هو تكرار الخطوات الثالثية ) 𝑡𝑜 ‪ (𝑥𝑡 , ℎ𝑡 ,‬مرة‬
‫واحدة في كل مرة‪ .‬يتم بعد ذلك تقييم التناقض بين المخرجات 𝑡𝑜 والهدف المطلوب 𝑡𝑦 بواسطة‬
‫دالة هدف 𝑇 عبر جميع الخطوات الزمنية‬
‫𝑇‬
‫‪1‬‬
‫∑ = ) 𝑜𝑤 ‪𝐿(𝑥1 , … , 𝑥𝑇 , 𝑦1 , … , 𝑦𝑇 , 𝑤ℎ ,‬‬ ‫‪𝑙(𝑦𝑡 , 𝑜𝑡 ).‬‬
‫𝑇‬
‫‪𝑡=1‬‬

‫بالنسبة إلى ‪ ، backpropagation‬تكون األمور أكثر تعقيدًا بعض الشيء ‪ ،‬خاصةً عندما نحسب‬
‫التدرجات فيما يتعلق بمعلمات ‪ 𝑤ℎ‬الدالة الموضوعية 𝐿‪ .‬على وجه التحديد ‪ ،‬من خالل قاعدة‬
‫السلسلة‪،‬‬
‫𝐿𝜕‬ ‫‪1‬‬ ‫) 𝑡𝑜‪𝜕𝑙(𝑦𝑡 ,‬‬
‫‪𝜕𝑤ℎ‬‬
‫‪= 𝑇 ∑𝑇𝑡=1‬‬ ‫‪𝜕𝑤ℎ‬‬
‫‪1‬‬ ‫𝑡‪𝜕𝑙(𝑦𝑡 ,𝑜𝑡 ) 𝜕𝑔(ℎ𝑡 ,𝑤𝑜 ) 𝜕ℎ‬‬
‫)‪(9.7.3‬‬
‫‪= ∑𝑇𝑡=1‬‬ ‫‪.‬‬
‫𝑇‬ ‫𝑡𝑜𝜕‬ ‫𝑡‪𝜕ℎ‬‬ ‫‪𝜕𝑤ℎ‬‬

‫يسهل حساب العامل األول والثاني للضرب في (‪ .)9.7.3‬العامل الثالث ‪ 𝜕ℎ𝑡 /𝜕𝑤ℎ‬هو المكان‬
‫الذي تصبح فيه األشياء خادعة ‪ ،‬ألننا نحتاج إلى حساب تأثير المعلمة ‪ 𝑤ℎ‬على 𝑡‪ ℎ‬بشكل متكرر‪.‬‬
‫وفقًا للحساب المتكرر في (‪ ℎ𝑡 ، )9.7.1‬يعتمد على كال ‪ ℎ𝑡−1‬و ‪ ، 𝑤ℎ‬وحيث يعتمد حساب‬
‫‪ ℎ𝑡−1‬على ‪ 𝑤ℎ‬أيضًا‪ .‬وبالتالي ‪ ،‬فإن تقييم إجمالي المشتق لـ 𝑡‪ ℎ‬فيما يتعلق بـ ‪ 𝑤ℎ‬باستخدام‬
‫عوائد قاعدة السلسلة‬
‫𝑡‪𝜕ℎ‬‬ ‫) ‪𝜕𝑓(𝑥𝑡 ,ℎ𝑡−1 ,𝑤ℎ‬‬ ‫‪𝜕𝑓(𝑥𝑡 ,ℎ𝑡−1 ,𝑤ℎ ) 𝜕ℎ𝑡−1‬‬
‫=‬ ‫‪+‬‬ ‫‪.‬‬ ‫)‪(9.7.4‬‬
‫‪𝜕𝑤ℎ‬‬ ‫‪𝜕𝑤ℎ‬‬ ‫‪𝜕ℎ𝑡−1‬‬ ‫‪𝜕𝑤ℎ‬‬

‫الشتقاق التدرج أعاله ‪ ،‬افترض أن لدينا ثالثة متواليات } 𝑡𝑐{ ‪ {𝑎𝑡 }, {𝑏𝑡 },‬تحقق ‪𝑎0 = 0‬‬
‫و ‪ 𝑎𝑡 = 𝑏𝑡 + 𝑐𝑡 𝑎𝑡−1‬من أجل … ‪ .𝑡 = 1,2,‬ثم الجل ‪ 𝑡 ≥ 1‬من السهل أن تظهر‬
‫‪𝑡−1‬‬
‫∑ ‪𝑎𝑡 = 𝑏𝑡 +‬‬ ‫‪(∏𝑡𝑗=𝑖+1‬‬ ‫‪𝑐𝑗 ) 𝑏𝑖 .‬‬ ‫)‪(9.7.5‬‬
‫‪𝑖=1‬‬

‫بتعويض 𝑡𝑎 ‪ 𝑏𝑡 ،‬و 𝑡𝑐 وفقًا لـ‬


‫‪219‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫𝑡‪𝜕ℎ‬‬
‫𝑡𝑎‬ ‫=‬ ‫‪,‬‬
‫‪𝜕𝑤ℎ‬‬
‫) ‪𝜕𝑓(𝑥𝑡 ,ℎ𝑡−1 ,𝑤ℎ‬‬
‫𝑡𝑏‬ ‫=‬ ‫‪𝜕𝑤ℎ‬‬
‫‪,‬‬ ‫)‪(9.7.6‬‬
‫) ‪𝜕𝑓(𝑥𝑡 ,ℎ𝑡−1 ,𝑤ℎ‬‬
‫𝑡𝑐‬ ‫=‬ ‫‪𝜕ℎ𝑡−1‬‬
‫‪,‬‬

‫حساب التدرج في (‪ )9.7.4‬يحقق ‪ 𝑎𝑡 = 𝑏𝑡 + 𝑐𝑡 𝑎𝑡−1‬وبالتالي ‪ ،‬في (‪ ، )9.7.5‬يمكننا إزالة‬


‫الحساب المتكرر في (‪ )9.7.4‬مع‬
‫‪𝑡−1‬‬
‫) ‪𝜕𝑓(𝑥𝑗 ,ℎ𝑗−1 ,𝑤ℎ ) 𝜕𝑓(𝑥𝑖 ,ℎ𝑖−1 ,𝑤ℎ‬‬
‫)‪. (9.7.7‬‬
‫𝑡‪𝜕ℎ‬‬ ‫) ‪𝜕𝑓(𝑥𝑡 ,ℎ𝑡−1 ,𝑤ℎ‬‬
‫=‬ ‫∑‪+‬‬ ‫‪(∏𝑡𝑗=𝑖+1‬‬ ‫)‬
‫‪𝜕𝑤ℎ‬‬ ‫‪𝜕𝑤ℎ‬‬ ‫‪𝜕ℎ𝑗−1‬‬ ‫‪𝜕𝑤ℎ‬‬
‫‪𝑖=1‬‬

‫بينما يمكننا استخدام قاعدة السلسلة لحساب ‪ 𝜕ℎ𝑡 /𝜕𝑤ℎ‬بشكل تكراري ‪ ،recursively‬يمكن‬
‫أن تصبح هذه السلسلة طويلة جدًا عندما 𝑡 تكون كبيرة‪ .‬دعونا نناقش عددًا من االستراتيجيات‬
‫للتعامل مع هذه المشكلة‪.‬‬

‫‪Full Computation‬‬ ‫‪9.7.1.1‬‬


‫قد تكون إحدى األفكار هي حساب المبلغ الكامل ‪ full sum‬في (‪ .)9.7.7‬ومع ذلك ‪ ،‬فإن هذا‬
‫بطيء جدًا ويمكن أن تتفجر التدرجات ‪ ،‬نظرًا ألن التغييرات الطفيفة في الظروف األولية يمكن‬
‫أن تؤثر على النتيجة كثيرًا‪ .‬بمعنى أنه يمكننا رؤية أشياء مشابهة لتأثير الفراشة ‪،butterfly effect‬‬
‫حيث تؤدي التغييرات الطفيفة في الظروف األولية إلى تغييرات غير متناسبة في النتيجة‪ .‬هذا‬
‫بشكل عام غير مرغوب فيه‪ .‬بعد كل شيء ‪ ،‬نحن نبحث عن مقدرات قوية تعمم جيدًا‪ .‬ومن ثم‬
‫فإن هذه اإلستراتيجية ال تُستخدم أبدًا في الممارسة العملية‪.‬‬

‫‪Truncating Time Steps‬‬ ‫‪9.7.1.2‬‬


‫بدالً من ذلك ‪ ،‬يمكننا اقتطاع المجموع ‪ truncate the sum‬في (‪ )9.7.7‬بعد الخطوات‪ .‬هذا‬
‫ما كنا نناقشه حتى اآلن‪ .‬هذا يؤدي إلى تقريب التدرج الحقيقي ‪ ،‬ببساطة عن طريق إنهاء المجموع‬
‫عند ‪ .𝜕ℎ𝑡−𝜏 /𝜕𝑤ℎ‬في الممارسة العملية ‪ ،‬هذا يعمل بشكل جيد‪ .‬هذا هو ما يشار إليه عادة باسم‬
‫االنتشار الخلفي المقتطع عبر الزمن ‪truncated backpropgation through time‬‬
‫( ‪ .) 2002 ،Jaeger‬ومن عواقب ذلك أن النموذج يركز في المقام األول على التأثير قصير المدى‬
‫بدالً من العواقب طويلة المدى‪ .‬هذا أمر مرغوب فيه بالفعل ‪ ،‬ألنه يوجه التقدير نحو نماذج أبسط‬
‫وأكثر استقرارًا‪.‬‬

‫‪Randomized Truncation‬‬ ‫‪9.7.1.3‬‬


‫أخيرًا ‪ ،‬يمكننا االستعاضة ‪ 𝜕ℎ𝑡 /𝜕𝑤ℎ‬ب متغير عشوائي يكون صحيحًا في التوقع ولكنه يقطع‬
‫التسلسل‪ .‬يتم تحقيق ذلك باستخدام تسلسل 𝑡𝜉 مع معرف مسبقًا ‪ ، 0 ≤ 𝜋𝑡 ≤ 1‬حيث‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪220‬‬

‫𝑡𝜋 ‪ 𝑃(𝜉𝑡 = 0) = 1 −‬و 𝑡𝜋 = ) ‪ 𝑃(𝜉𝑡 = 𝜋𝑡−1‬لذلك ‪ .𝐸[𝜉𝑡 ] = 1‬نستخدم هذا الستبدال‬


‫التدرج ‪ 𝜕ℎ𝑡 /𝜕𝑤ℎ‬في (‪ )9.7.4‬بـ‬

‫) ‪𝜕𝑓(𝑥𝑡 , ℎ𝑡−1 , 𝑤ℎ‬‬ ‫‪𝜕𝑓(𝑥𝑡 , ℎ𝑡−1 , 𝑤ℎ ) 𝜕ℎ𝑡−1‬‬


‫= 𝑡𝑧‬ ‫𝑡𝜉 ‪+‬‬ ‫‪.‬‬
‫‪𝜕𝑤ℎ‬‬ ‫‪𝜕ℎ𝑡−1‬‬ ‫‪𝜕𝑤ℎ‬‬

‫يتبع من تعريف 𝑡𝜉 ذلك ‪ .𝐸[𝑧𝑡 ] = 𝜕ℎ𝑡 /𝜕𝑤ℎ‬حيث ينتهي الحساب المتكرر ‪ 𝜉𝑡 = 0‬في تلك‬
‫الخطوة الزمنية 𝑡‪ .‬يؤدي هذا إلى مجموع اوزان للتسلسالت ذات أطوال متفاوتة ‪ ،‬حيث تكون‬
‫التسلسالت الطويلة نادرة ولكنها ذات وزن زائد ‪ overweighted‬بشكل مناسب‪ .‬تم اقتراح هذه‬
‫الفكرة من قبل ‪ Tallec‬و ‪.)2017( Ollivier‬‬

‫‪Comparing Strategies‬‬ ‫‪9.7.1.4‬‬

‫الشكل ‪ 9.7.1‬مقارنة استراتيجيات حساب التدرجات في ‪ .RNNs‬من أعلى إلى أسفل‪:‬‬


‫االقتطاع العشوائي ‪ randomized truncation‬واالقتطاع المنتظم ‪regular truncation‬‬
‫والحساب الكامل ‪.full computation‬‬

‫يوضح الشكل ‪ 9.7.1‬االستراتيجيات الثالث عند تحليل األحرف القليلة األولى من ‪The‬‬
‫‪ Time Machine‬باستخدام االنتشار الخلفي عبر الزمن لـ ‪:RNNs‬‬

‫الصف األول هو االقتطاع العشوائي ‪ randomized truncation‬الذي يقسم النص إلى‬ ‫•‬
‫مقاطع ذات أطوال مختلفة‪.‬‬
‫الصف الثاني هو االقتطاع المنتظم ‪ regular truncation‬الذي يقسم النص إلى‬ ‫•‬
‫تتابعات من نفس الطول‪ .‬هذا ما كنا نفعله في تجارب ‪.RNN‬‬
‫الصف الثالث هو االنتشار الخلفي الكامل عبر الزمن الذي يؤدي إلى تعبير غير عملي‬ ‫•‬
‫حسابيًا‪.‬‬

‫لسوء الحظ‪ ،‬على الرغم من جاذبيته من الناحية النظرية‪ ،‬فإن االقتطاع العشوائي ال يعمل بشكل‬
‫أفضل بكثير من االقتطاع المنتظم‪ ،‬ويرجع ذلك على األرجح إلى عدد من العوامل‪ .‬أوالً‪ ،‬تأثير‬
‫المشاهدة بعد عدد من خطوات االنتشار الخلفييف الماضي كافٍ تمامًا اللتقاط التبعياتيف ‬
‫الممارسة العملية‪ .‬ثانيًا‪ ،‬يتعارض التباين المتزايد مع حقيقة أن التدرج يكون أكثر دقة بمزيد من‬
‫‪221‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫الخطوات‪ .‬ثالثًا‪ ،‬نريديف الواقع نماذج لها نطاق قصير من التفاعالت‪ .‬وبالتالي‪ ،‬فإن االنتشار‬
‫الخلفي المقتطع بانتظام عبر الزمن له تأثير تنظيم طفيف يمكن أن يكون مرغوبًا فيه‪.‬‬

‫‪Backpropagation Through‬‬ ‫‪9.7.2‬‬


‫‪Time in Detail‬‬
‫بعد مناقشة المبدأ العام‪ ،‬دعونا نناقش االنتشار الخلفي عبر الزمن بالتفصيل‪ .‬بخالف التحليل‬
‫الوارديف القسم ‪ ،9.7.1‬سنعرض فيما يلي كيفية حساب تدرجات الدالة الموضوعية فيما يتعلق‬
‫بجميع معلمات النموذج المتحللة‪ .‬لتبسيط األمور‪ ،‬فإننا نعتبر ‪ RNN‬بدون معلمات التحيز‪،‬‬
‫والتي تستخدم دالة التنشيط الخاصة بهايف الطبقة المخفية تعيين الهوية ‪identity mapping‬‬
‫(𝑥 = )𝑥(𝜙)‪ .‬بالنسبة للخطوة الزمنية 𝑡‪ ،‬دع إدخال المثال الفردي والهدف يكونان 𝑑‪،𝐱𝑡 ∈ ℝ‬‬
‫𝑡𝑦على التوالي‪ .‬يتم حساب الحالة المخفية ‪ 𝐡𝑡 ∈ ℝℎ‬واإلخراج 𝑞‪ 𝐨𝑡 ∈ ℝ‬كـ‬

‫𝑡𝐡‬ ‫‪= 𝐖ℎ𝑥 𝐱𝑡 + 𝐖ℎℎ 𝐡𝑡−1 ,‬‬


‫𝑡𝐨‬ ‫‪= 𝐖𝑞ℎ 𝐡𝑡 ,‬‬

‫حيث 𝑑×‪ 𝐖ℎℎ ∈ ℝℎ×ℎ ، 𝐖ℎ𝑥 ∈ ℝℎ‬و ‪ 𝐖𝑞ℎ ∈ ℝ𝑞×ℎ‬هي معلمات الوزن‪ 𝑙(𝐨𝑡 , 𝑦𝑡 ) .‬تدل‬
‫على الخطأيف الخطوة الزمنية 𝑡‪ .‬دالتنا الموضوعية هي الخطأ بمرور الوقت 𝑇 من بداية التسلسل‬
‫لذلك‪:‬‬
‫𝑇‬
‫‪1‬‬
‫‪𝐿 = ∑ 𝑙(𝐨𝑡 , 𝑦𝑡 ).‬‬
‫𝑇‬
‫‪𝑡=1‬‬

‫الشكل ‪ 9.7.2‬رسم بياني حسابي يوضح التبعيات لنموذج ‪ RNN‬بثالث خطوات زمنية‪ .‬تمثل‬
‫المربعات متغيرات (غير مظللة) أو معلمات (مظللة) وتمثل الدوائر عوامل التشغيل‪.‬‬

‫من أجل تصور التبعيات بين متغيرات النموذج والمعلمات أثناء حساب ‪ ،RNN‬يمكننا رسم‬
‫مخطط بياني حسابي للنموذج‪ ،‬كما هو موضحيف الشكل ‪ .9.7.2‬على سبيل المثال‪ ،‬يعتمد حساب‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪222‬‬

‫الحاالت المخفية للخطوة الزمنية ‪ 𝐡3 ،3‬على معلمات النموذج 𝑥‪ 𝐖ℎ‬و ‪ 𝐖ℎℎ‬الحالة المخفية‬
‫لخطوة الوقت األخيرة ‪ 𝐡2‬وإدخال الخطوة الزمنية الحالية ‪.𝐱3‬‬

‫كما ذكر للتو ‪ ،‬فإن معلمات النموذج في الشكل ‪ 9.7.2‬هي 𝑥‪ 𝐖ℎ‬و ‪ 𝐖ℎℎ‬و ‪ .𝐖𝑞ℎ‬بشكل عام ‪،‬‬
‫يتطلب تدريب هذا النموذج حساب التدرج فيما يتعلق بهذه المعلمات ‪𝜕𝐿/𝜕𝐖ℎ𝑥 ،‬‬
‫و ‪ 𝜕𝐿/𝜕𝐖ℎℎ‬و ‪ .𝜕𝐿/𝜕𝐖𝑞ℎ‬وفقًا للتبعيات الواردة في الشكل ‪ ، 9.7.2‬يمكننا اجتياز االتجاه‬
‫المعاكس لألسهم لحساب وتخزين التدرجات بدورها‪ .‬للتعبير بمرونة عن ضرب المصفوفات‬
‫والمتجهات والكميات ذات األشكال المختلفة في قاعدة السلسلة ‪ ،‬نستمر في استخدام العامل‬
‫‪ prod‬كما هو موضح في القسم ‪.5.3‬‬

‫بادئ ذي بدء ‪ ،‬يعد التفريق بين الدالة الموضوعية فيما يتعلق بإخراج النموذج في أي خطوة زمنية‬
‫𝑡 أمرًا بسيطًا إلى حد ما‪:‬‬

‫𝐿𝜕‬ ‫) 𝑡𝑦 ‪𝜕𝑙(𝐨𝑡 ,‬‬


‫=‬ ‫‪∈ ℝ𝑞 .‬‬
‫𝑡𝐨𝜕‬ ‫𝑡𝐨𝜕 ⋅ 𝑇‬

‫اآلن‪ ،‬يمكننا حساب انحدار الهدف فيما يتعلق بالمعامل ‪ 𝐖𝑞ℎ‬في طبقة المخرجات‪:‬‬
‫‪ .𝜕𝐿/𝜕𝐖𝑞ℎ ∈ ℝ𝑞×ℎ‬بناءً على الشكل ‪ ، 9.7.2‬يعتمد الهدف 𝐿 على ‪ 𝐖𝑞ℎ‬بواسطة‬
‫𝑇 𝐨 ‪ .𝐨1 , … ,‬باستخدام قاعدة السلسلة ينتج‬
‫𝑇‬ ‫𝑇‬
‫𝐿𝜕‬ ‫𝑡𝐨𝜕 𝐿𝜕‬ ‫⊤ 𝐿𝜕‬
‫∑=‬ ‫(‪prod‬‬ ‫‪,‬‬ ‫∑=)‬ ‫‪𝐡 ,‬‬
‫‪𝜕𝐖𝑞ℎ‬‬ ‫‪𝜕𝐨𝑡 𝜕𝐖𝑞ℎ‬‬ ‫𝑡 𝑡𝐨𝜕‬
‫‪𝑡=1‬‬ ‫‪𝑡=1‬‬

‫حيث 𝑡𝐨𝜕‪ 𝜕𝐿/‬تعطى بواسطة (‪.)9.7.11‬‬

‫بعد ذلك ‪ ،‬كما هو موضح في الشكل ‪ ، 9.7.2‬في الخطوة الزمنية النهائية 𝑇‪ ،‬تعتمد دالة الهدف‬
‫على الحالة المخفية 𝑇 𝐡 فقط عبر 𝑇 𝐨‪ .‬لذلك ‪ ،‬يمكننا بسهولة إيجاد التدرج ‪𝜕𝐿/𝜕𝐡𝑇 ∈ ℝℎ‬‬
‫باستخدام قاعدة السلسلة‪:‬‬

‫𝐿𝜕‬ ‫𝑇 𝐨𝜕 𝐿𝜕‬ ‫𝐿𝜕‬


‫(‪= prod‬‬ ‫‪,‬‬ ‫⊤‬
‫‪) = 𝐖𝑞ℎ‬‬ ‫‪.‬‬
‫𝑇 𝐡𝜕‬ ‫𝑇 𝐡𝜕 𝑇 𝐨𝜕‬ ‫𝑇 𝐨𝜕‬

‫يصبح األمر أكثر تعقيدًا في أي خطوة زمنية 𝑇 < 𝑡‪ ،‬حيث تعتمد الدالة الموضوعية 𝐿 على 𝑡𝐡‬
‫عبر ‪ 𝐡𝑡+1‬و 𝑡𝐨‪ .‬وفقًا لقاعدة السلسلة ‪ ،‬يمكن حساب التدرج للحالة المخفية ‪𝜕𝐿/𝜕𝐡𝑡 ∈ ℝℎ‬‬
‫في أي خطوة زمنية 𝑇 < 𝑡 بشكل متكرر على النحو التالي‪:‬‬

‫𝐿𝜕‬ ‫‪𝜕𝐿 𝜕𝐡𝑡+1‬‬ ‫𝑡𝐨𝜕 𝐿𝜕‬ ‫𝐿𝜕‬ ‫𝐿𝜕‬


‫(‪= prod‬‬ ‫‪,‬‬ ‫(‪) + prod‬‬ ‫‪,‬‬ ‫⊤‬
‫‪) = 𝐖ℎℎ‬‬ ‫⊤‬
‫‪+ 𝐖𝑞ℎ‬‬ ‫‪.‬‬
‫𝑡𝐡𝜕‬ ‫𝑡𝐡𝜕 ‪𝜕𝐡𝑡+1‬‬ ‫𝑡𝐡𝜕 𝑡𝐨𝜕‬ ‫‪𝜕𝐡𝑡+1‬‬ ‫𝑡𝐨𝜕‬
‫‪223‬‬ ‫الفصل التاسع‪ :‬الشبكات العصبية المتكررة‬

‫للتحليل ‪ ،‬يعطي توسيع الحساب المتكرر ألي خطوة زمنية 𝑇 ≤ 𝑡 ≤ ‪1‬‬


‫𝑇‬
‫𝐿𝜕‬ ‫⊤ 𝑖‪⊤ 𝑇−‬‬
‫𝐿𝜕‬
‫∑=‬ ‫‪(𝐖ℎℎ‬‬ ‫‪) 𝐖𝑞ℎ‬‬ ‫‪.‬‬
‫𝑡𝐡𝜕‬ ‫𝑖‪𝜕𝐨 𝑇+𝑡−‬‬
‫𝑡=𝑖‬

‫يمكننا أن نرى من (‪ )9.7.15‬أن هذا المثال الخطي البسيط يعرض بالفعل بعض المشكالت‬
‫‪ .𝐖ℎℎ‬في ذلك ‪ ،‬تختفي‬
‫⊤‬
‫الرئيسية لنماذج التسلسل الطويل‪ :‬إنه ينطوي على إمكانات كبيرة جدًا من‬
‫القيم الذاتية ‪ eigenvalues‬األصغر من ‪ 1‬وتتباعد القيم الذاتية األكبر من ‪ .1‬هذا غير مستقر‬
‫عدديًا ‪ ،‬والذي يتجلى في شكل تدرجات متالشية ومتفجرة‪ .‬تتمثل إحدى طرق معالجة ذلك في‬
‫اقتطاع الخطوات الزمنية بحجم مناسب حسابيًا كما تمت مناقشته في القسم ‪ .9.7.1‬من الناحية‬
‫العملية ‪ ،‬يمكن أيضًا إجراء هذا االقتطاع عن طريق فصل التدرج بعد عدد معين من الخطوات‬
‫الزمنية‪ .‬الحقًا ‪ ،‬سنرى كيف يمكن لنماذج التسلسل األكثر تعقيدًا مثل الذاكرة طويلة قصيرة‬
‫المدى ‪ long short-term memory‬أن تخفف من حدة هذا األمر أكثر‪.‬‬

‫أخيرًا ‪ ،‬يوضح الشكل ‪ 9.7.2‬أن دالة الهدف 𝐿 تعتمد على معلمات النموذج 𝑥‪ 𝐖ℎ‬و ‪ 𝐖ℎℎ‬في‬
‫الطبقة المخفية عبر الحاالت المخفية 𝑇 𝐡 ‪ .𝐡1 , … ,‬لحساب التدرجات فيما يتعلق بهذه‬
‫المعلمات 𝑑×‪ 𝜕𝐿/𝜕𝐖ℎ𝑥 ∈ ℝℎ‬و ‪ 𝜕𝐿/𝜕𝐖ℎℎ ∈ ℝℎ×ℎ‬نطبق قاعدة السلسلة التي تعطي‬
‫𝑇‬ ‫𝑇‬
‫𝐿𝜕‬ ‫𝑡𝐡𝜕 𝐿𝜕‬ ‫⊤ 𝐿𝜕‬
‫∑=‬ ‫(‪prod‬‬ ‫‪,‬‬ ‫∑=)‬ ‫‪𝐱 ,‬‬
‫𝑥‪𝜕𝐖ℎ‬‬ ‫𝑥‪𝜕𝐡𝑡 𝜕𝐖ℎ‬‬ ‫𝑡 𝑡𝐡𝜕‬
‫‪𝑡=1‬‬ ‫‪𝑡=1‬‬
‫𝑇‬ ‫𝑇‬
‫𝐿𝜕‬ ‫𝑡𝐡𝜕 𝐿𝜕‬ ‫⊤ 𝐿𝜕‬
‫∑=‬ ‫(‪prod‬‬ ‫‪,‬‬ ‫∑=)‬ ‫‪𝐡 ,‬‬
‫‪𝜕𝐖ℎℎ‬‬ ‫‪𝜕𝐡𝑡 𝜕𝐖ℎℎ‬‬ ‫‪𝜕𝐡𝑡 𝑡−1‬‬
‫‪𝑡=1‬‬ ‫‪𝑡=1‬‬

‫حيث 𝑡𝐡𝜕‪ 𝜕𝐿/‬يتم حسابها بشكل متكرر بواسطة (‪ )9.7.13‬و (‪ )9.7.14‬هي الكمية الرئيسية‬
‫التي تؤثر على االستقرار العددي‪.‬‬

‫نظرًا ألن االنتشار الخلفي عبر الزمن هو تطبيق االنتشار الخلفي في ‪ ، RNNs‬كما أوضحنا في‬
‫القسم ‪ ، 5.3‬فإن تدريب ‪ RNNs‬يبدل االنتشار األمامي مع االنتشار الخلفي عبر الزمن‪ .‬إلى‬
‫جانب ذلك ‪ ،‬يحسب االنتشار الخلفي عبر الزمن ويخزن التدرجات المذكورة أعاله بدوره‪ .‬على‬
‫وجه التحديد ‪ ،‬يتم إعادة استخدام القيم الوسيطة المخزنة لتجنب تكرار العمليات الحسابية ‪،‬‬
‫مثل تخزين 𝑡𝐡𝜕‪ 𝜕𝐿/‬الستخدامها في حساب كل من 𝑥‪ 𝜕𝐿/𝜕𝐖ℎ‬و ‪. 𝜕𝐿/𝜕𝐖ℎℎ‬‬

‫‪9.7.3‬‬
‫االنتشار الخلفي عبر الزمن هو مجرد تطبيق االنتشار الخلفي لتسلسل النماذج ذات الحالة‬
‫المخفية‪ .‬هناك حاجة إلى االقتطاع ‪ Truncation‬من أجل الراحة الحسابية واالستقرار العددي‪،‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪224‬‬

‫‪randomized‬‬ ‫مثل االقتطاع المنتظم ‪ regular truncation‬واالقتطاع العشوائي‬


‫‪ . truncation‬يمكن أن تؤدي القوى العالية للمصفوفات إلى قيم ذاتية متباعدة أو متالشية‪.‬‬
‫يتجلى هذا في شكل تدرجات متفجرة أو متالشية‪ .‬للحساب الفعال ‪ ،‬يتم تخزين القيم الوسيطة‬
‫مؤقتًا أثناء االنتشار الخلفي عبر الوقت‪.‬‬

‫‪9.7.4‬‬
‫‪ .1‬افترض أن لدينا مصفوفة متماثلة 𝑛×𝑛‪ 𝐌 ∈ ℝ‬مع قيم ذاتية (‪𝜆𝑖 )eigenvalues‬‬
‫المتجهات الذاتية المقابلة لها هي (𝑛 ‪ .𝐯𝑖 )𝑖 = 1, … ,‬دون فقدان العمومية ‪ ،‬افترض‬
‫أنها مرتبة بالترتيب | ‪.|𝜆𝑖 | ≥ |𝜆𝑖+1‬‬
‫𝑖𝑘𝜆‬ ‫‪ .2‬أظهر أن 𝑘 𝐌 لديه قيم ذاتية ‪eigenvalues‬‬
‫‪ .3‬إثبت أنه بالنسبة إلى المتجه العشوائي 𝑛‪ ، 𝐱 ∈ ℝ‬مع وجود احتمال 𝐱 𝑘 𝐌 كبير ‪ ،‬سيتم‬
‫محاذاة إلى حد كبير مع المتجه الذاتي (‪ 𝐯1)eigenvector‬لـ𝐌 ‪ .‬إضف طابع رسيماً‬
‫على هذا البيان‪.‬‬
‫‪ .4‬ماذا تعني النتيجة أعاله للتدرجات في ‪RNNs‬؟‬
‫‪ .5‬إلى جانب قص التدرج ‪ ، gradient clipping‬هل يمكنك التفكير في أي طرق أخرى‬
‫للتعامل مع انفجار التدرج في الشبكات العصبية المتكررة ‪RNN‬؟‬
‫الشبكات العصبية المتكررة‬
‫الحديثة‬ ‫‪10‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪226‬‬

‫‪Modern‬‬ ‫‪10‬‬
‫‪Recurrent Neural Networks‬‬
‫قدم الفصل السابق األفكار الرئيسية وراء الشبكات العصبية المتكررة (‪ .)RNNs‬ومع ذلك‪،‬‬
‫تمامًا كما هو الحال مع الشبكات العصبية التالفيفية ‪ ،CNN‬كان هناك قدر هائل من االبتكاريف ‬
‫معماريات ‪ ،RNN‬وبلغت ذروتهايف العديد من التصميمات المعقدة التي أثبتت نجاحهايف ‬
‫الممارسة‪ .‬على وجه الخصوص‪ ،‬تتميز التصميمات األكثر شيوعًا بآليات للتخفيف من عدم‬
‫االستقرار العددي ‪ numerical instability‬السيئ السمعة الذي تواجهه ‪ ،RNNs‬كما يتجلى‬
‫في اختفاء التدرجات وانفجارها‪ .‬تذكر أننايف القسم ‪ 9‬تعاملنا مع انفجار التدرج من خالل تطبيق‬
‫استدالل قص متدرج حاد ‪ .gradient clipping heuristic‬على الرغم من فعالية هذا‬
‫االختراق‪ ،‬فإنه يترك مشكلة اختفاء التدرجات مفتوحة‪.‬‬

‫في هذا الفصل‪ ،‬نقدم األفكار الرئيسية وراء أنجح بُنى ‪ RNN‬للتسلسل‪ ،‬والتي تنبع من مقالتين‬
‫تم نشرهمايف عام ‪ .1997‬المقالة األولى‪ ،‬الذاكرة طويلة قصيرة المدى ‪Hochreiter ( LSTM‬‬
‫‪ ، ) 1997 ،and Schmidhuber‬تقدم خلية الذاكرة ‪ ،‬وهي وحدة الحساب التي تحل محل‬
‫العقد التقليديةيف الطبقة المخفية للشبكة‪ .‬باستخدام خاليا الذاكرة هذه‪ ،‬تكون الشبكات قادرة‬
‫على التغلب على صعوبات التدريب التي واجهتها الشبكات المتكررة السابقة‪ .‬حدسيًا‪ ،‬تتجنب‬
‫خلية الذاكرة مشكلة التدرج المتالشي عن طريق االحتفاظ بالقيميف الحالة الداخلية لكل خلية‬
‫ذاكرة متتالية على طول حافة متكررة بوزن ‪ 1‬عبر العديد من الخطوات الزمنية المتتالية‪ .‬تساعد‬
‫مجموعة من البوابات المضاعفة الشبكة على تحديد كل من المدخالت التي يجب السماح‬
‫بدخولهايف حالة الذاكرة‪ ،‬ومتى يجب أن يؤثر محتوى حالة الذاكرة على إخراج النموذج‪.‬‬

‫المقالة الثانية‪ ،‬الشبكات العصبية المتكررة ثنائية االتجاه ‪Bidirectional Recurrent‬‬


‫‪ ، )1997 ،Schuster and Paliwal( Neural Networks‬تقدم بُنية يتم فيها استخدام‬
‫المعلومات من كل من المستقبل (الخطوات الزمنية الالحقة) والماضي (الخطوات الزمنية‬
‫السابقة) لتحديد المخرجاتيف أي نقطةيف تسلسل‪ .‬هذا على عكس الشبكات السابقة‪ ،‬حيث‬
‫يمكن أن تؤثر المدخالت السابقة فقط على المخرجات‪ .‬أصبحت ‪ RNNs‬ثنائية االتجاه الدعامة‬
‫األساسية لمهام وضع العالمات التسلسليةيف معالجة اللغة الطبيعية‪ ،‬من بين مهام أخرى ال تعد‬
‫وال تحصى‪ .‬لحسن الحظ‪ ،‬ال يتعارض االبتكاران مع بعضهما البعض‪ ،‬وقد تم دمجهما بنجاح‬
‫لتصنيف الصوتيات ‪)2005 ،Graves and Schmidhuber ( phoneme classification‬‬
‫والتعرف على خط اليد ‪.)2008 ،Graves et al. ( handwriting recognition‬‬
‫‪227‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫ستشرح األقسام األولىيف هذا الفصل بُنية ‪ ،LSTM‬وهي نسخة أخف وزنًا تسمى الوحدة‬
‫المتكررة ذات البوابات ‪ ،)GRU( gated recurrent unit‬واألفكار الرئيسية وراء شبكات‬
‫‪ RNN‬ثنائية االتجاه وشرح موجز لكيفية تكديس طبقات ‪ RNN‬معًا لتكوين شبكات ‪RNN‬‬
‫عميقة‪ .‬بعد ذلك‪ ،‬سوف نستكشف تطبيق ‪RNNs‬يف مهام التسلسل إلى التسلسل‪ ،‬وإدخال‬
‫الترجمة اآللية جنبًا إلى جنب مع األفكار الرئيسية مثل معماريات المشفر ‪-‬مفكك الشفرة‬
‫‪ encoder-decoder architectures‬والبحث الشعاعي ‪.beam search‬‬

‫‪Long Short-Term LSTM‬‬ ‫‪10.1‬‬


‫‪Memory‬‬
‫بعد فترة وجيزة من تدريب أول ‪ RNNs‬على غرار ‪ Elman‬باستخدام االنتشار الخلفي‪،‬‬
‫(‪ ،)1990,Elman‬أصبحت مشاكل تعلم التبعيات طويلة المدى (بسبب التالشي واالنفجار‬
‫التدرجات) بارزة‪ ،‬حيث ناقش ‪ Bengio‬و ‪ Hochreiter‬المشكلة‪،)1994,Bengio et al.( ،‬‬
‫(‪ .)2001,Hochreiter et al.‬كان ‪ Hochreiter‬قد أوضح هذه المشكلةيف وقت مبكر من‬
‫أطروحة الماجستير عام ‪ ،1991‬على الرغم من أن النتائج لم تكن معروفة على نطاق واسع ألن‬
‫األطروحة كتبت باللغة األلمانية‪ .‬بينما يساعد قص التدرجيف انفجار التدرجات‪ ،‬يبدو أن التعامل‬
‫مع التدرجات المتالشية يتطلب حالً أكثر تفصيالً‪ .‬جاءت واحدة من أولى التقنيات وأكثرها‬
‫نجاحًا لمعالجة التدرجات المتالشيةيف شكل نموذج الذاكرة طويلة قصيرة المدى (‪)LSTM‬‬
‫بسبب ‪ .)1997( Hochreiter and Schmidhuber‬تشبه ‪ LSTM‬الشبكات العصبية‬
‫المتكررة ا لقياسية ولكن هنا يتم استبدال كل عقدة متكررة عادية بخلية ذاكرة ‪.memory cell‬‬
‫تحتوي كل خلية ذاكرة على حالة داخلية ‪ ،internal state‬أي عقدة ذات حافة متكررة متصلة‬
‫ذاتيًا بوزن ثابت ‪ ،1‬مما يضمن أن التدرج يمكن أن يمر عبر العديد من الخطوات الزمنية دون أن‬
‫يتالشى أو ينفجر‪.‬‬

‫يأتي مصطلح "الذاكرة طويلة قصيرة المدى" من الحدس التالي‪ .‬تمتلك الشبكات العصبية‬
‫المتكررة البسيطة ذاكرة طويلة المدى على شكل أوزان‪ .‬تتغير األوزان ببطء أثناء التدريب‪ ،‬مما‬
‫يؤدي إلى ترميز المعرفة العامة حول البيانات‪ .‬لديهم أيضًا ذاكرة قصيرة المدىيف شكل عمليات‬
‫تنشيط سريعة الزوال‪ ،‬والتي تنتقل من كل عقدة إلى عقد متتالية‪ .‬يقدم نموذج ‪ LSTM‬نوعًا‬
‫وسيطًا للتخزين عبر خلية الذاكرة‪ .‬خلية الذاكرة هي وحدة مركبة‪ ،‬مبنية من عقد أبسطيف نمط‬
‫اتصال محدد‪ ،‬مع تضمين جديد للعقد المضاعفة‪.‬‬

‫‪Gated Memory Cell‬‬ ‫‪10.1.1‬‬


‫تم تجهيز كل خلية ذاكرة بحالة داخلية ‪ internal state‬وعدد من البوابات المضاعفة‬
‫‪ multiplicative gates‬التي تحدد ما إذا كان (‪ )1‬إدخال معين يجب أن يؤثر على الحالة‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪228‬‬

‫الداخلية (بوابة اإلدخال)‪ )2( ،‬يجب مسح الحالة الداخلية إلى (بوابة النسيان ‪ ،)forget gate‬و‬
‫(‪ ) 3‬يجب السماح للحالة الداخلية للخاليا العصبية بالتأثير على ناتج الخلية (بوابة اإلخراج‬
‫‪.)output gate‬‬

‫‪Gated Hidden State‬‬ ‫‪10.1.1.1‬‬


‫الفرق الرئيسي بين ‪ vanilla RNNs‬و‪ LSTMs‬هو أن األخير يدعم الحالة المخفية ذات‬
‫البوابات ‪ .Gated Hidden State‬هذا يعني أن لدينا آليات مخصصة لتحديد متى يجب‬
‫تحديث حالة مخفية وأيضًا متى يجب إعادة تعيينها ‪ .reset‬يتم تعلم هذه اآلليات وهي تتناول‬
‫المخاوف المذكورة أعاله‪ .‬على سبيل المثال‪ ،‬إذا كان الرمز ‪ token‬األول ذا أهمية كبيرة‪ ،‬فسوف‬
‫نتعلم عدم تحديث الحالة المخفية بعد المالحظة األولى‪ .‬وبالمثل‪ ،‬سوف نتعلم تخطي‬
‫المالحظات المؤقتة غير ذات الصلة‪ .‬أخيرًا‪ ،‬سوف نتعلم إعادة ضبط الحالة الكامنة عند الحاجة‪.‬‬
‫نناقش هذا بالتفصيل أدناه‪.‬‬

‫الشكل ‪ 10.1.1‬حساب بوابة اإلدخال وبوابة النسيان وبوابة اإلخراجيف نموذج ‪.LSTM‬‬

‫‪Input Gate, Forget Gate,‬‬ ‫‪10.1.1.2‬‬


‫‪and Output Gate‬‬
‫تغذية البيانات ‪data feeding‬يف بوابات ‪ LSTM‬هي المدخالتيف الخطوة الزمنية الحالية‬
‫والحالة المخفية للخطوة الزمنية السابقة‪ ،‬كما هو موضحيف الشكل ‪ .1.1.10‬ثالث طبقات متصلة‬
‫بالكامل مع دوال التنشيط ‪ sigmoid‬تحسب قيم بوابات اإلدخال والنسيان واإلخراج‪ .‬نتيجة‬
‫للتنشيط ‪ ،sigmoid‬تقع جميع قيم البوابات الثالثةيف نطاق‪ .‬باإلضافة إلى ذلك‪ ،‬نحتاج إلى عقدة‬
‫إدخال ‪ ،input node‬يتم حسابها عادةً بدالة تنشيط ‪ .tanh‬حدسيًا‪ ،‬تحدد بوابة اإلدخال ‪input‬‬
‫‪ gate‬مقدار قيمة عقدة اإلدخال التي يجب إضافتها إلى الحالة الداخلية لخلية الذاكرة الحالية‪.‬‬
‫تحدد بوابة النسيان ‪ forget gate‬ما إذا كنت تريد االحتفاظ بالقيمة الحالية للذاكرة أو مسحها‪.‬‬
‫‪229‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫وتحدد بوابة اإلخراج ‪ output gate‬ما إذا كان يجب أن تؤثر خلية الذاكرة على اإلخراجيف الخطوة‬
‫الزمنية الحالية‪.‬‬

‫رياضيًا‪ ،‬افترض أن هناك وحدات مخفية ‪ ، ℎ‬وحجم الدُفعة 𝑛 ‪ ،‬وعدد المدخالت 𝑑‪ .‬وبالتالي‪،‬‬
‫يكون اإلدخال 𝑑×𝑛‪ 𝐗 𝑡 ∈ ℝ‬والحالة المخفية للخطوة الزمنية السابقة هي ‪.𝐇𝑡−1 ∈ ℝ𝑛×ℎ‬يف ‬
‫المقابل‪ ،‬يتم تعريف البواباتيف الخطوة الزمنية 𝑡 على النحو التالي‪ :‬بوابة اإلدخال هي ∈ 𝑡𝐈‬
‫‪ ، ℝ𝑛×ℎ‬وبوابة النسيان ‪ ، 𝐅𝑡 ∈ ℝ𝑛×ℎ‬وبوابة اإلخراج هي ‪ .𝐎𝑡 ∈ ℝ𝑛×ℎ‬يتم حسابها على النحو‬
‫التالي‪:‬‬

‫𝑡𝐈‬ ‫‪= 𝜎(𝐗 𝑡 𝐖𝑥𝑖 + 𝐇𝑡−1 𝐖ℎ𝑖 + 𝐛𝑖 ),‬‬


‫𝑡𝐅‬ ‫‪= 𝜎(𝐗 𝑡 𝐖𝑥𝑓 + 𝐇𝑡−1 𝐖ℎ𝑓 + 𝐛𝑓 ),‬‬
‫𝑡𝐎‬ ‫‪= 𝜎(𝐗 𝑡 𝐖𝑥𝑜 + 𝐇𝑡−1 𝐖ℎ𝑜 + 𝐛𝑜 ),‬‬

‫هي معلمات الوزن و‬ ‫حيث ‪ 𝐖𝑥𝑖 , 𝐖𝑥𝑓 , 𝐖𝑥𝑜 ∈ ℝ𝑑×ℎ‬و ‪𝐖ℎ𝑖 , 𝐖ℎ𝑓 , 𝐖ℎ𝑜 ∈ ℝℎ×ℎ‬‬
‫‪ 𝐛𝑖 , 𝐛𝑓 , 𝐛𝑜 ∈ ℝ1×ℎ‬هي معلمات التحيز‪ .‬الحظ أن البث ‪( broadcasting‬انظر القسم ‪)2.1.4‬‬
‫يتم تشغيله أثناء عملية الجمع‪ .‬نحن نستخدم دوال ‪( sigmoid‬كما هو مقدميف القسم ‪)5.1‬‬
‫لتعيين قيم اإلدخال إلى الفاصل الزمني )‪.(0,1‬‬

‫الشكل ‪ 10.1.2‬حساب عقدة اإلدخاليف نموذج ‪.LSTM‬‬

‫‪Input Node‬‬ ‫‪10.1.1.3‬‬


‫بعد ذلك نقوم بتصميم خلية الذاكرة ‪ .memory cell‬نظرًا ألننا لم نحدد عمل البوابات المختلفة‬
‫~‬
‫بعد‪ ،‬فإننا نقدم أوالً عقدة اإلدخال (‪ .𝐂𝑡 ∈ ℝ𝑛×ℎ )Input Node‬يتشابه حسابها مع حساب‬
‫البوابات الثالثة الموضحة أعاله‪ ،‬ولكن باستخدام دالة ذات قيم نطاق )‪ (−1,1‬لدالة التنشيط‪.‬‬
‫هذا يؤدي إلى المعادلة التاليةيف الخطوة الزمنية 𝑡‬
‫~‬
‫‪𝐂𝑡 = tanh(𝐗 𝑡 𝐖𝑥𝑐 + 𝐇𝑡−1 𝐖ℎ𝑐 + 𝐛𝑐 ),‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪230‬‬

‫حيث ‪ 𝐖𝑥𝑐 ∈ ℝ𝑑×ℎ‬و ‪ 𝐖ℎ𝑐 ∈ ℝℎ×ℎ‬هي معلمات الوزن و ‪ 𝐛𝑐 ∈ ℝ1×ℎ‬هي معلمة تحيز‪.‬‬

‫يظهر توضيح سريع لعقدة اإلدخاليف الشكل ‪.10.1.2‬‬

‫‪Memory Cell Internal State‬‬ ‫‪10.1.1.4‬‬


‫في ‪ ،LSTMs‬تتحكم بوابة اإلدخال 𝑡𝐈يف مقدار البيانات الجديدة التي نأخذهايف االعتبار عن‬
‫~‬
‫طريق 𝑡𝐂وتعالج بوابة النسيان 𝑡𝐅 مقدار الحالة الداخلية ‪ 𝐂𝑡−1 ∈ ℝ𝑛×ℎ‬للخلية القديمة التي‬
‫نحتفظ بها‪ .‬باستخدام عامل ضرب هادامار )‪، ⊙ Hadamard (elementwise‬نصل إلى‬
‫معادلة التحديث التالية‪:‬‬
‫~‬
‫‪𝐂𝑡 = 𝐅𝑡 ⊙ 𝐂𝑡−1 + 𝐈𝑡 ⊙ 𝐂𝑡 .‬‬

‫إذا كانت بوابة النسيان دائمًا ‪ 1‬وكانت بوابة اإلدخال دائمًا ‪ ،0‬فستظل الحالة الداخلية ‪ 𝐂𝑡−1‬لخلية‬
‫الذاكرة ثابتة إلى األبد‪ ،‬وستمر دون تغييريف كل خطوة زمنية الحقة‪ .‬ومع ذلك‪ ،‬فإن بوابات اإلدخال‬
‫ونسيان البوابات تمنح النموذج المرونة لتعلم متى يجب الحفاظ على هذه القيمة دون تغيير ومتى‬
‫تشوشها استجابةً للمدخالت الالحقة‪.‬يف الممارسة العملية‪ ،‬يخفف هذا التصميم من مشكلة‬
‫التدرج المتالشي‪ ،‬مما ينتج عنه نماذج يسهل تدريبها كثيرًا‪ ،‬خاصةً عند مواجهة مجموعات‬
‫البيانات ذات أطوال التسلسل الطويل‪.‬‬

‫وهكذا نصل إلى مخطط التدفق ‪flow diagram‬يف الشكل ‪.10.1.3‬‬

‫الشكل ‪ 10.1.3‬حساب الحالة الداخلية لخلية الذاكرةيف نموذج ‪.LSTM‬‬

‫‪Hidden State‬‬ ‫‪10.1.1.5‬‬


‫أخيرًا‪ ،‬نحتاج إلى تحديد كيفية حساب إخراج خلية الذاكرة‪ ،‬أي الحالة المخفية ( ‪hidden‬‬
‫‪ ،𝐇𝑡 ∈ ℝ𝑛×ℎ )state‬كما تراها الطبقات األخرى‪ .‬هذا هو المكان الذي يتم فيه تشغيل بوابة‬
‫‪231‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫اإلخراج‪ .‬يف ‪ ،LSTMs‬نطبق أوالً على الحالة الداخلية لخلية الذاكرة ثم نطبق ضرب نقطي أخر‪،‬‬
‫هذه المرة باستخدام بوابة اإلخراج‪ .‬هذا يضمن أن تكون قيم 𝑡𝐇 دائمًايف الفاصل الزمني )‪:(−1,1‬‬

‫‪𝐇𝑡 = 𝐎𝑡 ⊙ tanh (𝐂𝑡 ).‬‬

‫عندما تكون بوابة اإلخراج قريبة من ‪ ،1‬فإننا نسمح للحالة الداخلية لخلية الذاكرة بالتأثير على‬
‫الطبقات الالحقة غير المحظورة‪ ،‬بينما بالنسبة لقيم بوابة اإلخراج القريبة من ‪ ،0‬فإننا نمنع الذاكرة‬
‫الحالية من التأثير على الطبقات األخرى للشبكةيف الخطوة الزمنية الحالية‪ .‬الحظ أن خلية الذاكرة‬
‫يمكنها تجميع المعلومات عبر العديد من الخطوات الزمنية دون التأثير على بقية الشبكة (طالما‬
‫أن بوابة اإلخراج تأخذ قيمًا قريبة من ‪ ،)0‬ثم تؤثر فجأة على الشبكةيف خطوة زمنية الحقة بمجرد‬
‫بوابة اإلخراج تقلب من قيم قريبة من ‪ 0‬إلى قيم قريبة من ‪.1‬‬

‫يحتوي الشكل ‪ 10.1.4‬على رسم توضيحي لتدفق البيانات‪.‬‬

‫الشكل ‪ 10.1.4‬حساب الحالة المخفيةيف نموذج ‪.LSTM‬‬

‫‪Implementation from Scratch‬‬ ‫‪10.1.2‬‬


‫اآلن دعونا ننفذ ‪ LSTM‬من البداية‪ .‬مثل التجاربيف القسم ‪ ،9.5‬نقوم أوالً بتحميل مجموعة‬
‫بيانات ‪.The Time Machine‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Initializing Model Parameters‬‬ ‫‪10.1.2.1‬‬
‫بعد ذلك‪ ،‬نحتاج إلى تحديد وتهيئة معلمات النموذج‪ .‬كمايف السابق‪ ،‬يحدد المعامل الفائق‬
‫‪ num_hiddens‬عدد الوحدات المخفية‪ .‬نقوم بتهيئة األوزان بعد توزيع ‪ Gaussian‬مع‬
‫انحراف معياري ‪ ،0.01‬وقمنا بتعيين التحيزات على ‪.0‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 232

class LSTMScratch(d2l.Module): #@save


def __init__(self, num_inputs, num_hiddens,
sigma=0.01):
super().__init__()
self.save_hyperparameters()

init_weight = lambda *shape:


tf.Variable(tf.random.normal(shape) * sigma)
triple = lambda: (init_weight(num_inputs,
num_hiddens),
init_weight(num_hiddens,
num_hiddens),

tf.Variable(tf.zeros(num_hiddens)))

self.W_xi, self.W_hi, self.b_i = triple() #


Input gate
self.W_xf, self.W_hf, self.b_f = triple() #
Forget gate
self.W_xo, self.W_ho, self.b_o = triple() #
Output gate
self.W_xc, self.W_hc, self.b_c = triple() #
Input node
‫ الحظ‬.‫ ويتألف من ثالث بوابات وعقدة إدخال‬،‫يتم تعريف النموذج الفعلي كما هو موضح أعاله‬
.‫أنه يتم تمرير الحالة المخفية فقط إلى طبقة اإلخراج‬

@d2l.add_to_class(LSTMScratch)
def forward(self, inputs, H_C=None):
H, C = None, None if H_C is None else H_C
outputs = []
for X in inputs:
I = tf.sigmoid(tf.matmul(X, self.W_xi) + (
tf.matmul(H, self.W_hi) if H is not None
else 0) + self.b_i)
if H is None:
H, C = tf.zeros_like(I), tf.zeros_like(I)
F = tf.sigmoid(tf.matmul(X, self.W_xf) +
tf.matmul(H, self.W_hf) +
self.b_f)
O = tf.sigmoid(tf.matmul(X, self.W_xo) +
tf.matmul(H, self.W_ho) +
self.b_o)
233 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

C_tilde = tf.tanh(tf.matmul(X, self.W_xc) +


tf.matmul(H, self.W_hc) +
self.b_c)
C = F * C + I * C_tilde
H = O * tf.tanh(C)
outputs.append(H)
return outputs, (H, C)
Training and Prediction 10.1.2.2
‫كما هو موضحيف‬RNNLMScratch ‫ عن طريق إنشاء مثيل لفئة‬LSTM ‫دعنا ندرب نموذج‬
.9.5 ‫القسم‬

data = d2l.TimeMachine(batch_size=1024, num_steps=32)


with d2l.try_gpu():
lstm = LSTMScratch(num_inputs=len(data.vocab),
num_hiddens=32)
model = d2l.RNNLMScratch(lstm,
vocab_size=len(data.vocab), lr=4)
trainer = d2l.Trainer(max_epochs=50,
gradient_clip_val=1)
trainer.fit(model, data)

Concise Implementation 10.1.3


LSTM ‫ يمكننا إنشاء نموذج‬،API ‫باستخدام واجهات برمجة التطبيقات عالية المستوى‬
‫ الكود أسرع بشكل ملحوظ‬.‫ هذا يلخص جميع تفاصيل التكوين التي أوضحناها أعاله‬.ً‫مباشرة‬
.‫ألنه يستخدم عوامل مجمعة بدالً من بايثون للعديد من التفاصيل التي أوضحناها من قبل‬

class LSTM(d2l.RNN):
def __init__(self, num_hiddens):
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 234

d2l.Module.__init__(self)
self.save_hyperparameters()
self.rnn = tf.keras.layers.LSTM(
num_hiddens, return_sequences=True,
return_state=True, time_major=True)

def forward(self, inputs, H_C=None):


outputs, *H_C = self.rnn(inputs, H_C)
return outputs, H_C

lstm = LSTM(num_hiddens=32)
with d2l.try_gpu():
model = d2l.RNNLM(lstm, vocab_size=len(data.vocab),
lr=4)
trainer.fit(model, data)

model.predict('it has', 20, data.vocab)


'it has the the the the the'

.‫ هي النموذج األولي الكامن المتغير االنحدار التلقائي مع التحكميف الحالة غير البديهية‬LSTM
multiple ‫ طبقات متعددة‬،‫ على سبيل المثال‬،‫تم اقتراح العديد من المتغيرات على مر السنين‬
‫ فإن‬،‫ ومع ذلك‬.‫ أنواع مختلفة من التنظيم‬،residual connections ‫ وصالت متبقية‬،layers
‫) مكلف للغاية بسبب التبعية طويلة‬GRUs ‫ ونماذج التسلسل األخرى (مثل‬LSTMs ‫تدريب‬
‫ الحقًا سنواجه نماذج بديلة مثل المحوالت‬.‫ للتسلسل‬long range dependency ‫المدى‬
.‫ التي يمكن استخدامهايف بعض الحاالت‬transformers
‫‪235‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪10.1.4‬‬

‫بينما تم نشر ‪LSTMs‬يف عام ‪ ،1997‬فقد برزت بشكل أكبر مع بعض االنتصاراتيف مسابقات‬
‫التنبؤيف منتصف العقد األول من القرن الحادي والعشرين‪ ،‬وأصبحت النماذج السائدة للتعلم‬
‫المتسلسل من عام ‪ 2011‬حتى وقت قريب مع ظهور نماذج المحوالت ‪transformer‬‬
‫‪ ،models‬بدءًا من عام ‪ .2017‬حتى مخترعي المحوالت يدينون ببعض أفكارهم الرئيسية‬
‫البتكارات التصميم المعماري التي قدمتها ‪ .LSTM‬تحتوي ‪ LSTM‬على ثالثة أنواع من‬
‫البوابات‪ :‬بوابات اإلدخال ‪ input gates‬وبوابات النسيان ‪ forget gates‬وبوابات اإلخراج‬
‫‪ output gates‬التي تتحكميف تدفق المعلومات‪ .‬يتضمن إخراج الطبقة المخفية لـ ‪LSTM‬‬
‫الحالة المخفية والحالة الداخلية لخلية الذاكرة‪ .‬يتم تمرير الحالة المخفية فقط إلى طبقة اإلخراج‬
‫بينما تكون الحالة الداخلية لخلية الذاكرة داخلية بالكامل‪ .‬يمكن أن تخفف ‪ LSTMs‬من التالشي‬
‫وانفجار التدرجات‪.‬‬

‫‪10.1.5‬‬
‫‪ .1‬اضبط المعلمات الفائقة وحلل تأثيرها على وقت التشغيل واالرتباك وتسلسل اإلخراج‪.‬‬
‫‪ .2‬كيف ستحتاج إلى تغيير النموذج لتوليد كلمات مناسبة بدالً من تسلسل األحرف؟‬
‫‪ .3‬قارن التكلفة الحسابية لـ ‪ GRUs‬و ‪ LSTMs‬و ‪ RNNs‬العادية لبُعد مخفي معين‪.‬‬
‫قم بإيالء اهتمام خاص لتكلفة التدريب واالستدالل‪.‬‬
‫‪ .4‬نظرًا ألن خلية الذاكرة المرشحة تضمن أن نطاق القيمة يقع بين ‪ −1‬و ‪ 1‬باستخدام‬
‫الدالة ‪ ، tanh‬فلماذا تحتاج الحالة المخفية إلى استخدام الدالة مرة أخرى للتأكد من‬
‫أن نطاق قيمة اإلخراج يقع بين ‪ −1‬و‪ 1‬؟‬
‫‪ .5‬نفذ نموذج ‪ LSTM‬لتنبؤ السالسل الزمنية بدالً من توقع تسلسل األحرف‪.‬‬

‫‪Gated Recurrent GRU‬‬ ‫‪10.2‬‬


‫‪Units‬‬
‫نظرًا ألن ‪ RNNs‬وخاصة بنية ‪( LSTM‬القسم ‪ )10.1‬اكتسبت شعبية بسرعة خالل ‪،2010‬‬
‫بدأ عدد من المقاالتيف تجربة ال ُب نى المبسطة على أمل االحتفاظ بالفكرة الرئيسية لدمج آليات‬
‫البوابة الداخلية ‪ internal state‬والحالة المضاعفة ‪ multiplicative gating‬ولكن بهدف‬
‫إسراع الحساب‪ .‬قدمت الوحدة المتكررة ذات البوابات ‪The gated recurrent unit‬‬
‫)‪ )2014 ،Cho et al.( (GRU‬نسخة مبسطة من خلية ذاكرة ‪ LSTM‬التي تحقق غالبًا أداءً‬
‫مشابهًا ولكن مع ميزة كونها أسرعيف الحساب (‪.)2014 ،Chung et al.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪236‬‬

‫‪Reset Gate and Update Gate‬‬ ‫‪10.2.1‬‬


‫هنا‪ ،‬يتم استبدال بوابات ‪ LSTM‬الثالثة بوابتين‪ :‬بوابة إعادة الضبط ‪ reset gate‬وبوابة التحديث‬
‫‪ .update gate‬كما هو الحال مع ‪ ،LSTMs‬تُعطى هذه البوابات تنشيطات ‪ ،sigmoid‬مما يجبر‬
‫قيمها على الوقوعيف الفاصل الزمني)‪ .(0,1‬بشكل حدسي‪ ،‬تتحكم بوابة إعادة الضبطيف مقدار‬
‫الحالة السابقة التي قد ال نزال نريد تذكرها‪ .‬وبالمثل‪ ،‬ستسمح لنا بوابة التحديث بالتحكميف مدى‬
‫كون الحالة الجديدة مجرد نسخة من الحالة القديمة‪ .‬يوضح الشكل ‪ 10.2.1‬المدخالت لكل‬
‫من بوابات إعادة الضبط والتحديثيف ‪ ،GRU‬بالنظر إلى مدخالت الخطوة الزمنية الحالية‬
‫والحالة المخفية للخطوة الزمنية السابقة‪ .‬يتم إعطاء مخرجات بوابتين بواسطة طبقتين متصلتين‬
‫بالكامل بدالة التنشيط ‪.sigmoid‬‬

‫الشكل ‪ 10.2.1‬حساب بوابة إعادة الضبط وبوابة التحديثيف نموذج ‪.GRU‬‬

‫رياضيًا‪ ،‬لخطوة زمنية معينة 𝑡 ‪ ،‬افترض أن اإلدخال عبارة عن عدد من الدفعات الصغيرة ∈ 𝑡 𝐗‬
‫𝑑×𝑛‪ :ℝ‬عدد األمثلة‪، 𝑛:‬عدد المدخالت‪ ) 𝑑 :‬والحالة المخفية للخطوة الزمنية السابقة هي‬
‫‪( 𝐇𝑡−1 ∈ ℝ𝑛×ℎ‬عدد الوحدات المخفية‪ .) ℎ:‬بعد ذلك‪ ،‬يتم حساب بوابة إعادة التعيين ∈ 𝑡 𝐑‬
‫‪ ℝ𝑛×ℎ‬وبوابة التحديث ‪ 𝐙𝑡 ∈ ℝ𝑛×ℎ‬على النحو التالي‪:‬‬

‫‪𝐑 𝑡 = 𝜎(𝐗 𝑡 𝐖𝑥𝑟 + 𝐇𝑡−1 𝐖ℎ𝑟 + 𝐛𝑟 ),‬‬


‫‪𝐙𝑡 = 𝜎(𝐗 𝑡 𝐖𝑥𝑧 + 𝐇𝑡−1 𝐖ℎ𝑧 + 𝐛𝑧 ),‬‬

‫حيث ‪ 𝐖𝑥𝑟 , 𝐖𝑥𝑧 ∈ ℝ𝑑×ℎ‬و ‪ 𝐖ℎ𝑟 , 𝐖ℎ𝑧 ∈ ℝℎ×ℎ‬هي معلمات الوزن و ‪𝐛𝑟 , 𝐛𝑧 ∈ ℝ1×ℎ‬‬
‫هي معلمات التحيز‪.‬‬
‫‪237‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪Candidate Hidden State‬‬ ‫‪10.2.2‬‬


‫بعد ذلك‪ ،‬نقوم بدمج بوابة إعادة الضبط 𝑡 𝐑 بآلية التحديث المنتظمة ‪regular updating‬‬
‫~‬
‫‪mechanism‬يف (‪ ،)9.4.5‬مما يؤدي إلى الحالة المخفية ‪ 𝐇𝑡 ∈ ℝ𝑛×ℎ‬للمرشح ‪candidate‬‬
‫التالييف الخطوة الزمنية 𝑡‪:‬‬
‫~‬
‫‪𝐇𝑡 = tanh (𝐗 𝑡 𝐖𝑥ℎ + (𝐑 𝑡 ⊙ 𝐇𝑡−1 )𝐖ℎℎ + 𝐛ℎ ),‬‬ ‫(‪)10.2.2‬‬

‫حيث ‪ 𝐖𝑥ℎ ∈ ℝ𝑑×ℎ‬و ‪ 𝐖ℎℎ ∈ ℝℎ×ℎ‬هي معلمات الوزن‪ 𝐛ℎ ∈ ℝ1×ℎ ،‬هو التحيز‪ ،‬والرمز‬
‫⊙ هو عامل ضرب ‪( Hadamard‬بشكل عنصري ‪ .)elementwise‬هنا نستخدم دالة تنشيط‬
‫‪.tanh‬‬

‫والنتيجة مرشح ‪ ،candidate‬ألننا ما زلنا بحاجة إلى دمج عمل بوابة التحديث‪ .‬بالمقارنة مع‬
‫(‪ ،)9.4.5‬يمكن اآلن تقليل تأثير الحاالت السابقة مع الضرب األولي لـ 𝑡 𝐑 و ‪ 𝐇𝑡−1‬يف ‬
‫(‪ .)10.2.2‬عندما تكون اإلدخاالتيف بوابة إعادة الضبط 𝑡 𝐑 قريبة من ‪ ،1‬فإننا نسترد ‪vanilla‬‬
‫‪ RNN‬كمايف (‪ .)9.4.5‬بالنسبة لجميع إدخاالت بوابة إعادة الضبط 𝑡 𝐑 القريبة من ‪ ،0‬تكون‬
‫حالة المرشح المخفية نتيجة ‪ MLP‬مع إدخال 𝑡 𝐗‪ .‬وبالتالي يتم إعادة تعيين ‪ reset‬أي حالة‬
‫مخفية موجودة مسبقًا إلى اإلعدادات االفتراضية‪.‬‬

‫يوضح الشكل ‪ 10.2.2‬التدفق الحسابي بعد تطبيق بوابة إعادة الضبط ‪.reset gate‬‬

‫الشكل ‪ 10.2.2‬حساب الحالة المخفية المرشحةيف نموذج ‪.GRU‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪238‬‬

‫‪Hidden State‬‬ ‫‪10.2.3‬‬


‫أخيرًا‪ ،‬نحتاج إلى دمج تأثير بوابة التحديث 𝑡𝐙‪ .‬يحدد هذا إلى أي مدى تتطابق الحالة المخفية‬
‫الجديدة ‪ 𝐇𝑡 ∈ ℝ𝑛×ℎ‬مع الحالة القديمة ‪ 𝐇𝑡−1‬مقابل مدى تشابهها مع الحالة الجديدة‬
‫~‬
‫المرشحة 𝑡𝐇‪ .‬يمكن استخدام بوابة التحديث 𝑡𝐙 لهذا الغرض‪ ،‬وذلك ببساطة عن طريق أخذ‬
‫~‬
‫مجموعات محدبة عنصرية من ‪ 𝐇𝑡−1‬و 𝑡𝐇 ‪ .‬هذا يؤدي إلى معادلة التحديث النهائية لـ ‪:GRU‬‬
‫~‬
‫‪𝐇𝑡 = 𝐙𝑡 ⊙ 𝐇𝑡−1 + (1 − 𝐙𝑡 ) ⊙ 𝐇𝑡 .‬‬

‫عندما تكون بوابة التحديث 𝑡𝐙 قريبة من ‪ ،1‬فإننا ببساطة نحتفظ بالحالة القديمة‪.‬يف هذه الحالة‪،‬‬
‫يتم تجاهل المعلومات الواردة من 𝑡 𝐗 ‪ ،‬مما يؤدي بشكل فعال إلى تخطي الخطوة الزمنية 𝑡يف ‬
‫سلسلة التبعية‪.‬يف المقابل‪ ،‬عندما تكون 𝑡𝐙 قريبة من ‪ ،0‬تقترب الحالة الكامنة الجديدة 𝑡𝐇 من‬
‫~‬
‫الحالة الكامنة المرشحة 𝑡𝐇‪ .‬يوضح الشكل ‪ 10.2.3‬التدفق الحسابي بعد تشغيل بوابة التحديث‪.‬‬

‫الشكل ‪ 10.2.3‬حساب الحالة المخفيةيف نموذج ‪.GRU‬‬

‫باختصار‪ ،‬تمتلك ‪ GRU‬السمتين المميزتين التاليتين‪:‬‬

‫تساعد بوابات إعادة الضبط ‪ Reset gates‬تعيين البوابات في التقاط التبعيات قصيرة‬ ‫•‬
‫المدى في التسلسل‪.‬‬
‫تساعد بوابات التحديث ‪ Update gates‬على التقاط التبعيات طويلة المدى في‬ ‫•‬
‫التسلسل‪.‬‬

‫‪Implementation from Scratch‬‬ ‫‪10.2.3.1‬‬


‫للحصول على فهم أفضل لنموذج ‪ ،GRU‬دعنا نطبقه من البداية‪.‬‬
239 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

import tensorflow as tf
from d2l import tensorflow as d2l
Initializing Model Parameters 10.2.4
‫ نرسم األوزان من توزيع غاوسي مع االنحراف‬.‫الخطوة األولى هي تهيئة معلمات النموذج‬
‫ عدد‬num_hiddens ‫ يحدد المعامل الفائق‬.0 ‫ونضبط التحيز على‬sigma ‫المعياري ليكون‬
‫ نقوم بإنشاء جميع األوزان والتحيزات المتعلقة ببوابة التحديث وبوابة إعادة‬.‫الوحدات المخفية‬
.‫الضبط والحالة المخفية المرشحة‬

class GRUScratch(d2l.Module):
def __init__(self, num_inputs, num_hiddens,
sigma=0.01):
super().__init__()
self.save_hyperparameters()

init_weight = lambda *shape:


tf.Variable(tf.random.normal(shape) * sigma)
triple = lambda: (init_weight(num_inputs,
num_hiddens),
init_weight(num_hiddens,
num_hiddens),

tf.Variable(tf.zeros(num_hiddens)))

self.W_xz, self.W_hz, self.b_z = triple() #


Update gate
self.W_xr, self.W_hr, self.b_r = triple() #
Reset gate
self.W_xh, self.W_hh, self.b_h = triple() #
Candidate hidden state
Defining the Model 10.2.5
RNN ‫ هيكلها هو نفسه هيكل خلية‬.‫ األمامي‬GRU ‫اآلن نحن جاهزون لتعريف حساب‬
.‫ فيما عدا أن معادالت التحديث أكثر تعقيدًا‬،‫األساسية‬

@d2l.add_to_class(GRUScratch)
def forward(self, inputs, H=None):
matmul_H = lambda A, B: tf.matmul(A, B) if H is not
None else 0
outputs = []
for X in inputs:
Z = tf.sigmoid(tf.matmul(X, self.W_xz) + (
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 240

tf.matmul(H, self.W_hz) if H is not None


else 0) + self.b_z)
if H is None: H = tf.zeros_like(Z)
R = tf.sigmoid(tf.matmul(X, self.W_xr) +
tf.matmul(H, self.W_hr) +
self.b_r)
H_tilde = tf.tanh(tf.matmul(X, self.W_xh) +
tf.matmul(R * H, self.W_hh) +
self.b_h)
H = Z * H + (1 - Z) * H_tilde
outputs.append(H)
return outputs, (H, )
Training 10.2.6
‫ بالطريقة نفسها تمامًا‬The Time Machine ‫يعمل تدريب نموذج لغوي على مجموعة بيانات‬
.9.5 ‫كمايف القسم‬

data = d2l.TimeMachine(batch_size=1024, num_steps=32)


with d2l.try_gpu():
gru = GRUScratch(num_inputs=len(data.vocab),
num_hiddens=32)
model = d2l.RNNLMScratch(gru,
vocab_size=len(data.vocab), lr=4)
trainer = d2l.Trainer(max_epochs=50,
gradient_clip_val=1)
trainer.fit(model, data)
241 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

Concise Implementation 10.2.6.1


‫ هذا‬.ً‫ مباشرة‬GPU ‫ يمكننا إنشاء نموذج‬،API ‫في واجهات برمجة التطبيقات عالية المستوى‬
.‫يلخص كل تفاصيل التكوين التي أوضحناها أعاله‬

class GRU(d2l.RNN):
def __init__(self, num_inputs, num_hiddens):
d2l.Module.__init__(self)
self.save_hyperparameters()
self.rnn = tf.keras.layers.GRU(num_hiddens,
return_sequences=True,

return_state=True)
.‫ بدالً من بايثون‬compiled operators ‫الكود أسرعيف التدريب ألنه يستخدم عوامل مترجمة‬

gru = GRU(num_inputs=len(data.vocab), num_hiddens=32)


with d2l.try_gpu():
model = d2l.RNNLM(gru, vocab_size=len(data.vocab),
lr=4)
trainer.fit(model, data)

‫يف مجموعة التدريب والتسلسل المتوقع‬perplexity ‫ نقوم بطباعة االرتباك‬،‫بعد التدريب‬


.‫ بعد البادئة المقدمة‬predicted sequence

model.predict('it has', 20, data.vocab)


'it has the the the the the'
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪242‬‬

‫‪10.2.6.2‬‬
‫مقارنةً بـ ‪ ،LSTMs‬تحقق وحدات ‪ GRU‬أداءً مشابهًا ولكنها تميل إلى أن تكون أخف من‬
‫الناحية الحسابية‪ .‬بشكل عام‪ ،‬مقارنةً بـ ‪ RNNs‬البسيطة‪ ،‬يمكن لـ ‪ RNNs‬ذات البوابات مثل‬
‫‪ LSTMs‬و‪ GRUs‬التقاط التبعيات بشكل أفضل للتسلسالت ذات مسافات الخطوة الزمنية‬
‫الكبيرة‪ .‬تحتوي وحدات ‪ GRU‬على ‪ RNNs‬األساسية كحالة قصوى عند تشغيل بوابة إعادة‬
‫التعيين ‪ .reset gate‬يمكنهم أيضًا تخطي التكرارات الالحقة عن طريق تشغيل بوابة التحديث‬
‫‪.update gate‬‬

‫‪10.2.6.3‬‬
‫‪′‬‬
‫‪ .1‬افترض أننا نريد فقط استخدام اإلدخال في الخطوة الزمنية 𝑡 للتنبؤ باإلخراج في‬
‫الخطوة الزمنية ‪ .𝑡 > 𝑡 ′‬ما هي أفضل القيم لبوابات إعادة التعيين والتحديث لكل خطوة‬
‫زمنية؟‬
‫‪ .2‬اضبط المعلمات الفائقة وحلل تأثيرها على وقت التشغيل واالرتباك وتسلسل اإلخراج‪.‬‬
‫‪ .3‬قارن بين وقت التشغيل واالرتباك وسالسل اإلخراج لتطبيقات ‪ rnn.RNN‬و‬
‫‪ rnn.GRU‬مع بعضها البعض‪.‬‬
‫‪ .4‬ماذا يحدث إذا قمت بتنفيذ أجزاء فقط من ‪ ، GRU‬على سبيل المثال ‪ ،‬مع بوابة إعادة‬
‫الضبط فقط أو بوابة تحديث فقط؟‬

‫‪Deep Recurrent‬‬ ‫‪10.3‬‬


‫‪Neural Networks‬‬
‫حتى اآلن‪ ،‬ركزنا على تعريف الشبكات التي تتكون من إدخال تسلسلي وطبقة ‪ RNN‬مخفية‬
‫واحدة وطبقة إخراج‪ .‬على الرغم من وجود طبقة مخفية واحدة فقط بين اإلدخاليف أي خطوة‬
‫زمنية والمخرجات المقابلة‪ ،‬إال أن هناك إحساسًا بأن هذه الشبكات عميقة‪ .‬يمكن أن تؤثر‬
‫المدخالت من الخطوة األولى على المخرجاتيف الخطوة الزمنية النهائية 𝑇 (غالبًا ‪ 100‬أو ‪1000‬‬
‫خطوة الحقًا)‪ .‬تمر هذه المدخالت عبر تطبيقات الطبقة المتكررة 𝑇 قبل الوصول إلى الناتج‬
‫النهائي‪ .‬ومع ذلك‪ ،‬غالبًا ما نرغب أيضًايف االحتفاظ بالقدرة على التعبير عن العالقات المعقدة‬
‫بين المدخالتيف خطوة زمنية معينة والمخرجاتيف نفس الخطوة الزمنية‪ .‬وبالتالي فإننا غالبًا ما‬
‫نبني ‪ RNNs‬التي تكون عميقة ليس فقطيف اتجاه الوقت ولكن أيضًايف اتجاه اإلدخال إلى‬
‫اإلخراج‪ .‬ه ذا هو بالضبط مفهوم العمق الذي واجهناه بالفعليف تطويرنا لـ ‪ MLPs‬و‪CNNs‬‬
‫العميقة‪.‬‬

‫الطريقة القياسية لبناء هذا النوع من ‪ RNN‬العميقة بسيطة بشكل مذهل‪ :‬نحن نكدس ‪RNNs‬‬
‫فوق بعضنا البعض‪ .‬بالنظر إلى تسلسل الطول 𝑇‪ ،‬ينتج ‪ RNN‬األول سلسلة من المخرجات‪،‬‬
‫‪243‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫وكذلك الطول 𝑇‪ .‬هذه‪ ،‬بدورها‪ ،‬تشكل المدخالت إلى طبقة ‪ RNN‬التالية‪.‬يف هذا القسم‬
‫القصير‪ ،‬نوضح نمط التصميم هذا ونقدم مثالًا بسيطًا لكيفية ترميز مثل هذه ‪ RNNs‬المكدسة‪.‬‬
‫أدناه‪،‬يف الشكل ‪ ،10.3.1‬نوضح ‪ RNN‬عميقًا مع طبقات مخفية‪ .‬تعمل كل حالة مخفية على‬
‫إدخال متسلسل وتنتج مخرجات متسلسلة‪ .‬عالوة على ذلك‪ ،‬تعتمد أي خلية ‪( RNN‬المربع‬
‫األبيضيف الشكل ‪) 10.3.1‬يف كل خطوة زمنية على كل من قيمة الطبقة نفسهايف الخطوة الزمنية‬
‫السابقة وقيمة الطبقة السابقةيف نفس الخطوة الزمنية‪.‬‬

‫الشكل ‪ 10.3.1‬معمارية شبكة ‪ RNN‬العميقة‪.‬‬

‫بشكل رسمي‪ ،‬افترض أن لدينا الدفعات الصغيرة مع االدخال 𝑑×𝑛‪( 𝐗 𝑡 ∈ ℝ‬عدد األمثلة‪، 𝑛:‬‬
‫عدد المدخالتيف كل مثال‪) 𝑑:‬يف الخطوة الزمنية‪.‬يف نفس الخطوة الزمنية 𝑡 ‪ ،‬ليكن الحالة‬
‫)𝑙(‬
‫المخفية لـ ‪ 𝑙 th‬الطبقة المخفية ( 𝐿 ‪ )𝑙 = 1, … ,‬تكون ‪( 𝐇𝑡 ∈ ℝ𝑛×ℎ‬عدد الوحدات المخفية‪:‬‬
‫)‪(0‬‬
‫𝑡𝐇‪ ،‬يتم حساب‬ ‫‪ )ℎ‬ومتغير طبقة اإلخراج يكون 𝑞×𝑛‪( 𝐎𝑡 ∈ ℝ‬عدد النواتج‪ .) 𝑞:‬ضبط 𝑡 𝐗 =‬
‫الحالة المخفية لـ ‪ 𝑙 th‬الطبقة المخفية التي تستخدم دالة التنشيط 𝑙𝜙 على النحو التالي‪:‬‬
‫)𝑙(‬ ‫)‪(𝑙−1‬‬ ‫)𝑙(‬ ‫)𝑙(‬ ‫)𝑙(‬ ‫)𝑙(‬
‫𝑡𝐇( 𝑙𝜙 = 𝑡𝐇‬ ‫‪𝐖𝑥ℎ + 𝐇𝑡−1 𝐖ℎℎ + 𝐛ℎ ),‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪244‬‬

‫)𝑙(‬ ‫)𝑙(‬ ‫)𝑙(‬


‫حيث األوزان ‪ 𝐖𝑥ℎ ∈ ℝℎ×ℎ‬و ‪ ،𝐖ℎℎ ∈ ℝℎ×ℎ‬جنبًا إلى جنب مع التحيز ‪،𝐛ℎ ∈ ℝ1×ℎ‬‬
‫هي معلمات نموذج ‪ 𝑙 th‬الطبقة المخفية‪.‬‬

‫في النهاية‪ ،‬يعتمد حساب الطبقة المخرجة فقط على الحالة المخفية لـ ‪ 𝐿th‬الطبقة المخفية‬
‫النهائية‪:‬‬
‫)𝐿(‬
‫‪𝐎𝑡 = 𝐇𝑡 𝐖ℎ𝑞 + 𝐛𝑞 ,‬‬

‫حيث الوزن 𝑞×‪ 𝐖ℎ𝑞 ∈ ℝℎ‬والتحيز 𝑞×‪ 𝐛𝑞 ∈ ℝ1‬هما معلمات النموذج للطبقة الناتجة‪.‬‬

‫تمامًا كما هو الحال مع ‪ ،MLPs‬فإن عدد الطبقات المخفية 𝐿 وعدد الوحدات المخفية ‪ ℎ‬هي‬
‫معلمات فائقة يمكننا ضبطها‪ .‬تقع عروض طبقة ‪ RNN‬الشائعة (‪)ℎ‬يف النطاق )‪، (64,2056‬‬
‫بينما تقع األعماق الشائعة ( 𝐿)يف النطاق )‪ .(1,8‬باإلضافة إلى ذلك‪ ،‬يمكننا بسهولة الحصول‬
‫على ‪ RNN‬ذي بوابات عميقة عن طريق استبدال حساب الحالة المخفيةيف (‪ )10.3.1‬بحساب‬
‫‪ LSTM‬أو ‪.GRU‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Implementation from Scratch‬‬ ‫‪10.3.1‬‬
‫لتنفيذ ‪ RNN‬متعدد الطبقات من البداية‪ ،‬يمكننا التعامل مع كل طبقة على أنها مثيل‬
‫‪ RNNScratch‬مع معلماتها القابلة للتعلم‪.‬‬

‫‪class StackedRNNScratch(d2l.Module):‬‬
‫‪def __init__(self, num_inputs, num_hiddens,‬‬
‫‪num_layers, sigma=0.01):‬‬
‫)(__‪super().__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫‪self.rnns = [d2l.RNNScratch(num_inputs if i==0‬‬
‫‪else num_hiddens,‬‬
‫)‪num_hiddens, sigma‬‬
‫])‪for i in range(num_layers‬‬
‫يقوم الحساب األمامي متعدد الطبقات ببساطة بإجراء حساب إلى األمام طبقة تلو األخرى‪.‬‬

‫)‪@d2l.add_to_class(StackedRNNScratch‬‬
‫‪def forward(self, inputs, Hs=None):‬‬
‫‪outputs = inputs‬‬
‫)‪if Hs is None: Hs = [None] * len(inputs‬‬
‫‪for i in range(self.num_layers):‬‬
‫)]‪outputs, Hs[i] = self.rnns[i](outputs, Hs[i‬‬
‫‪return outputs, Hs‬‬
‫‪245‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫على سبيل المثال‪ ،‬نقوم بتدريب نموذج ‪ GRU‬عميق على مجموعة بيانات ‪The Time‬‬
‫‪( Machine‬كمايف القسم ‪ .)9.5‬لتبسيط األمور‪ ،‬قمنا بتعيين عدد الطبقات على ‪.2‬‬

‫)‪data = d2l.TimeMachine(batch_size=1024, num_steps=32‬‬


‫‪with d2l.try_gpu():‬‬
‫= ‪rnn_block‬‬
‫‪StackedRNNScratch(num_inputs=len(data.vocab),‬‬
‫‪num_hiddens=32,‬‬
‫)‪num_layers=2‬‬
‫‪model = d2l.RNNLMScratch(rnn_block,‬‬
‫)‪vocab_size=len(data.vocab), lr=2‬‬
‫‪trainer = d2l.Trainer(max_epochs=100,‬‬
‫)‪gradient_clip_val=1‬‬
‫)‪trainer.fit(model, data‬‬

‫‪Concise Implementation‬‬ ‫‪10.3.2‬‬


‫لحسن الحظ‪ ،‬فإن العديد من التفاصيل اللوجستية المطلوبة لتنفيذ طبقات متعددة من ‪RNN‬‬
‫متاحة بسهولةيف واجهات برمجة التطبيقات عالية المستوى ‪ .API‬سيستخدم تطبيقنا الموجز مثل‬
‫هذه الدوال المدمجة‪ .‬يعمم الكود الرمز الذي استخدمناه سابقًايف القسم ‪ ،10.2‬مما يسمح‬
‫بتحديد عدد الطبقات بشكل صريح بدالً من اختيار االفتراضي لطبقة واحدة‪.‬‬

‫‪class GRU(d2l.RNN): #@save‬‬


‫‪def __init__(self, num_hiddens, num_layers,‬‬
‫‪dropout=0):‬‬
‫)‪d2l.Module.__init__(self‬‬
‫)(‪self.save_hyperparameters‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 246

gru_cells =
[tf.keras.layers.GRUCell(num_hiddens, dropout=dropout)
for _ in range(num_layers)]
self.rnn = tf.keras.layers.RNN(gru_cells,
return_sequences=True,

return_state=True, time_major=True)

def forward(self, X, state=None):


outputs, *state = self.rnn(X, state)
return outputs, state
.10.2 ‫تشبه القرارات المعمارية مثل اختيار المعلمات الفائقة إلى حد كبير تلك الواردةيف القسم‬
‫ أي‬،distinct tokens ‫نختار نفس عدد المدخالت والمخرجات ألن لدينا رموز مميزة‬
‫ االختالف الوحيد هو‬.32 ‫ ال يزال عدد الوحدات المخفية‬.vocab_size ‫حجم_المفردات‬
.‫أننا نختار اآلن عددًا غير أساسي من الطبقات المخفية عن طريق تحديد قيمة عدد الطبقات‬

gru = GRU(num_hiddens=32, num_layers=2)


with d2l.try_gpu():
model = d2l.RNNLM(gru, vocab_size=len(data.vocab),
lr=2)
trainer.fit(model, data)

model.predict('it has', 20, data.vocab)


'it has i the time travelle'
‫‪247‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪10.3.3‬‬
‫في ‪ RNNs‬العميقة‪ ،‬يتم تمرير معلومات الحالة المخفية إلى الخطوة الزمنية التالية للطبقة‬
‫الحالية والخطوة الزمنية الحالية للطبقة التالية‪ .‬توجد العديد من النكهات المختلفة لـ ‪RNNs‬‬
‫العميقة‪ ،‬مثل ‪ LSTMs‬أو ‪ GRUs‬أو ‪ .vanilla RNNs‬بشكل مالئم‪ ،‬تتوفر جميع هذه النماذج‬
‫كأجزاء من واجهات برمجة التطبيقات عالية المستوى ألطر التعلم العميق‪ .‬يتطلب تهيئة النماذج‬
‫االهتمام‪ .‬بشكل عام‪ ،‬تتطلب شبكات ‪ RNN‬العميقة قدرًا كبيرًا من العمل (مثل معدل التعلم‬
‫والقص ‪ )clipping‬لضمان التقارب المناسب‪.‬‬

‫‪10.3.4‬‬
‫‪ .1‬استبدل ‪ GRU‬بـ ‪ LSTM‬وقارن الدقة وسرعة التدريب‪.‬‬
‫‪ .2‬قم بزيادة بيانات التدريب لتشمل كتبًا متعددة‪ .‬إلى أي مدى يمكن أن تذهب على‬
‫مقياس االرتباك ‪ perplexity scale‬؟‬
‫‪ .3‬هل تريد الجمع بين مصادر مؤلفين مختلفين عند نمذجة النص؟ لماذا هذه الفكرة‬
‫جيدة؟ ما الخطأ الذي يمكن أن يحدث؟‬

‫‪Bidirectional‬‬ ‫‪10.4‬‬
‫‪Recurrent Neural Networks‬‬
‫حتى اآلن‪ ،‬كان مثالنا العملي لمهمة التعلم المتسلسل هو نمذجة اللغة‪ ،‬حيث نهدف إلى توقع‬
‫الرمز التالي مع األخذيف االعتبار جميع الرموز السابقةيف تسلسل‪.‬يف هذا السيناريو‪ ،‬نرغب فقطيف ‬
‫الشرط على السياق األيسر‪ ،‬وبالتالي يبدو التسلسل أحادي االتجاه ‪unidirectional chaining‬‬
‫لـ ‪ RNN‬القياسي مناسبًا‪ .‬ومع ذلك‪ ،‬هناك العديد من سياقات مهام التعلم المتسلسلة األخرى‬
‫حيث يكون من الجيد تمامًا تكييف التنبؤيف كل خطوة زمنية على كل من السياق األيمن واأليسر‪.‬‬
‫ضعيف اعتبارك‪ ،‬على سبيل المثال‪ ،‬جزءًا من اكتشاف الكالم ‪.part of speech detection‬‬
‫لماذا ال يجب أن نأخذ السياقيف كال االتجاهينيف االعتبار عند تقييم جزء الكالم المرتبط بكلمة‬
‫معينة؟‬

‫مهمة أخرى شائعة ‪ -‬غالبًا ما تكون مفيدة كتمرين مسبق قبل ضبط نموذج على مهمة فعلية مثيرة‬
‫لالهتمام ‪ -‬وهي إخفاء الرموز العشوائيةيف مستند نصي ثم تدريب نموذج تسلسل للتنبؤ بقيم‬
‫الرموز المفقودة‪ .‬الحظ أنه بناءً على ما يأتي بعد الفراغ‪ ،‬فإن القيمة المحتملة للرمز المفقود تتغير‬
‫بشكل كبير‪:‬‬

‫•‬ ‫‪I am ___.‬‬


‫•‬ ‫‪I am ___ hungry.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪248‬‬

‫•‬ ‫‪I am ___ hungry, and I can eat half a pig.‬‬


‫في الجملة األولى‪ ،‬يبدو أن كلمة "‪ " happy‬هي المرشح المحتمل‪ .‬يبدو أن الكلمتين "‪ "not‬و‬
‫"‪ "very‬معقولتانيف الجملة الثانية‪ ،‬لكن "‪ "not‬تبدو غير متوافقة مع الجمل الثالثة‪.‬‬

‫لحسن الحظ‪ ،‬هناك تقنية بسيطة تحول أي ‪ RNN‬أحادي االتجاه ‪ unidirectional‬إلى‬


‫‪ RNN‬ثنائي االتجاه ‪ .)1997 ،Schuster and Paliwal( bidrectional‬نحن ببساطة ننفذ‬
‫طبقتين من ‪ RNN‬أحادي االتجاه مرتبطان ببعضهما البعضيف اتجاهات متعاكسة وتعمل على‬
‫نفس المدخالت (الشكل ‪ .)10.4.1‬بالنسبة لطبقة ‪ RNN‬األولى‪ ،‬يكون اإلدخال األول هو ‪𝐱1‬‬
‫والمدخل األخير 𝑇 𝐱 ‪ ،‬ولكن بالنسبة لطبقة ‪ RNN‬الثانية‪ ،‬يكون اإلدخال األول 𝑇 𝐱 والمدخل‬
‫األخير هو ‪ .𝐱1‬إلنتاج ناتج طبقة ‪ RNN‬ثنائية االتجاه هذه‪ ،‬نقوم ببساطة بربط المخرجات‬
‫المقابلة لطبقتين ‪ RNN‬األساسيتين أحادي االتجاه معًا‪.‬‬

‫الشكل ‪ 10.4.1‬معمارية ‪ RNN‬ثنائية االتجاه‪.‬‬

‫رسميًا ألي خطوة زمنية 𝑡 ‪ ،‬نعتبر إدخال الدفعات الصغيرة هو 𝑑×𝑛‪( 𝐗 𝑡 ∈ ℝ‬عدد األمثلة‪، 𝑛:‬‬
‫عدد المدخالتيف كل مثال‪ ) 𝑑:‬ودع دالة تنشيط الطبقة المخفية تكون 𝜙‪.‬يف البنية ثنائية االتجاه‪،‬‬
‫←‬ ‫→‬
‫الحاالت المخفية لألمام والخلف لهذه الخطوة الزمنية هي ‪ 𝐇𝑡 ∈ ℝ𝑛×ℎ‬و ‪ ،𝐇𝑡 ∈ ℝ𝑛×ℎ‬على‬
‫التوالي‪ ،‬حيث ‪ ℎ‬هو عدد الوحدات المخفية‪ .‬تحديثات الحالة المخفية لألمام والخلف هي كما‬
‫يلي‪:‬‬
‫→‬ ‫→‬
‫)𝑓(‬ ‫)𝑓(‬ ‫)𝑓(‬
‫𝑡𝐇‬ ‫‪= 𝜙(𝐗 𝑡 𝐖𝑥ℎ + 𝐇𝑡−1 𝐖ℎℎ + 𝐛ℎ ),‬‬
‫←‬ ‫←‬
‫)𝑏(‬ ‫)𝑏(‬ ‫)𝑏(‬
‫𝑡𝐇‬ ‫‪= 𝜙(𝐗 𝑡 𝐖𝑥ℎ + 𝐇𝑡+1 𝐖ℎℎ + 𝐛ℎ ),‬‬
‫‪249‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫)𝑓(‬ ‫)𝑓(‬ ‫)𝑏(‬ ‫)𝑏(‬


‫حيث األوزان ‪𝐖𝑥ℎ ∈ ℝ𝑑×ℎ , 𝐖ℎℎ ∈ ℝℎ×ℎ , 𝐖𝑥ℎ ∈ ℝ𝑑×ℎ , and 𝐖ℎℎ ∈ ℝℎ×ℎ‬و‬
‫)𝑏(‬ ‫)𝑏(‬
‫‪ 𝐖ℎℎ ∈ ℝℎ×ℎ‬والتحيزات ‪ 𝐛ℎ ∈ ℝ1×ℎ‬هي جميع معلمات النموذج‪.‬‬
‫←‬ ‫→‬
‫بعد ذلك‪ ،‬نجمع بين الحاالت المخفية األمامية والخلفية 𝑡𝐇 و 𝑡𝐇 للحصول على الحالة المخفية‬
‫‪ 𝐇𝑡 ∈ ℝ𝑛×2ℎ‬التي سيتم تغذيتهايف طبقة اإلخراج‪.‬يف شبكات ‪ RNN‬ثنائية االتجاه العميقة‬
‫ذات الطبقات المخفية المتعددة‪ ،‬يتم تمرير هذه المعلومات كمدخالت إلى الطبقة ثنائية االتجاه‬
‫التالية‪ .‬أخيرًا‪ ،‬طبقة اإلخراج تحسب اإلخراج 𝑞×𝑛‪( 𝐎𝑡 ∈ ℝ‬عدد المخرجات‪:) 𝑞:‬‬

‫‪𝐎𝑡 = 𝐇𝑡 𝐖ℎ𝑞 + 𝐛𝑞 .‬‬

‫هنا‪ ،‬مصفوفة الوزن 𝑞×‪ 𝐖ℎ𝑞 ∈ ℝ2ℎ‬والتحيز 𝑞×‪ 𝐛𝑞 ∈ ℝ1‬هما معلمات نموذج طبقة اإلخراج‪.‬‬
‫بينما من الناحية الفنية‪ ،‬يمكن أن يكون لالتجاهين أعداد مختلفة من الوحدات المخفية‪ ،‬إال أن‬
‫اختيار التصميم هذا نادرًا ما يتم إجراؤه عمليًا‪ .‬نعرض اآلن تنفيذًا بسيطًا لـ ‪ RNN‬ثنائي االتجاه‬
‫‪.bidirectional RNN‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Implementation from Scratch‬‬ ‫‪10.4.1‬‬
‫لتنفيذ ‪ RNN‬ثنائي االتجاه من البداية‪ ،‬يمكننا تضمين مثيلين ‪ RNNScratch‬أحادي االتجاه‬
‫مع معلمات منفصلة قابلة للتعلم‪.‬‬

‫‪class BiRNNScratch(d2l.Module):‬‬
‫‪def __init__(self, num_inputs, num_hiddens,‬‬
‫‪sigma=0.01):‬‬
‫)(__‪super().__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫‪self.f_rnn = d2l.RNNScratch(num_inputs,‬‬
‫)‪num_hiddens, sigma‬‬
‫‪self.b_rnn = d2l.RNNScratch(num_inputs,‬‬
‫)‪num_hiddens, sigma‬‬
‫‪self.num_hiddens *= 2 # The output dimension‬‬
‫‪will be doubled‬‬
‫يتم تحديث حاالت ‪ RNNs‬األمامية والخلفية بشكل منفصل‪ ،‬بينما يتم توصيل مخرجات‬
‫هاتين ‪.RNNs‬‬

‫)‪@d2l.add_to_class(BiRNNScratch‬‬
‫‪def forward(self, inputs, Hs=None):‬‬
‫)‪f_H, b_H = Hs if Hs is not None else (None, None‬‬
‫)‪f_outputs, f_H = self.f_rnn(inputs, f_H‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪250‬‬

‫)‪b_outputs, b_H = self.b_rnn(reversed(inputs), b_H‬‬


‫‪outputs = [tf.concat((f, b), -1) for f, b in‬‬
‫])‪zip(f_outputs, b_outputs‬‬
‫)‪return outputs, (f_H, b_H‬‬
‫‪Concise Implementation‬‬ ‫‪10.4.2‬‬
‫باستخدام واجهات برمجة التطبيقات عالية المستوى ‪ ،API‬يمكننا تنفيذ ‪ RNN‬ثنائية االتجاه‬
‫بشكل أكثر إيجازًا‪ .‬هنا نأخذ نموذج ‪ GRU‬كمثال‪.‬‬

‫‪10.4.2.1‬‬
‫في ‪ RNNs‬ثنائية االتجاه ‪ ،bidirectional RNNs‬يتم تحديد الحالة المخفية لكل خطوة‬
‫زمنيةيف وقت واحد بواسطة البيانات قبل وبعد الخطوة الزمنية الحالية‪ RNNs .‬ثنائية االتجاه‬
‫مفيدةيف الغالب لتشفير التسلسل وتقدير المالحظاتيف سياق ثنائي االتجاه‪ RNNs .‬ثنائية‬
‫االتجاه مكلفة للغاية للتدريب بسبب سالسل التدرج الطويلة ‪.long gradient chains‬‬

‫‪10.4.2.2‬‬
‫‪ .1‬إذا كانت االتجاهات المختلفة تستخدم عددًا مختلفًا من الوحدات المخفية‪ ،‬فكيف‬
‫سيتغير الشكل 𝑡𝐇 ؟‬
‫‪ .2‬صمم ‪ RNN‬ثنائي االتجاه مع طبقات مخفية متعددة‪.‬‬
‫‪ .3‬تعدد المعاني ‪ Polysemy‬شائعيف اللغات الطبيعية‪ .‬على سبيل المثال‪ ،‬لكلمة "‪" bank‬‬
‫معاني مختلفةيف السياقات " ‪ " i went to the bank to deposit cash‬و " ‪i went‬‬
‫‪ ." to the bank to sit down‬كيف يمكننا تصميم نموذج شبكة عصبية بحيث يتم‬
‫إرجاع تمثيل متجه للكلمةيف السياقيف ضوء تسلسل السياق والكلمة؟ ما نوع البنى‬
‫العصبية المفضل للتعامل مع تعدد المعاني ‪polysemy‬؟‬

‫‪Machine Translation and‬‬ ‫‪10.5‬‬


‫‪the Dataset‬‬
‫من بين اإلنجازات الرئيسية التي أدت إلى اهتمام واسع النطاق بـ ‪ RNNs‬الحديثة‪ ،‬كان هناك‬
‫تقدم كبيريف المجال التطبيقي للترجمة اآللية ‪ machine translation‬اإلحصائية‪ .‬هنا‪ ،‬يتم تقديم‬
‫النموذج بجملة بلغة واحدة ويجب أن يتنبأ بالجمل المقابليف لغة أخرى‪ .‬الحظ أن الجمل هنا قد‬
‫تكون ذات أطوال مختلفة‪ ،‬وأن الكلمات المقابلةيف الجملتين قد ال تظهر بنفس الترتيب‪ ،‬بسبب‬
‫االختالفاتيف التركيب النحوي للغتين‪.‬‬

‫العديد من المشاكل لها طابع التعيين ‪ mapping‬بين اثنين من هذه التتابعات "غير المحاذاة‬
‫‪ ." unaligned‬تتضمن األمثلة التعيين من مطالبات الحوار إلى الردود أو من األسئلة إلى‬
‫‪251‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫اإلجابات‪ .‬بشكل عام‪ ،‬تسمى هذه المشكالت مشاكل التسلسل إلى التسلسل ‪sequence-to-‬‬
‫‪ )seq2seq( sequence‬وهي محور تركيزنا لكل من الجزء المتبقي من هذا الفصل والكثير من‬
‫القسم ‪.11‬‬

‫في هذا القسم‪ ،‬نقدم مشكلة الترجمة اآللية ‪ machine translation‬ومثالًا لمجموعة البيانات‬
‫‪ dataset‬التي سنستخدمهايف األمثلة الالحقة‪ .‬لعقود من الزمان‪ ،‬كانت الصيغ اإلحصائية للترجمة‬
‫بين اللغات شائعة (‪ ،)1988 ،Brown et al. ،1990 ،Brown et al.‬حتى قبل أن يعمل‬
‫الباحثون على اتباع نهج الشبكة العصبية (غالبًا ما يتم تجميع الطرق معًا تحت مصطلح الترجمة‬
‫اآللية العصبية ‪.)neural machine translation‬‬

‫أوالً‪ ،‬سنحتاج إلى رمز جديد لمعالجة بياناتنا‪ .‬على عكس نمذجة اللغة التي رأيناهايف القسم ‪،9.3‬‬
‫يتكون كل مثال هنا من تسلسلين نصيين منفصلين‪ ،‬أحدهما بلغة المصدر واآلخر (الترجمة)يف ‬
‫اللغة الهدف‪ .‬ستوضح مقتطفات التعليمات البرمجية التالية كيفية تحميل البيانات المعالجة‬
‫مسبقًا إلى الدفعات الصغيرة للتدريب‪.‬‬

‫‪import os‬‬
‫‪import tensorflow as tf‬‬
‫‪from d2l import tensorflow as d2l‬‬
‫‪Downloading and‬‬ ‫‪10.5.1‬‬
‫‪Preprocessing the Dataset‬‬
‫للبدء‪ ،‬نقوم بتنزيل مجموعة بيانات إنجليزية‪-‬فرنسية تتكون من أزواج جمل ثنائية اللغة‬
‫‪ bilingual sentence pairs‬من مشروع ‪ .Tatoeba‬كل سطريف مجموعة البيانات عبارة عن‬
‫زوج محدد بعالمات جدولة يتكون من تسلسل نص إنجليزي وتسلسل نص فرنسي مترجم‪ .‬الحظ‬
‫أن كل تسلسل نصي يمكن أن يكون مجرد جملة واحدة‪ ،‬أو فقرة من جمل متعددة‪.‬يف مشكلة‬
‫الترجمة اآللية هذه حيث تتم ترجمة اللغة اإلنجليزية إلى الفرنسية‪ ،‬تسمى اللغة اإلنجليزية لغة‬
‫المصدر ‪ source language‬وتسمى الفرنسية اللغة الهدف ‪.target language‬‬

‫‪class MTFraEng(d2l.DataModule): #@save‬‬


‫‪def _download(self):‬‬
‫(‪d2l.extract(d2l.download‬‬
‫‪d2l.DATA_URL+'fra-eng.zip', self.root,‬‬
‫))'‪'94646ad1522d915e7b0f9296181140edcf86a4f5‬‬
‫‪with open(self.root + '/fra-eng/fra.txt',‬‬
‫‪encoding='utf-8') as f:‬‬
‫)(‪return f.read‬‬

‫)(‪data = MTFraEng‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪252‬‬

‫)(‪raw_text = data._download‬‬
‫)]‪print(raw_text[:75‬‬
‫! ‪Go. Va‬‬
‫! ‪Hi. Salut‬‬
‫!‪Run‬‬ ‫! ‪Cours‬‬
‫!‪Run‬‬ ‫! ‪Courez‬‬
‫?‪Who‬‬ ‫? ‪Qui‬‬
‫!‪Wow‬‬ ‫! ‪Ça alors‬‬
‫بعد تنزيل مجموعة البيانات ‪ ،dataset‬ننتقل إلى العديد من خطوات المعالجة المسبقة لبيانات‬
‫النص الخام‪ .‬على سبيل المثال‪ ،‬نستبدل المسافات غير المنقسمة بمسافة‪ ،‬ونحول األحرف‬
‫الكبيرة إلى أحرف صغيرة‪ ،‬ونضع مسافة بين الكلمات وعالمات الترقيم‪.‬‬

‫‪@d2l.add_to_class(MTFraEng) #@save‬‬
‫‪def _preprocess(self, text):‬‬
‫‪# Replace non-breaking space with space‬‬
‫' ‪text = text.replace('\u202f', ' ').replace('\xa0',‬‬
‫)'‬
‫‪# Insert space between words and punctuation marks‬‬
‫'?!‪no_space = lambda char, prev_char: char in ',.‬‬
‫' ' =! ‪and prev_char‬‬
‫‪out = [' ' + char if i > 0 and no_space(char, text[i‬‬
‫‪- 1]) else char‬‬
‫]))(‪for i, char in enumerate(text.lower‬‬
‫)‪return ''.join(out‬‬

‫)‪text = data._preprocess(raw_text‬‬
‫)]‪print(text[:80‬‬
‫‪go .‬‬ ‫! ‪va‬‬
‫‪hi .‬‬ ‫! ‪salut‬‬
‫! ‪run‬‬ ‫! ‪cours‬‬
‫! ‪run‬‬ ‫! ‪courez‬‬
‫? ‪who‬‬ ‫? ‪qui‬‬
‫! ‪wow‬‬ ‫! ‪ça alors‬‬
‫‪Tokenization‬‬ ‫‪10.5.2‬‬
‫على عكس الترميز على مستوى الحرفيف القسم ‪ ،9.3‬بالنسبة للترجمة اآللية‪ ،‬فإننا نفضل الترميز‬
‫على مستوى الكلمات هنا (تستخدم النماذج الحديثة اليوم تقنيات ترميز أكثر تعقيدًا)‪ .‬تقوم‬
‫طريقة ‪ _tokenize‬التالية بترميز أول أزواج تسلسل نصي ‪ ،max_examples‬حيث يكون‬
‫كل رمز إما كلمة أو عالمة ترقيم‪ .‬نلحق الرمز المميز "<‪ ">eos‬بنهاية كل تسلسل لإلشارة إلى‬
‫نهاية التسلسل‪ .‬عندما يتنبأ نموذج عن طريق إنشاء رمز تسلسلي بعد الرمز‪ ،‬يمكن أن يشير إنشاء‬
253 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

‫ تُرجع الطريقة أدناه قائمتين من‬،‫يف النهاية‬.‫>" إلى اكتمال تسلسل اإلخراج‬eos<" ‫الرمز المميز‬
‫ هي قائمة من الرموز من‬src[i] ، ‫ على وجه التحديد‬tgt. ‫ و‬src :‫قوائم الرموز المميزة‬
‫ هو ذلكيف اللغة الهدف (الفرنسية‬tgt[i] ‫تسلسل النصيف اللغة المصدر (اإلنجليزية هنا) و‬
.)‫هنا‬

@d2l.add_to_class(MTFraEng) #@save
def _tokenize(self, text, max_examples=None):
src, tgt = [], []
for i, line in enumerate(text.split('\n')):
if max_examples and i > max_examples: break
parts = line.split('\t')
if len(parts) == 2:
# Skip empty tokens
src.append([t for t in f'{parts[0]}
<eos>'.split(' ') if t])
tgt.append([t for t in f'{parts[1]}
<eos>'.split(' ') if t])
return src, tgt

src, tgt = data._tokenize(text)


src[:6], tgt[:6]
([['go', '.', '<eos>'],
['hi', '.', '<eos>'],
['run', '!', '<eos>'],
['run', '!', '<eos>'],
['who', '?', '<eos>'],
['wow', '!', '<eos>']],
[['va', '!', '<eos>'],
['salut', '!', '<eos>'],
['cours', '!', '<eos>'],
['courez', '!', '<eos>'],
['qui', '?', '<eos>'],
['ça', 'alors', '!', '<eos>']])
‫يف مجموعة البيانات اإلنجليزية‬.‫دعنا نرسم المدرج التكراري لعدد الرموز لكل تسلسل نصي‬
.‫ رمزًا‬20 ‫ تحتوي معظم التسلسالت النصية على أقل من‬،‫الفرنسية البسيطة هذه‬

#@save
def show_list_len_pair_hist(legend, xlabel, ylabel,
xlist, ylist):
"""Plot the histogram for list length pairs."""
d2l.set_figsize()
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪254‬‬

‫(‪_, _, patches = d2l.plt.hist‬‬


‫‪[[len(l) for l in xlist], [len(l) for l in‬‬
‫)]]‪ylist‬‬
‫)‪d2l.plt.xlabel(xlabel‬‬
‫)‪d2l.plt.ylabel(ylabel‬‬
‫‪for patch in patches[1].patches:‬‬
‫)'‪patch.set_hatch('/‬‬
‫)‪d2l.plt.legend(legend‬‬

‫‪show_list_len_pair_hist(['source', 'target'], '# tokens‬‬


‫‪per sequence',‬‬
‫;)‪'count', src, tgt‬‬

‫‪Loading Sequences of‬‬ ‫‪10.5.3‬‬


‫‪Fixed Length‬‬
‫تذكر أنهيف نمذجة اللغة لكل مثال تسلسل‪ ،‬سواء كان مقطعًا من جملة واحدة أو امتدادًا عبر جمل‬
‫متعددة‪ ،‬يكون له طول ثابت‪ .‬تم تحديد ذلك بواسطة الوسيطة ‪( num_steps‬عدد الخطوات‬
‫الزمنية أو الرموز ‪)tokens‬يف القسم ‪.9.3‬يف الترجمة اآللية‪ ،‬يكون كل مثال زوجًا من تسلسل‬
‫النص المصدر والهدف‪ ،‬حيث قد يكون لتسلسل النصين أطوال مختلفة‪.‬‬

‫لتحقيق الكفاءة الحسابية‪ ،‬ال يزال بإمكاننا معالجة مجموعة صغيرة من تسلسالت النصيف وقت‬
‫واحد عن طريق االقتطاع ‪ truncation‬والحشو ‪ .padding‬افترض أن كل تسلسليف نفس‬
‫الدفعات الصغيرة ‪ minibatch‬يجب أن يكون له نفس الطول ‪ .num_steps‬إذا كان التسلسل‬
‫النصي يحتوي على أقل من ‪ num_steps‬للرموز‪ ،‬فسنستمريف إلحاق الرمز المميز "<‪">pad‬‬
‫بنهايته حتى يصل طوله إلى عدد_الخطوات ‪ .num_steps‬خالفًا لذلك‪ ،‬سنقوم باقتطاع‬
‫‪255‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫تسلسل النص من خالل أخذ الرموز لعدد الخطوات األولى ‪ num_steps‬فقط والتخلص من‬
‫الباقي‪ .‬بهذه الطريقة‪ ،‬سيكون لكل تسلسل نصي نفس الطول ليتم تحميلهيف دفعات صغيرة من‬
‫نفس الشكل‪ .‬إلى جانب ذلك‪ ،‬نسجل أيضًا طول تسلسل المصدر باستثناء الرموز للحشو‬
‫‪ .padding‬ستحتاج بعض النماذج إلى هذه المعلومات التي سنغطيها الحقًا‪.‬‬

‫نظرًا ألن مجموعة بيانات الترجمة اآللية تتكون من أزواج من اللغات‪ ،‬يمكننا بناء مفردتين لكل‬
‫من اللغة المصدر واللغة الهدف بشكل منفصل‪ .‬باستخدام الترميز على مستوى الكلمة‪ ،‬سيكون‬
‫حجم المفردات أكبر بكثير من ذلك باستخدام الترميز على مستوى الحرف‪ .‬للتخفيف من هذا‪،‬‬
‫نتعامل هنا مع الرموز غير المتكررة التي تظهر أقل من مرتين كرمز غير معروف ("<‪.)" >unk‬‬
‫كما سنشرح الحقًا (الشكل ‪ ،)10.7.1‬عند التدريب باستخدام التسلسالت المستهدفة‪ ،‬يمكن‬
‫أن يكون إخراج وحدة مفكك الشفرة ‪( decoder output‬رموز للتسمية ‪ )label tokens‬هو‬
‫نفس مدخالت مفكك الشفرة (رموز المستهدفة ‪ ، )target tokens‬والتي يتم إزاحتها بواسطة‬
‫رمز واحد وسيتم استخدام الرمز لبداية التسلسل "<‪ ">bos‬كأول رمز للدخل للتنبؤ بالتسلسل‬
‫المستهدف (الشكل ‪.)10.7.3‬‬

‫‪@d2l.add_to_class(MTFraEng) #@save‬‬
‫‪def __init__(self, batch_size, num_steps=9,‬‬
‫‪num_train=512, num_val=128):‬‬
‫)(__‪super(MTFraEng, self).__init‬‬
‫)(‪self.save_hyperparameters‬‬
‫= ‪self.arrays, self.src_vocab, self.tgt_vocab‬‬
‫(‪self._build_arrays‬‬
‫))(‪self._download‬‬

‫‪@d2l.add_to_class(MTFraEng) #@save‬‬
‫‪def _build_arrays(self, raw_text, src_vocab=None,‬‬
‫‪tgt_vocab=None):‬‬
‫‪def _build_array(sentences, vocab, is_tgt=False):‬‬
‫( ‪pad_or_trim = lambda seq, t:‬‬
‫]'>‪seq[:t] if len(seq) > t else seq + ['<pad‬‬
‫)))‪* (t - len(seq‬‬
‫‪sentences = [pad_or_trim(s, self.num_steps) for‬‬
‫]‪s in sentences‬‬
‫‪if is_tgt:‬‬
‫‪sentences = [['<bos>'] + s for s in‬‬
‫]‪sentences‬‬
‫‪if vocab is None:‬‬
‫)‪vocab = d2l.Vocab(sentences, min_freq=2‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 256

array = tf.constant([vocab[s] for s in


sentences])
valid_len = tf.reduce_sum(
tf.cast(array != vocab['<pad>'], tf.int32),
1)
return array, vocab, valid_len
src, tgt =
self._tokenize(self._preprocess(raw_text),
self.num_train +
self.num_val)
src_array, src_vocab, src_valid_len =
_build_array(src, src_vocab)
tgt_array, tgt_vocab, _ = _build_array(tgt,
tgt_vocab, True)
return ((src_array, tgt_array[:,:-1], src_valid_len,
tgt_array[:,1:]),
src_vocab, tgt_vocab)
Reading the Dataset 10.5.4
.data iterator ‫ إلرجاع مكرر البيانات‬get_dataloader ‫ نحدد طريقة‬،‫أخيرًا‬

@d2l.add_to_class(MTFraEng) #@save
def get_dataloader(self, train):
idx = slice(0, self.num_train) if train else
slice(self.num_train, None)
return self.get_tensorloader(self.arrays, train,
idx)
.‫الفرنسية‬-‫دعنا نقرأ الدفعة األولى من مجموعة البيانات اإلنجليزية‬

data = MTFraEng(batch_size=3)
src, tgt, src_valid_len, label =
next(iter(data.train_dataloader()))
print('source:', tf.cast(src, tf.int32))
print('decoder input:', tf.cast(tgt, tf.int32))
print('source len excluding pad:',
tf.cast(src_valid_len, tf.int32))
print('label:', tf.cast(label, tf.int32))
source: tf.Tensor(
[[ 79 5 0 3 4 4 4 4 4]
[ 28 150 2 3 4 4 4 4 4]
[ 69 0 3 4 4 4 4 4 4]], shape=(3, 9),
dtype=int32)
decoder input: tf.Tensor(
257 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

[[ 3 49 37 6 0 4 5 5 5]
[ 3 206 31 0 4 5 5 5 5]
[ 3 210 6 0 4 5 5 5 5]], shape=(3, 9),
dtype=int32)
source len excluding pad: tf.Tensor([4 4 3], shape=(3,),
dtype=int32)
label: tf.Tensor(
[[ 49 37 6 0 4 5 5 5 5]
[206 31 0 4 5 5 5 5 5]
[210 6 0 4 5 5 5 5 5]], shape=(3, 9),
dtype=int32)
‫نعرض أدناه زوجًا من التسلسالت المصدر والهدف التي تتم معالجتها بواسطة طريقة‬
.)string format ‫_ أعاله (في تنسيق السلسلة‬build_arrays

@d2l.add_to_class(MTFraEng) #@save
def build(self, src_sentences, tgt_sentences):
raw_text = '\n'.join([src + '\t' + tgt for src, tgt
in zip(
src_sentences, tgt_sentences)])
arrays, _, _ = self._build_arrays(
raw_text, self.src_vocab, self.tgt_vocab)
return arrays

src, tgt, _, _ = data.build(['hi .'], ['salut .'])


print('source:',
data.src_vocab.to_tokens(tf.cast(src[0], tf.int32)))
print('target:',
data.tgt_vocab.to_tokens(tf.cast(tgt[0], tf.int32)))
source: ['hi', '.', '<eos>', '<pad>', '<pad>', '<pad>',
'<pad>', '<pad>', '<pad>']
target: ['<bos>', 'salut', '.', '<eos>', '<pad>',
'<pad>', '<pad>', '<pad>', '<pad>']
10.5.5
‫ تشير الترجمة اآللية إلى مهمة التعيين التلقائي من تسلسل يمثل سلسلة‬،‫في معالجة اللغة الطبيعية‬
‫ باستخدام الترميز على مستوى‬.‫نصيةيف لغة المصدر إلى سلسلة تمثل ترجمة معقولةيف لغة الهدف‬
‫ سيكون حجم المفردات أكبر بكثير من ذلك باستخدام‬،word-level tokenization ‫الكلمة‬
‫ لكن أطوال التسلسل ستكون‬،character-level tokenization ‫الترميز على مستوى الحرف‬
‫ يمكننا التعامل مع الرموز غير المتكررة على أنها رمز‬،‫ لتقليل حجم المفردات الكبير‬.‫أقصر بكثير‬
‫ تسلسالت النص بحيث‬pad ‫ وحشو‬truncate ‫ يمكننا اقتطاع‬."unknown ‫مميز "غير معروف‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪258‬‬

‫يكون لكل منهم نفس الطول ليتم تحميله ف الدفعات الصغيرة ‪ .minibatches‬غالبًا ما تستخدم‬
‫التطبيقات الحديثة تسلسالت بأطوال مماثلة لتجنب إهدار الحساب المفرط على الحشو‪.‬‬

‫‪10.5.6‬‬
‫‪ .1‬جرب قيمًا مختلفة للوسيطة ‪max_examples‬يف طريقة ‪ ._tokenize‬كيف يؤثر‬
‫ذلك على أحجام مفردات اللغة المصدر واللغة الهدف؟‬
‫‪ .2‬ال يحتوي النصيف بعض اللغات مثل الصينية واليابانية على مؤشرات حدود الكلمات‬
‫(على سبيل المثال‪ ،‬المسافة)‪ .‬هل ال يزال الترميز على مستوى الكلمة فكرة جيدة لمثل‬
‫هذه الحاالت؟ لما ولما ال؟‬

‫‪Encoder-Decoder‬‬ ‫‪10.6‬‬
‫‪Architecture‬‬
‫في مسائل ‪ seq2seq‬العامة مثل الترجمة اآللية (القسم ‪ ،)10.5‬تكون المدخالت والمخرجات‬
‫ذات أطوال متفاوتة وغير محاذية‪ .‬يتمثل النهج القياسي لمعالجة هذا النوع من البياناتيف تصميم‬
‫معمارية المشفر‪-‬مفكك الشفرة ‪( encoder-decoder architecture‬الشكل ‪)10.6.1‬‬
‫تتكون من مكونين رئيسيين‪ :‬المشفر ‪ encoder‬يأخذ تسلسلًا متغير الطول كمدخل‪ ،‬ومفكك‬
‫الشفرة ‪ decoder‬يعمل كنموذج لغة شرطي‪ ،‬مع األخذيف االعتبار المدخالت المشفرة والسياق‬
‫األيسر للتسلسل المستهدف والتنبؤ بالرمز التالييف التسلسل المستهدف‪.‬‬

‫الشكل ‪ 10.6.1‬معمارية المشفر ومفكك الشفرة‪.‬‬

‫لنأخذ الترجمة اآللية من اإلنجليزية إلى الفرنسية كمثال‪ .‬بالنظر إلى تسلسل اإلدخال باللغة‬
‫اإلنجليزية‪ ،”.“ ،“ watching" ،“ are" ،“ They" :‬تقوم معمارية المشفر‪-‬مفكك الشفرة‬
‫هذه أوالً بتشفير المدخالت ذات الطول المتغير إلى حالة‪ ،‬ثم تقوم بفك تشفير الحالة إلنشاء‬
‫التسلسل المترجم‪ ،‬رمزاً رمزاً‪ ،‬كمخرج‪ ."." ، " regardent" ، " Ils" :‬نظرًا ألن معمارية المشفر‪-‬‬
‫مفكك الشفرة تشكل أساسًا لنماذج ‪ seq2seq‬المختلفةيف األقسام الالحقة‪ ،‬فإن هذا القسم‬
‫سيحول هذه المعمارية إلى واجهة سيتم تنفيذها الحقًا‪.‬‬

‫‪Encoder‬‬ ‫‪10.6.1‬‬
‫في واجهة المشفر‪ ،‬نحدد فقط أن المشفر يأخذ تسلسالت متغيرة الطول كمدخل ‪ .X‬سيتم توفير‬
‫التنفيذ بواسطة أي نموذج يرث كالس ‪ Encoder‬األساسية هذه‪.‬‬

‫‪import tensorflow as tf‬‬


259 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

from d2l import tensorflow as d2l

#@save
class Encoder(tf.keras.layers.Layer):
"""The base encoder interface for the encoder-
decoder architecture."""
def __init__(self):
super().__init__()

# Later there can be additional arguments (e.g.,


length excluding padding)
def call(self, X, *args):
raise NotImplementedError
Decoder 10.6.2
‫ إضافية لتحويل إخراج المشفر‬init_state ‫ نضيف دالة‬،‫في واجهة مفكك الشفرة التالية‬
‫ الحظ أن هذه الخطوة قد تتطلب‬.encoded state ‫) إلى الحالة المشفرة‬enc_outputs(
.10.5 ‫ والذي تم شرحهيف القسم‬،‫ لإلدخال‬valid length ‫ مثل الطول الصالح‬،‫مدخالت إضافية‬
‫يف كل مرة قد تقوم مفكك الشفرة بتعيين‬،token ‫إلنشاء رمز تسلسل متغير الطول بواسطة الرمز‬
‫ الرمز الذي تم إنشاؤهيف الخطوة الزمنية السابقة) والحالة المشفرةيف رمز‬،‫إدخال (على سبيل المثال‬
.‫إخراجيف الخطوة الزمنية الحالية‬

#@save
class Decoder(tf.keras.layers.Layer):
"""The base decoder interface for the encoder-
decoder architecture."""
def __init__(self):
super().__init__()

# Later there can be additional arguments (e.g.,


length excluding padding)
def init_state(self, enc_outputs, *args):
raise NotImplementedError

def call(self, X, state):


raise NotImplementedError
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪260‬‬

‫‪Putting the Encoder and‬‬ ‫‪10.6.3‬‬


‫‪Decoder Together‬‬
‫في االنتشار األمامي ‪ ،forward propagation‬يتم استخدام خرج المشفر إلنتاج الحالة‬
‫المشفرة‪ ،‬وسيتم استخدام هذه الحالة أيضًا بواسطة مفكك الشفرة كأحد مدخالته‪.‬‬

‫‪#@save‬‬
‫‪class EncoderDecoder(d2l.Classifier):‬‬
‫‪"""The base class for the encoder-decoder‬‬
‫"""‪architecture.‬‬
‫‪def __init__(self, encoder, decoder):‬‬
‫)(__‪super().__init‬‬
‫‪self.encoder = encoder‬‬
‫‪self.decoder = decoder‬‬

‫‪def call(self, enc_X, dec_X, *args):‬‬


‫‪enc_outputs = self.encoder(enc_X, *args,‬‬
‫)‪training=True‬‬
‫‪dec_state = self.decoder.init_state(enc_outputs,‬‬
‫)‪*args‬‬
‫‪# Return decoder output only‬‬
‫‪return self.decoder(dec_X, dec_state,‬‬
‫]‪training=True)[0‬‬
‫في القسم التالي‪ ،‬سنرى كيفية تطبيق ‪ RNNs‬لتصميم نماذج ‪ seq2seq‬بناءً على معمارية‬
‫المشفر‪-‬مفكك الشفرة هذه‪.‬‬

‫‪10.6.4‬‬
‫يمكن أن تتعامل معماريات المشفر‪-‬مفكك الشفرة مع المدخالت والمخرجات التي تتكون من‬
‫متواليات متغيرة الطول وبالتالي فهي مناسبة لمشاكل ‪ seq2seq‬مثل الترجمة اآللية‪ .‬يأخذ المشفر‬
‫‪ encoder‬تسلسلًا متغير الطول كمدخل ويحوله إلى حالة ذات شكل ثابت‪ .‬يقوم مفكك الشفرة‬
‫‪ decoder‬بتعيين الحالة المشفرة لشكل ثابت إلى تسلسل متغير الطول‪.‬‬

‫‪10.6.5‬‬
‫‪ .1‬لنفترض أننا نستخدم الشبكات العصبية لتنفيذ معمارية المشفر‪-‬مفكك الشفرة‪ .‬هل‬
‫يجب أن يكون المشفر ومفكك الشفرة من نفس نوع الشبكة العصبية؟‬
‫‪ .2‬إلى جانب الترجمة اآللية‪ ،‬هل يمكنك التفكيريف تطبيق آخر حيث يمكن تطبيق معمارية‬
‫الشفرة‪-‬مفكك الشفرة؟‬
‫‪261‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪Encoder-‬‬ ‫‪Seq2Seq‬‬ ‫‪10.7‬‬


‫‪Decoder Seq2Seq for Machine Translation‬‬
‫فيما يسمى بالمشكالت ‪ seq2seq‬مثل الترجمة اآللية ‪( machine translation‬كما تمت‬
‫مناقشتهيف القسم ‪ ،)10.5‬حيث تتكون كل من المدخالت والمخرجات من متواليات‬
‫(تسلسالت) متغيرة الطول غير محاذاة ‪ ،variable-length unaligned sequences‬فإننا‬
‫نعتمد عمومًا على معماريات المشفر‪-‬مفكك الشفرة ‪encoder-decoder architecture‬‬
‫(القسم ‪.)10.6‬يف هذا القسم‪ ،‬سوف نوضح تطبيق معمارية المشفر‪-‬مفكك الشفرة‪ ،‬حيث يتم‬
‫تنفيذ كل من المشفر ومفكك الشفرة على أنهما ‪ ،RNNs‬لمهمة الترجمة اآللية (‪،Cho et al.‬‬
‫‪.)2014 ،Sutskever et al. ،2014‬‬

‫هنا‪ ،‬سيأخذ المشفر ‪ RNN‬تسلسلًا متغير الطول كمدخل ويحوله إلى حالة مخفية ذات شكل‬
‫ثابت‪ .‬الحقًا‪،‬يف القسم ‪ ،11‬سنقدم آليات االنتباه ‪ ،attention mechanisms‬والتي تسمح لنا‬
‫بالوصول إلى المدخالت المشفرة دون الحاجة إلى ضغط المدخالت بالكامليف تمثيل واحد ذي‬
‫طول ثابت‪.‬‬

‫بعد ذلك‪ ،‬إلنشاء تسلسل اإلخراج‪ ،‬رمز واحديف كل مرة‪ ،‬سيتنبأ نموذج وحدة مفكك الشفرة‬
‫‪ ،decoder model‬الذي يتكون من ‪ RNN‬منفصل‪ ،‬بكل رمز مستهدف متتالي بالنظر إلى كل‬
‫من تسلسل اإلدخال والرموز السابقةيف المخرجات‪ .‬أثناء التدريب‪ ،‬عادةً ما يكون مفكك الشفرة‬
‫مشروطًا بالرموز السابقةيف التسمية الحقيقية "‪ "Ground-Truth‬الرسمي‪ .‬ومع ذلك‪،‬يف وقت‬
‫االختبار‪ ،‬سنرغبيف تكييف كل إخراج من مفكك الشفرة على الرموز التي تم توقعها بالفعل‪.‬‬
‫الحظ أنه إذا تجاهلنا المشفر‪ ،‬فإن مفكك الشفرةيف بنية ‪ seq2seq‬تتصرف تمامًا مثل نموذج‬
‫اللغة العادي‪ .‬يوضح الشكل ‪ 10.7.1‬كيفية استخدام ‪ RNNs‬تعلم التسلسل للتسلسليف الترجمة‬
‫اآللية‪.‬‬

‫الشكل ‪ 10.7.1‬تعلم التسلسل للتسلسل باستخدام مشفر ‪ RNN‬ومفكك شفرة ‪.RNN‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪262‬‬

‫في الشكل ‪ ،10.7.1‬يشير الرمز "<‪ ">eos‬إلى نهاية التسلسل‪ .‬يمكن أن يتوقف نموذجنا عن إجراء‬
‫تنبؤات بمجرد إنشاء هذا الرمز‪.‬يف الخطوة الزمنية األولية لمفكك شفرة ‪ ،RNN‬هناك قراران‬
‫تصميم خاصان يجب أن تكون على دراية بهما‪ :‬أوالً‪ ،‬نبدأ كل إدخال برمز لبداية التسلسل‬
‫"<‪ .">bos‬ثانيًا‪ ،‬قد نقوم بتغذية الحالة المخفية النهائية للمشفريف مفكك الشفرةيف كل خطوة‬
‫زمنية لمفكك الشفرة (‪.)2014 ،Cho et al.‬يف بعض التصميمات األخرى‪ ،‬مثل ‪Sutskever‬‬
‫‪ ،)2014( .et al‬تُستخدم الحالة المخفية النهائية لمشفر ‪ RNN‬لبدء الحالة المخفية لمفكك‬
‫الشفرة فقطيف خطوة مفكك الشفرة األولى‪.‬‬

‫‪Teacher Forcing‬‬ ‫‪10.7.1‬‬


‫أثناء تشغيل المشفر على تسلسل اإلدخال أمر بسيط نسبيًا‪ ،‬فإن كيفية التعامل مع مدخالت‬
‫ومخرجات مفكك الشفرة تتطلب مزيدًا من العناية‪ .‬يُطلق على النهج األكثر شيوعًا أحيانًا اسم‬
‫إجبار المعلم ‪ .teacher forcing‬هنا‪ ،‬يتم تغذية التسلسل الهدف األصلي (تسميات الرمز‬
‫‪)token labels‬يف مفكك الشفرة كمدخل‪ .‬بشكل أكثر تحديدًا‪ ،‬يتم تجميع رمز بداية التسلسل‬
‫الخاص والتسلسل المستهدف األصلي‪ ،‬باستثناء الرمز النهائي‪ ،‬كمدخل إلى مفكك الشفرة‪،‬يف ‬
‫حين أن إخراج مفكك الشفرة (تسميات التدريب) هو التسلسل الهدف األصلي‪ ،‬ويتم إزاحته‬
‫بواسطة رمز واحد‪">eos<" ، "." ، " regardent" ، "Ils" "." ، " regardent" ، ""Ils ،bos>" <" :‬‬
‫(الشكل ‪.)10.7.1‬‬

‫تطبيقنايف القسم ‪ 10.5.3‬بيانات تدريب مُعدّة إلجبار المعلم‪ ،‬حيث يشبه تحويل الرموز للتعلم‬
‫تحت اإلشراف الذاتي تدريب النماذج اللغويةيف القسم ‪ .9.3‬تتمثل الطريقة البديلةيف تغذية الرمز‬
‫المتوقع من الخطوة الزمنية السابقة كمدخل حالي إلى مفكك الشفرة‪.‬‬

‫فيما يلي‪ ،‬نشرح التصميم الموضحيف الشكل ‪ 10.7.1‬بمزيد من التفصيل‪ .‬سنقوم بتدريب هذا‬
‫النموذج للترجمة اآللية على مجموعة البيانات اإلنجليزية‪-‬الفرنسية كما هو مقدميف القسم ‪.10.5‬‬

‫‪import collections‬‬
‫‪import math‬‬
‫‪import tensorflow as tf‬‬
‫‪from d2l import tensorflow as d2l‬‬
‫‪Encoder‬‬ ‫‪10.7.2‬‬
‫تذكر أن المشفر يحول تسلسل إدخال متغير الطول إلى متغير سياق ثابت الشكل (انظر الشكل‬
‫‪.)10.7.1‬‬

‫ضعيف اعتبارك مثال تسلسل واحد (حجم الدُفعة ‪ .)1‬افترض أن تسلسل اإلدخال هو 𝑇𝑥 ‪𝑥1 , … ,‬‬
‫حيث 𝑡𝑥 هو ‪ 𝑡 th‬الرمز‪.‬يف الخطوة الزمنية 𝑡 ‪ ،‬يقوم ‪ RNN‬بتحويل متجه ميزة اإلدخال 𝑡𝐱 لـ 𝑡𝑥‬
‫‪263‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫والحالة المخفية ‪ 𝐡𝑡−1‬من الخطوة الزمنية السابقة إلى الحالة المخفية الحالية 𝑡𝐡‪ .‬يمكننا‬
‫استخدام دالة 𝑓 للتعبير عن تحول الطبقة المتكررة لـ ‪:RNN‬‬

‫‪𝐡𝑡 = 𝑓(𝐱𝑡 , 𝐡𝑡−1 ).‬‬

‫بشكل عام‪ ،‬يحول المشفر الحاالت المخفيةيف جميع الخطوات الزمنية إلى متغير سياق من خالل‬
‫دالة مخصصة 𝑞‪:‬‬

‫‪𝐜 = 𝑞(𝐡1 , … , 𝐡 𝑇 ).‬‬

‫على سبيل المثال‪،‬يف الشكل ‪ ،10.7.1‬متغير السياق هو فقط الحالة المخفية 𝑇 𝐡 المقابلة لتمثيل‬
‫المشفر ‪ RNN‬بعد معالجة الرمز النهائي لتسلسل اإلدخال‪.‬‬

‫في هذا المثال‪ ،‬استخدمنا ‪ RNN‬أحادي االتجاه ‪ unidirectional‬لتصميم المشفر‪ ،‬حيث‬


‫تعتمد الحالة المخفية فقط على المدخالت الالحقةيف وقبل الخطوة الزمنية للحالة المخفية‪.‬‬
‫يمكننا أيضًا إنشاء مشفرات باستخدام ‪ RNNs‬ثنائية االتجاه ‪.bidirectional‬يف هذه الحالة‪،‬‬
‫تعتمد الحا لة المخفية على الخطوة الالحقة قبل الخطوة الزمنية وبعدها (بمايف ذلك اإلدخاليف ‬
‫الخطوة الزمنية الحالية)‪ ،‬والتي تشفر معلومات التسلسل بأكمله‪.‬‬

‫فلنبدأ اآلنيف تنفيذ مشفر ‪ .RNN‬الحظ أننا نستخدم طبقة التضمين ‪embedding layer‬‬
‫للحصول على متجه المعالم لكل رمزيف تسلسل اإلدخال‪ .‬وزن طبقة التضمين هو مصفوفة‪ ،‬حيث‬
‫يتوافق عدد الصفوف مع حجم مفردات اإلدخال (‪ )vocab_size‬ويتوافق عدد األعمدة مع‬
‫أبعاد متجه المعالم (‪ .)embed_size‬بالنسبة ألي فهرس رمز إدخال 𝑖 ‪ ،‬تجلب طبقة التضمين‬
‫لـ ‪ 𝑖 th‬الصف (بدءًا من ‪ )0‬من مصفوفة الوزن إلرجاع متجه الميزة الخاص بها‪ .‬هنا نقوم بتنفيذ‬
‫المشفر باستخدام ‪ GRU‬متعدد الطبقات‪.‬‬

‫‪class Seq2SeqEncoder(d2l.Encoder): #@save‬‬


‫‪"""The RNN encoder for sequence to sequence‬‬
‫"""‪learning.‬‬
‫‪def __init__(self, vocab_size, embed_size,‬‬
‫‪num_hiddens, num_layers,‬‬
‫‪dropout=0):‬‬
‫)(__‪super().__init‬‬
‫= ‪self.embedding‬‬
‫)‪tf.keras.layers.Embedding(vocab_size, embed_size‬‬
‫‪self.rnn = d2l.GRU(num_hiddens, num_layers,‬‬
‫)‪dropout‬‬

‫‪def call(self, X, *args):‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪264‬‬

‫)‪# X shape: (batch_size, num_steps‬‬


‫))‪embs = self.embedding(tf.transpose(X‬‬
‫‪# embs shape: (num_steps, batch_size,‬‬
‫)‪embed_size‬‬
‫)‪output, state = self.rnn(embs‬‬
‫‪# output shape: (num_steps, batch_size,‬‬
‫)‪num_hiddens‬‬
‫‪# state shape: (num_layers, batch_size,‬‬
‫)‪num_hiddens‬‬
‫‪return output, state‬‬
‫دعنا نستخدم مثالًا ملموسًا لتوضيح تنفيذ المشفر أعاله‪ .‬أدناه‪ ،‬نقوم بإنشاء مثيل لـ ‪ GRU‬مشفر‬
‫من طبقتين عدد وحداته المخفية هو ‪ .16‬بالنظر إلى الدفعات الصغيرة ‪ minibatch‬لمدخالت‬
‫التسلسل ‪( X‬حجم الدُفعة‪ ،4 :‬عدد خطوات الوقت‪ ،)9 :‬الحاالت المخفية للطبقة األخيرة طوال‬
‫الوقت الخطوات (المخرجات التي يتم إرجاعها بواسطة الطبقات المتكررة للمشفر) هي موتر‬
‫للشكل (عدد خطوات الوقت‪ ،‬حجم الدفعة‪ ،‬عدد الوحدات المخفية)‪.‬‬

‫‪vocab_size, embed_size, num_hiddens, num_layers = 10, 8,‬‬


‫‪16, 2‬‬
‫‪batch_size, num_steps = 4, 9‬‬

‫‪encoder = Seq2SeqEncoder(vocab_size, embed_size,‬‬


‫)‪num_hiddens, num_layers‬‬
‫))‪X = tf.zeros((batch_size, num_steps‬‬
‫)‪outputs, state = encoder(X‬‬

‫‪d2l.check_shape(outputs, (num_steps, batch_size,‬‬


‫))‪num_hiddens‬‬
‫نظرًا ألننا نستخدم ‪ GRU‬هنا‪ ،‬فإن شكل الحاالت المخفية متعددة الطبقاتيف الخطوة الزمنية‬
‫النهائية هو (عدد الطبقات المخفية‪ ،‬حجم الدُفعة‪ ،‬عدد الوحدات المخفية)‪.‬‬

‫‪Decoder‬‬ ‫‪10.7.3‬‬
‫بالنظر إلى تسلسل اإلخراج المستهدف ‪ 𝑦1 , 𝑦2 , … , 𝑦 𝑇 ′‬لكل خطوة زمنية ‪( 𝑡 ′‬نستخدم ‪ 𝑡 ′‬للتمييز‬
‫عن خطوات وقت تسلسل اإلدخال)‪ ،‬يقوم مفكك الشفرة بتعيين احتمالية متوقعة لكل رمز ممكن‬
‫يحدثيف الخطوة ‪ 𝑦𝑡 ′ +1‬المشروطة بالرموز السابقةيف الهدف ‪ 𝑦1 , … , 𝑦𝑡 ′‬ومتغير السياق 𝐜 ‪ ،‬أي‬
‫)𝐜 ‪. 𝑃(𝑦𝑡 ′ +1 ∣ 𝑦1 , … , 𝑦𝑡 ′ ,‬‬
‫‪265‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫للتنبؤ بالرمز الالحق ‪𝑡 ′ + 1‬يف التسلسل المستهدف‪ ،‬يأخذ مفكك شفرة ‪ RNN‬الرمز الهدف‬
‫للخطوة السابقة ‪ ، 𝑦𝑡 ′‬وحالة ‪ RNN‬المخفية من الخطوة الزمنية السابقة ‪ ، 𝐬𝑡 ′ −1‬ومتغير السياق‬
‫𝐜 كمدخالت‪ ،‬ويحولهم إلى الحالة المخفية ‪𝐬𝑡 ′‬يف الخطوة الزمنية الحالية‪ .‬يمكننا استخدام دالة‬
‫𝑔 للتعبير عن تحول الطبقة المخفية لمفكك الشفرة‪:‬‬

‫‪𝐬𝑡 ′ = 𝑔(𝑦𝑡 ′ −1 , 𝐜, 𝐬𝑡 ′ −1 ).‬‬

‫بعد الحصول على الحالة المخفية لمفكك الشفرة‪ ،‬يمكننا استخدام طبقة اإلخراج وعملية‬
‫‪softmax‬لحساب التوزيع التنبئي )𝐜 ‪ 𝑝(𝑦𝑡 ′ +1 ∣ 𝑦1 , … , 𝑦𝑡 ′ ,‬على رمز اإلخراج التالي ‪𝑡 ′ +‬‬
‫‪.1‬‬

‫باتباع الشكل ‪ ،10.7.1‬عند تنفيذ مفكك الشفرة على النحو التالي‪ ،‬فإننا نستخدم الحالة المخفية‬
‫مباشرةًيف الخطوة الزمنية النهائية للمشفر لتهيئة الحالة المخفية لمفكك الشفرة‪ .‬يتطلب ذلك أن‬
‫يكون لمشفر ‪ RNN‬ومفكك شفرة ‪ RNN‬نفس عدد الطبقات والوحدات المخفية‪ .‬لمزيد من‬
‫دمج معلومات تسلسل اإلدخال المشفر‪ ،‬يكون متغير السياق متسلسلًا مع إدخال مفكك الشفرة‬
‫في جميع خطوات الوقت‪ .‬للتنبؤ بالتوزيع االحتمالي للرمز الناتج‪ ،‬نستخدم طبقة متصلة بالكامل‬
‫لتحويل الحالة المخفيةيف الطبقة األخيرة من مفكك شفرة ‪.RNN‬‬

‫‪class Seq2SeqDecoder(d2l.Decoder):‬‬
‫‪"""The RNN decoder for sequence to sequence‬‬
‫"""‪learning.‬‬
‫‪def __init__(self, vocab_size, embed_size,‬‬
‫‪num_hiddens, num_layers,‬‬
‫‪dropout=0):‬‬
‫)(__‪super().__init‬‬
‫= ‪self.embedding‬‬
‫)‪tf.keras.layers.Embedding(vocab_size, embed_size‬‬
‫‪self.rnn = d2l.GRU(num_hiddens, num_layers,‬‬
‫)‪dropout‬‬
‫)‪self.dense = tf.keras.layers.Dense(vocab_size‬‬

‫‪def init_state(self, enc_outputs, *args):‬‬


‫]‪return enc_outputs[1‬‬

‫‪def call(self, X, enc_state):‬‬


‫)‪# X shape: (batch_size, num_steps‬‬
‫‪# embs shape: (num_steps, batch_size,‬‬
‫)‪embed_size‬‬
‫))‪embs = self.embedding(tf.transpose(X‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 266

# context shape: (batch_size, num_hiddens)


context = enc_state[-1]
# Broadcast context to (num_steps, batch_size,
num_hiddens)
context = tf.tile(tf.expand_dims(context, 0),
(embs.shape[0], 1, 1))
# Concat at the feature dimension
embs_and_context = tf.concat((embs, context), -
1)
outputs, state = self.rnn(embs_and_context,
enc_state)
outputs = tf.transpose(self.dense(outputs), (1,
0, 2))
# outputs shape: (batch_size, num_steps,
vocab_size)
# state shape: (num_layers, batch_size,
num_hiddens)
return outputs, state
‫ أدناه نقوم بإنشاء مثيل لها باستخدام نفس المعلمات الفائقة من‬،‫لتوضيح مفكك الشفرة المنفذ‬
‫ عدد‬،‫ يصبح شكل إخراج مفكك الشفرة (حجم الدُفعة‬،‫ كما نرى‬.‫المشفر المذكورة أعاله‬
.‫ حيث يخزن البعد األخير للموتر توزيع الرمز المتوقع‬،)‫ حجم المفردات‬،‫الخطوات الزمنية‬

decoder = Seq2SeqDecoder(vocab_size, embed_size,


num_hiddens, num_layers)
state = decoder.init_state(encoder(X))
outputs, state = decoder(X, state)

d2l.check_shape(outputs, (batch_size, num_steps,


vocab_size))
d2l.check_len(state, num_layers)
d2l.check_shape(state[0], (batch_size, num_hiddens))
.‫ أعاله‬RNN ‫مفكك شفرة‬-‫ الطبقاتيف نموذج مشفر‬10.7.2 ‫ يوضح الشكل‬،‫للتلخيص‬

Encoder- 10.7.4
Decoder for Sequence to Sequence Learning
:‫ينتج عن وضع كل ذلك معًايف التعليمات البرمجية ما يلي‬

class Seq2Seq(d2l.EncoderDecoder): #@save


def __init__(self, encoder, decoder, tgt_pad, lr):
super().__init__(encoder, decoder)
self.save_hyperparameters()
‫‪267‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪def validation_step(self, batch):‬‬


‫)]‪Y_hat = self(*batch[:-1‬‬
‫‪self.plot('loss', self.loss(Y_hat, batch[-1]),‬‬
‫)‪train=False‬‬

‫‪def configure_optimizers(self):‬‬
‫‪# Adam optimizer is used here‬‬
‫‪return‬‬
‫)‪tf.keras.optimizers.Adam(learning_rate=self.lr‬‬

‫الشكل ‪ 10.7.2‬طبقاتيف نموذج مشفر‪-‬مفكك شفرة‪. RNN‬‬

‫‪Loss Function with Masking‬‬ ‫‪10.7.5‬‬


‫في كل خطوة زمنية‪ ،‬يتنبأ مفكك الشفرة بتوزيع احتمالي لرموز اإلخراج‪ .‬كما هو الحال مع نمذجة‬
‫اللغة‪ ،‬يمكننا تطبيق ‪ softmax‬للحصول على التوزيع وحساب خطأ االنتروبيا المتقاطعة من أجل‬
‫التحسين‪ .‬تذكر القسم ‪ 10.5‬أن رموز الحشو الخاصة يتم إلحاقها بنهاية التسلسالت بحيث يمكن‬
‫تحميل التسلسالت ذات األطوال المتفاوتة بكفاءةيف دفعات صغيرة من نفس الشكل‪ .‬ومع ذلك‪،‬‬
‫ينبغي استبعاد التنبؤ بالرموز للحشو من حسابات الخطأ‪ .‬تحقيقا لهذه الغاية‪ ،‬يمكننا إخفاء ‪mask‬‬
‫المدخالت غير ذات الصلة بقيم صفرية بحيث يكون ضرب أي تنبؤ غير ذي صلة بصفر يساوي‬
‫صفرًا‪.‬‬

‫)‪@d2l.add_to_class(Seq2Seq‬‬
‫‪def loss(self, Y_hat, Y):‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 268

l = super(Seq2Seq, self).loss(Y_hat, Y,
averaged=False)
mask = tf.cast(tf.reshape(Y, -1) != self.tgt_pad,
tf.float32)
return tf.reduce_sum(l * mask) / tf.reduce_sum(mask)
Training 10.7.6
‫التسلسل على‬-‫ للتعلم التسلسل‬RNN ‫مفكك شفرة‬-‫اآلن يمكننا إنشاء وتدريب نموذج مشفر‬
.‫مجموعة بيانات الترجمة اآللية‬

data = d2l.MTFraEng(batch_size=128)
embed_size, num_hiddens, num_layers, dropout = 256, 256,
2, 0.2
with d2l.try_gpu():
encoder = Seq2SeqEncoder(
len(data.src_vocab), embed_size, num_hiddens,
num_layers, dropout)
decoder = Seq2SeqDecoder(
len(data.tgt_vocab), embed_size, num_hiddens,
num_layers, dropout)
model = Seq2Seq(encoder, decoder,
tgt_pad=data.tgt_vocab['<pad>'],
lr=0.001)
trainer = d2l.Trainer(max_epochs=50,
gradient_clip_val=1)
trainer.fit(model, data)
269 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

Prediction 10.7.7.
‫ يتم إدخال الرمز المتوقع من الخطوة الزمنية السابقةيف مفكك‬،‫للتنبؤ بتسلسل اإلخراجيف كل خطوة‬
‫ تتمثل إحدى اإلستراتيجيات البسيطةيف أخذ عينة من أي رمز حدده مفكك‬.‫الشفرة كمدخل‬
،‫يف الخطوة الزمنية األولية‬،‫ كما هو الحاليف التدريب‬.‫الشفرة ألعلى احتمال عند التنبؤيف كل خطوة‬
‫ عملية التنبؤ هذه موضحةيف الشكل‬.‫<"( في مفكك الشفرة‬bos>") ‫يتم تغذية رمز بداية التسلسل‬
.‫ يكون تنبؤ تسلسل اإلخراج قد اكتمل‬، ("<eos>")‫ عندما يتم توقع رمز نهاية التسلسل‬.10.7.3

.RNN ‫مفكك شفرة‬-‫ توقع رمز تسلسل الخرج برمز باستخدام مشفر‬10.7.3 ‫الشكل‬

beam search ‫ سوف نقدم استراتيجيات أكثر تعقيدًا بناءً على البحث الشعاعي‬،‫في القسم التالي‬
.)10.8 ‫(القسم‬

@d2l.add_to_class(d2l.EncoderDecoder) #@save
def predict_step(self, batch, device, num_steps,
save_attention_weights=False):
src, tgt, src_valid_len, _ = batch
enc_outputs = self.encoder(src, src_valid_len,
training=False)
dec_state = self.decoder.init_state(enc_outputs,
src_valid_len)
outputs, attention_weights =
[tf.expand_dims(tgt[:,0], 1), ], []
for _ in range(num_steps):
Y, dec_state = self.decoder(outputs[-1],
dec_state, training=False)
outputs.append(tf.argmax(Y, 2))
# Save attention weights (to be covered later)
if save_attention_weights:

attention_weights.append(self.decoder.attention_weights)
return tf.concat(outputs[1:], 1), attention_weights
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪270‬‬

‫‪Evaluation of Predicted‬‬ ‫‪10.7.8‬‬


‫‪Sequences‬‬
‫يمكننا تقييم تسلسل متوقع من خالل مقارنته بالتسلسل المستهدف (الحقيقة)‪ .‬ولكن ما هو‬
‫بالضبط المقياس المناسب لمقارنة التشابه بين تسلسلين؟‬

‫‪( BLEU‬دراسة التقييم ثنائي اللغة ‪ ، )Bilingual Evaluation Understudy‬على الرغم من‬
‫اقتراحهايف األصل لتقييم نتائج الترجمة اآللية ( ‪ ، )2002 ،Papineni et al.‬فقد تم استخدامها‬
‫على نطاق واسعيف قياس جودة تسلسل المخرجات للتطبيقات المختلفة‪ .‬من حيث المبدأ‪ ،‬بالنسبة‬
‫ألي 𝑛 ‪Grams-‬يف التسلسل المتوقع‪ ،‬تقوم ‪ BLEU‬بتقييم ما إذا كانت هذه 𝑛 ‪ Grams-‬تظهر‬
‫في التسلسل المستهدف‪.‬‬

‫𝑛𝑝 تدل على دقة 𝑛 ‪ ،grams-‬وهي نسبة عدد 𝑛 ‪ Grams-‬المتطابقةيف التسلسل المتوقع‬
‫والهدف إلى عدد 𝑛 ‪grams-‬يف التسلسل المتوقع‪ .‬لشرح‪ ،‬بالنظر إلى التسلسل المستهدف 𝐴 ‪،‬‬
‫𝐵 ‪ 𝐹 ، 𝐸 ، 𝐷 ، 𝐶 ،‬والتسلسل المتوقع‪ ، 𝐷 ، 𝐵 ، 𝐵 ، 𝐴،‬لدينا‪، 𝑝2 = 3/4 ، 𝑝1 = 4/5،‬‬
‫‪ 𝑝3 = 1/3‬و‪ . 𝑝4 = 0‬إلى جانب ذلك‪ ،‬ليكن ‪ lenlabel‬و ‪ lenpred‬أن يكون عدد الرموزيف ‬
‫التسلسل المستهدف والتسلسل المتوقع‪ ،‬على التوالي‪ .‬بعد ذلك‪ ،‬يتم تعريف ‪ BLEU‬على أنه‬
‫𝑘‬
‫‪lenlabel‬‬ ‫𝑛‪1/2‬‬
‫‪exp (𝑚𝑖𝑛(0,1 −‬‬ ‫∏ ))‬ ‫𝑛𝑝‬ ‫‪,‬‬
‫‪lenpred‬‬
‫‪𝑛=1‬‬

‫حيث 𝑘 هي أطول 𝑛 ‪-‬غرام للمطابقة‪.‬‬

‫استنادًا إلى تعريف ‪BLEU‬يف (‪ ،)10.7.4‬كلما كان التسلسل المتوقع هو نفسه التسلسل‬
‫المستهدف‪ ،‬يكون ‪ BLEU‬هو ‪ .1‬عالوة على ذلك‪ ،‬نظرًا ألن مطابقة الغرام األطول أكثر صعوبة‪،‬‬
‫فإن ‪ BLEU‬تعين وزناً أكبر لدقة الغرام األطول‪ .‬على وجه التحديد‪ ،‬عندما يتم إصالح 𝑛𝑝 ‪،‬‬
‫𝑛‪1/‬‬ ‫𝑛‪1/2‬‬
‫𝑛𝑝)‪ .‬عالوة على ذلك‪ ،‬نظرًا ألن التنبؤ‬ ‫𝑛𝑝 يزداد مع نمو 𝑛 (يستخدم الورق األصلي‬
‫بالتسلسالت األقصر يميل إلى الحصول على قيمة 𝑛𝑝 أعلى‪ ،‬فإن المعامل قبل حد الضربيف ‬
‫(‪ ) 10.7.4‬يعاقب التسلسالت األقصر المتوقعة‪ .‬على سبيل المثال‪ ،‬عندما ‪ ، 𝑘 = 2‬بالنظر إلى‬
‫التسلسل المستهدف 𝐴 ‪ 𝐹 ، 𝐸 ، 𝐷 ، 𝐶 ، 𝐵 ،‬والتسلسل المتوقع 𝐴 ‪ 𝐵 ،‬على الرغم من أن‬
‫عامل الجزاء ‪ exp (1 − 6/2) ≈ 0.14‬اقل من ‪.BLEU‬‬

‫نقوم بتنفيذ مقياس ‪ BLEU‬على النحو التالي‪.‬‬

‫‪def bleu(pred_seq, label_seq, k):‬‬ ‫‪#@save‬‬


‫"""‪"""Compute the BLEU.‬‬
271 ‫ الشبكات العصبية المتكررة الحديثة‬:‫الفصل العاشر‬

pred_tokens, label_tokens = pred_seq.split(' '),


label_seq.split(' ')
len_pred, len_label = len(pred_tokens),
len(label_tokens)
score = math.exp(min(0, 1 - len_label / len_pred))
for n in range(1, min(k, len_pred) + 1):
num_matches, label_subs = 0,
collections.defaultdict(int)
for i in range(len_label - n + 1):
label_subs[' '.join(label_tokens[i: i + n])]
+= 1
for i in range(len_pred - n + 1):
if label_subs[' '.join(pred_tokens[i: i +
n])] > 0:
num_matches += 1
label_subs[' '.join(pred_tokens[i: i +
n])] -= 1
score *= math.pow(num_matches / (len_pred - n +
1), math.pow(0.5, n))
return score
‫ المدربة لترجمة بعض الجمل اإلنجليزية إلى‬RNN ‫مفكك شفرة‬-‫ نستخدم مشفر‬،‫في النهاية‬
.‫ للنتائج‬BLEU ‫الفرنسية وحساب‬

engs = ['go .', 'i lost .', 'he\'s calm .', 'i\'m home
.']
fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je
suis chez moi .']
preds, _ = model.predict_step(
data.build(engs, fras), d2l.try_gpu(),
data.num_steps)
for en, fr, p in zip(engs, fras, preds):
translation = []
for token in data.tgt_vocab.to_tokens(p):
if token == '<eos>':
break
translation.append(token)
print(f'{en} => {translation}, bleu,'
f'{bleu(" ".join(translation), fr, k=2):.3f}')
go . => ['<unk>', '!'], bleu,0.000
i lost . => ["j'ai", '<unk>', '.'], bleu,0.000
he's calm . => ['<unk>', 'tom', '.'], bleu,0.000
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪272‬‬

‫‪i'm home . => ['je', 'suis', 'suis', '<unk>', '<unk>',‬‬


‫‪'gentil', 'gentil', 'gentil', 'aille'], bleu,0.280‬‬
‫‪10.7.9‬‬
‫بعد تصميم معمارية المشفر‪-‬مفكك الشفرة ‪ ،encoder-decoder architecture‬يمكننا‬
‫استخدام اثنين من ‪ RNN‬لتصميم نموذج تعلم التسلسل للمتسلسل ‪sequence to‬‬
‫‪.sequence learning‬يف تدريب المشفر‪-‬مفكك الشفرة‪ ،‬يقوم أسلوب إجبار المعلم ‪teacher‬‬
‫‪ forcing‬بتغذية تسلسالت اإلخراج األصلية (على عكس التنبؤات)يف مفكك الشفرة‪ .‬عند تنفيذ‬
‫المشفر ومفكك الشفرة‪ ،‬يمكننا استخدام ‪ RNNs‬متعددة الطبقات‪ .‬يمكننا استخدام األقنعة‬
‫‪ masks‬لتصفية الحسابات غير ذات الصلة‪ ،‬كما هو الحال عند حساب الخطأ‪ .‬بالنسبة لتقييم‬
‫تسلسل المخرجات‪ ،‬فإن ‪ BLEU‬هو مقياس شائع عن طريق مطابقة 𝑛 ‪-‬جرام بين التسلسل‬
‫المتوقع والتسلسل المستهدف‪.‬‬

‫‪10.7.10‬‬
‫‪ .1‬هل يمكنك ضبط المعلمات الفائقة لتحسين نتائج الترجمة؟‬
‫‪ .2‬أعد تشغيل التجربة بدون استخدام األقنعةيف حساب الخطأ‪ .‬ما هي النتائج التي‬
‫تالحظها؟ لماذا؟‬
‫‪ .3‬إذا اختلف المشفر ‪ encoder‬ومفكك الشفرة ‪decoder‬يف عدد الطبقات أو عدد‬
‫الوحدات المخفية‪ ،‬فكيف يمكننا تهيئة الحالة المخفية لمفكك الشفرة؟‬
‫‪ .4‬في التدريب‪ ،‬استبدل إجبار المعلم بتغذية التنبؤيف الخطوة الزمنية السابقةيف مفكك‬
‫الشفرة‪ .‬كيف يؤثر هذا على األداء؟‬
‫‪ .5‬أعد تشغيل التجربة عن طريق استبدال ‪ GRU‬بـ ‪.LSTM‬‬
‫‪ .6‬هل هناك أي طرق أخرى لتصميم طبقة اإلخراج لمفكك الشفرة؟‬

‫‪Beam Search‬‬ ‫‪10.8‬‬


‫في القسم ‪ ،10.7‬قدمنا معمارية المشفر‪-‬مفكك الشفرة‪ ،‬والتقنيات القياسية لتدريبهم من طرف‬
‫إلى طرف‪ .‬ومع ذلك‪ ،‬عندما يتعلق األمر بالتنبؤ بوقت االختبار‪ ،‬فقد ذكرنا فقط استراتيجية الجشع‬
‫‪ ،greedy strategy‬حيث نختاريف كل خطوة الرمز نظرًا ألعلى احتمالية متوقعة للظهور التالي‪،‬‬
‫حتى‪،‬يف وقت ما‪ ،‬نجد أننا توقعنا رمز مميز لنهاية التسلسل "<‪.">eos‬يف هذا القسم‪ ،‬سنبدأ بإضفاء‬
‫الطابع الرسمي على استراتيجية البحث الجشع ‪ Greedy Search‬هذه وتحديد بعض‬
‫المشكالت التي يميل الممارسون إلى مواجهتها‪ .‬بعد ذلك‪ ،‬قمنا بمقارنة هذه اإلستراتيجية مع‬
‫بديلين‪ :‬بحث شامل ‪( exhaustive search‬توضيحي ولكن ليس عمليًا) وبحث شعاعي‬
‫‪( beam search‬الطريقة القياسيةيف الممارسة)‪.‬‬
‫‪273‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫لنبدأ بإعداد التدوين الرياضي ‪ ،mathematical notation‬واستعارة االصطالحات من القسم‬


‫‪.10.7‬يف أي خطوة زمنية ‪ ، 𝑡 ′‬يُخرج مفكك الشفرة تنبؤات تمثل احتمالية كل رمزيف المفردات‬
‫القادمةيف التسلسل (القيمة المحتملة لـ ‪ ، 𝑦𝑡 ′ +1‬المشروطة بالرموز السابقة ‪ 𝑦1 , … , 𝑦𝑡 ′‬ومتغير‬
‫السياق 𝐜 ‪ ،‬التي ينتجها المشفر لتمثيل تسلسل اإلدخال‪ .‬تحديد التكلفة الحسابية‪ ،‬يتم اإلشارة‬
‫إليها بواسطة 𝒴 مفردات اإلخراج (بمايف ذلك الرمز الخاص بنهاية التسلسل "<‪ .)">eos‬دعنا‬
‫أيضًا نحدد الحد األقصى لعدد الرموز لتسلسل المخرجات كما هو ‪ .𝑇 ′‬هدفنا هو البحث عن‬
‫‪′‬‬
‫مخرجات مثالية من جميع ) 𝑇|𝒴|(𝒪 تسلسالت اإلخراج الممكنة‪ .‬الحظ أن هذا يبالغ قليالًيف ‬
‫تقدير عدد المخرجات المميزة ألنه ال توجد رموز الحقة بعد حدوث المميز "<‪ .">eos‬ومع‬
‫ذلك‪ ،‬ألغراضنا‪ ،‬يلتقط هذا الرقم حجم مساحة البحث تقريبًا‪.‬‬

‫‪Greedy Search‬‬ ‫‪10.8.1‬‬


‫ضعيف اعتبارك استراتيجية البحث الجشع ‪ Greedy Search‬البسيطة من القسم ‪ .10.7‬هنا‪،‬يف ‬
‫أي خطوة زمنية ‪ ، 𝑡 ′‬نختار ببساطة الرمز بأعلى احتمالية شرطية من 𝒴 ‪ ،‬على سبيل المثال‪،‬‬

‫‪𝑦𝑡 ′ = argmax𝑃(𝑦 ∣ 𝑦1 , … , 𝑦𝑡 ′ −1 , 𝐜).‬‬


‫𝒴∈𝑦‬

‫بمجرد أن يخرج نموذجنا "<‪( ">eos‬أو نصل إلى الحد األقصى للطول ‪ ،)𝑇 ′‬يكتمل تسلسل‬
‫اإلخراج‪.‬‬

‫قد تبدو هذه اإلستراتيجية معقولة‪ ،‬وهييف الحقيقة ليست سيئة للغاية! بالنظر إلى مدى تساهله‬
‫من الناحية الحسابية‪ ،‬ستتعرض لضغوط شديدة للحصول على المزيد من الفوائد مقابل أموالك‪.‬‬
‫ومع ذلك‪ ،‬إذا وضعنا الكفاءة جانباً لمدة دقيقة‪ ،‬فقد يبدو من المعقول أكثر البحث عن التسلسل‬
‫األكثر احتماالً‪ ،‬وليس تسلسل الرموز (المختارة بطمع) على األرجح‪ .‬اتضح أن هذين الكائنين‬
‫يمكن أن يكونا مختلفين تمامًا‪ .‬التسلسل األكثر احتماال هو الذي يقوم بتكبير التعبير‬
‫‪′‬‬
‫‪.∏𝑇𝑡 ′ =1‬يف مثال الترجمة اآللية لدينا‪ ،‬إذا استعاد مفكك الشفرة‬ ‫)𝐜 ‪𝑃(𝑦𝑡 ′ ∣ 𝑦1 , … , 𝑦𝑡 ′ −1 ,‬‬
‫حقًا احتماالت العملية التوليدية األساسية‪ ،‬فإن هذا سيعطينا الترجمة األكثر احتمالية‪ .‬لسوء‬
‫الحظ‪ ،‬ليس هناك ما يضمن أن البحث الجشع سوف يعطينا هذا التسلسل‪.‬‬

‫دعونا نوضح ذلك بمثال‪ .‬افترض أن هناك أربعة رموز مميزة "‪ "A‬و "‪ "B‬و "‪ "C‬و "<‪">eos‬يف ‬
‫قاموس اإلخراج‪.‬يف الشكل ‪ ،10.8.1‬تمثل األرقام األربعة تحت كل خطوة زمنية االحتماالت‬
‫الشرطية لتوليد "‪ "A‬و "‪ "B‬و "‪ "C‬و "<‪">eos‬يف تلك الخطوة الزمنية‪ ،‬على التوالي‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪274‬‬

‫الشكل ‪10.8.1‬يف كل خطوة زمنية‪ ،‬يقوم البحث الجشع بتحديد الرمز أعلى احتمالية شرطية‪.‬‬

‫في كل خطوة زمنية‪ ،‬يقوم البحث الجشع بتحديد الرمز بأعلى احتمالية شرطية‪ .‬لذلك‪ ،‬سيتم توقع‬
‫تسلسل الخرج "‪ "A‬و "‪ "B‬و "‪ "C‬و "<‪( ">eos‬الشكل ‪ .)10.8.1‬االحتمال الشرطي لتسلسل‬
‫اإلخراج هذا هو ‪.0.5 × 0.4 × 0.4 × 0.6 = 0.048‬‬

‫بعد ذلك‪ ،‬دعونا نلقي نظرة على مثال آخريف الشكل ‪ .10.8.2‬على عكس الشكل ‪،10.8.1‬يف ‬
‫الخطوة الزمنية ‪ 2‬نختار الرمز المميز "‪"C‬يف الشكل ‪ ،10.8.2‬والذي له ثاني أعلى احتمال شرطي‪.‬‬

‫الشكل ‪ 10.8.2‬تمثل األرقام األربعة الموجودة أسفل كل خطوة زمنية االحتماالت الشرطية‬
‫لتوليد "‪ "A‬و "‪ "B‬و "‪ "C‬و "<‪">eos‬يف تلك الخطوة الزمنية‪.‬يف الخطوة الزمنية ‪ ،2‬يتم تحديد‬
‫الرمز المميز "‪ ،”C‬الذي يحتوي على ثاني أعلى احتمالية شرطية‪.‬‬

‫نظرًا ألن المخرجات الالحقةيف الخطوتين ‪ 1‬و‪ ،2‬التي تستند إليها الخطوة الزمنية ‪ ،3‬قد تغيرت‬
‫من "‪ "A‬و "‪"B‬يف الشكل ‪ 10.8.1.‬إلى "‪ "A‬و "‪"C‬يف الشكل ‪ ،10.8.2‬كما تغير االحتمال الشرطي‬
‫لكل رمزيف الخطوة الزمنية ‪3‬يف الشكل ‪ .10.8.2‬لنفترض أننا اخترنا الرمز "‪"B‬يف الوقت الخطوة‬
‫‪ .3‬اآلن الخطوة الزمنية ‪ 4‬مشروطة باإلخراج الالحقيف الخطوات الثالث األولى "‪ "A‬و "‪ "C‬و‬
‫"‪ ،”B‬والتي تختلف عن "‪ "A‬و "‪“ B‬و "‪"C‬يف الشكل ‪ .10.8.1‬لذلك‪ ،‬فإن االحتمال الشرطي‬
‫لتوليد كل رمزيف الخطوة الزمنية ‪4‬يف الشكل ‪ 10.8.2‬يختلف أيضًا عن ذلكيف الشكل ‪.10.8.1‬‬
‫ونتيجة لذلك‪ ،‬فإن االحتمال الشرطي لتسلسل المخرجات "‪ "A‬و "‪ "C‬و "‪ "B‬و "<‪">eos‬يف الشكل‬
‫‪ I, 0.5 × 0.3 × 0.6 × 0.6 = 0.054 10.8.2‬أكبر من احتمال البحث الجشعيف الشكل‬
‫‪275‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪.1 .10.8‬يف هذا المثال‪ ،‬تسلسل المخرجات "‪ "A‬و "‪ "B‬و "‪ "C‬و "<‪ ">eos‬الذي تم الحصول‬
‫عليه عن طريق البحث الجشع ليس هو التسلسل األمثل‪.‬‬

‫‪Exhaustive Search‬‬ ‫‪10.8.2‬‬


‫إذا كان الهدف هو الحصول على التسلسل األكثر احتمالًا‪ ،‬فقد نفكريف استخدام البحث الشامل‬
‫‪ :exhaustive search‬قم بتعداد شامل لجميع تسلسالت المخرجات المحتملة مع احتماالتها‬
‫الشرطية‪ ،‬ثم إخراج التسلسل الذي يسجل أعلى احتمالية متوقعة‪.‬‬
‫‪′‬‬
‫في حين أن هذا سيعطينا بالتأكيد ما نرغب فيه‪ ،‬إال أنه سيأتي بتكلفة حسابية باهظة) 𝑇|𝒴|(𝒪 ‪،‬‬
‫وأسيةيف طول التسلسل وقاعدة هائلة من حجم المفردات‪ .‬على سبيل المثال‪ ،‬عندما = |𝒴|‬
‫‪ 10000‬و ‪ ، 𝑇 ′ = 10‬سنحتاج إلى تقييم المتتاليات ‪ .1000010 = 1040‬هذه أرقام صغيرة‬
‫مقارنة بالتطبيقات الحقيقية ولكنها بالفعل تتجاوز قدرات أي أجهزة كمبيوتر متوقعة‪ .‬من ناحية‬
‫أخرى‪ ،‬فإن التكلفة الحسابية للبحث الجشع هي ) ‪ :𝒪(|𝒴|𝑇 ′‬رخيصة بأعجوبة ولكنها بعيدة عن‬
‫المثالية‪ .‬على سبيل المثال‪ ،‬عندما ‪ |𝒴| = 10000‬و‪ ، 𝑇 ′ = 10‬نحتاج فقط إلى تقييم‬
‫المتتاليات ‪.10000 × 10 = 105‬‬

‫الشكل ‪ 10.8.3‬عملية البحث الشعاعي (حجم الحزمة‪ ،2 :‬الحد األقصى لطول تسلسل الخرج‪:‬‬
‫‪ .)3‬تسلسالت اإلخراج المرشح هي 𝐴 و 𝐶 و𝐵𝐴 و 𝐸𝐶 و𝐷𝐵𝐴 و 𝐷𝐸𝐶‪.‬‬

‫‪Beam Search‬‬ ‫‪10.8.3‬‬


‫يمكنك عرض إستراتيجيات فك تشفير التسلسل على أنها تقع على طيف ‪ ،spectrum‬حيث‬
‫يقدم البحث الشعاعي ‪ Beam Search‬حالً وسطًا بين كفاءة البحث الجشع ومثالية البحث‬
‫الشامل‪ .‬تتميز النسخة األكثر وضوحًا من البحث الشعاعي بمعامل فائق واحد‪ ،‬حجم الشعاع‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪276‬‬

‫‪. 𝑘،beam size‬يف الخطوة الزمنية ‪ ،1‬نختار الرموز بأعلى االحتماالت المتوقعة‪ .‬سيكون كل‬
‫واحد منهم الرمز األول لتسلسل اإلخراج المرشح‪ ،‬على التوالي‪.‬يف كل خطوة زمنية الحقة‪ ،‬بناءً‬
‫على تسلسل اإلخراج المرشح 𝑘يف الخطوة الزمنية السابقة‪ ،‬نواصل تحديد تسلسالت إخراج‬
‫المرشح 𝑘 ذات أعلى االحتماالت المتوقعة من الخيارات الممكنة‪.‬‬

‫يوضح الشكل ‪ 10.8.3‬عملية البحث الشعاعي مع مثال‪ .‬لنفترض أن مفردات اإلخراج تحتوي‬
‫على خمسة عناصر فقط‪ 𝒴 = {𝐴, 𝐵, 𝐶, 𝐷, 𝐸} :‬أحدها "<‪ .">eos‬اجعل حجم الشعاع ‪ 2‬ويكون‬
‫الحد األقصى لطول تسلسل اإلخراج ‪.3‬يف الخطوة الزمنية ‪ ،1‬افترض أن الرموز ذات االحتماالت‬
‫الشرطية األعلى )𝐜 ∣ ‪ 𝑃(𝑦1‬هي 𝐴 و 𝐶‪.‬يف الخطوة الزمنية ‪ ،2‬لكل ‪ 𝑦2 ∈ 𝒴,‬نحسب‪:‬‬

‫‪𝑃(𝐴, 𝑦2 ∣ 𝐜) = 𝑃(𝐴 ∣ 𝐜)𝑃(𝑦2 ∣ 𝐴, 𝐜),‬‬


‫‪𝑃(𝐶, 𝑦2 ∣ 𝐜) = 𝑃(𝐶 ∣ 𝐜)𝑃(𝑦2 ∣ 𝐶, 𝐜),‬‬

‫واختر أكبر قيمتين من بين هذه القيم العشر‪ ،‬على سبيل المثال )𝐜 ∣ 𝐵 ‪ 𝑃(𝐴,‬و)𝐜 ∣ 𝐸 ‪. 𝑃(𝐶,‬‬
‫ثميف الخطوة الزمنية ‪ ،3‬لكل 𝒴 ∈ ‪ 𝑦3‬نقوم بحساب‪:‬‬

‫‪𝑃(𝐴, 𝐵, 𝑦3 ∣ 𝐜) = 𝑃(𝐴, 𝐵 ∣ 𝐜)𝑃(𝑦3 ∣ 𝐴, 𝐵, 𝐜),‬‬


‫‪𝑃(𝐶, 𝐸, 𝑦3 ∣ 𝐜) = 𝑃(𝐶, 𝐸 ∣ 𝐜)𝑃(𝑦3 ∣ 𝐶, 𝐸, 𝐜),‬‬

‫واختر أكبر قيمتين من بين هذه القيم العشر‪ ،‬على سبيل المثال )𝐜 ∣ 𝐷 ‪ 𝑃(𝐴, 𝐵,‬و∣ 𝐷 ‪𝑃(𝐶, 𝐸,‬‬
‫‪ 𝐜).‬نتيجة لذلك‪ ،‬نحصل على ست متواليات إخراج مرشحة‪:‬‬

‫في النهاية‪ ،‬نحصل على مجموعة تسلسالت اإلخراج المرشح النهائية بناءً على هذه التسلسالت‬
‫الستة (على سبيل المثال‪ ،‬تجاهل األجزاء بمايف ذلك وبعد "<‪ .)">eos‬ثم نختار التسلسل ذي‬
‫الدرجة األعلى من الدرجة التالية كتسلسل اإلخراج‪:‬‬
‫𝐿‬
‫‪1‬‬ ‫‪1‬‬
‫𝛼‬
‫∑ 𝛼 = )𝐜 ∣ 𝐿𝑦 ‪log 𝑃(𝑦1 , … ,‬‬ ‫‪log 𝑃(𝑦𝑡 ′ ∣ 𝑦1 , … , 𝑦𝑡 ′ −1 , 𝐜),‬‬
‫𝐿‬ ‫‪𝐿 ′‬‬
‫‪𝑡 =1‬‬

‫حيث 𝐿 هو طول تسلسل المرشح النهائي وعادة ما يتم تعيينه على ‪ .0.75‬نظرًا ألن التسلسل‬
‫األطول يحتوي على مصطلحات لوغاريتمية أكثريف جمع (‪ ،)10.8.4‬فإن المصطلح 𝛼𝐿يف المقام‬
‫يعاقب التسلسالت الطويلة‪.‬‬

‫التكلفة الحسابية للبحث الشعاعي هي ) ‪ .𝒪(𝑘|𝒴|𝑇 ′‬هذه النتيجة تقع بين نتيجة البحث الجشع‬
‫ونتائج البحث الشامل‪ .‬يمكن التعامل مع البحث الجشع كحالة خاصة للبحث الشعاعي التي تنشأ‬
‫عند ضبط حجم الشعاع ‪ beam size‬على ‪.1‬‬
‫‪277‬‬ ‫الفصل العاشر‪ :‬الشبكات العصبية المتكررة الحديثة‬

‫‪10.8.4‬‬
‫تتضمن استراتيجيات البحث المتسلسل البحث الجشع والبحث الشامل والبحث الشعاعي‪ .‬يوفر‬
‫البحث الشعاعي مفاضلة بين الدقة مقابل التكلفة الحسابية من خالل اختياره المرن لحجم‬
‫الشعاع‪.‬‬

‫‪10.8.5‬‬
‫‪ .1‬هل يمكننا التعامل مع البحث الشامل كنوع خاص من البحث الشعاعي؟ لما ولما ال؟‬
‫‪ .2‬قم بتطبيق البحث الشعاعييف مشكلة الترجمة اآلليةيف القسم ‪ .10.7‬كيف يؤثر حجم‬
‫الشعاع على نتائج الترجمة وسرعة التنبؤ؟‬
‫‪ .3‬استخدمنا نمذجة اللغة إلنشاء نص يتبع البادئات التي قدمها المستخدم ‪user-‬‬
‫‪provided prefixes‬يف القسم ‪ .9.5‬ما نوع استراتيجية البحث التي تستخدمها؟ هل‬
‫يمكنك تحسينه؟‬
‫آليات االنتباه والمحوالت‬
‫‪11‬‬
‫‪279‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪Attention Mechanisms‬‬ ‫‪11‬‬


‫‪and Transformers‬‬
‫يتلقى العصب البصري للنظام البصري الرئيسي مدخالت حسية هائلة‪ ،‬تتجاوز بكثير ما يمكن‬
‫للدماغ معالجته بشكل كامل‪ .‬لحسن الحظ‪ ،‬ليست كل المحفزات متساوية‪ .‬مكّن التركيز البؤري‬
‫للوعي وتركيزه الرئيسي من توجيه االنتباه إلى األشياء محل االهتمام‪ ،‬مثل الفرائس والحيوانات‬
‫المفترسة‪،‬يف البيئة المرئية المعقدة‪ .‬إن القدرة على االنتباه إلى جزء صغير فقط من المعلومات لها‬
‫أهمية تطورية‪ ،‬مما يسمح للبشر بالعيش والنجاح‪.‬‬

‫كان العلماء يدرسون االنتباه ‪attention‬يف مجال علم األعصاب اإلدراكي ‪cognitive‬‬
‫‪ neuroscience‬منذ القرن التاسع عشر‪.‬يف هذا الفصل‪ ،‬سنبدأ بمراجعة إطار عمل شائع لشرح‬
‫كيفية نشر االنتباهيف المشهد المرئي‪ .‬مستوحاة من إشارات االنتباه ‪attention cues‬يف هذا‬
‫اإلطار‪ ،‬سنصمم نماذج تستفيد من إشارات االنتباه هذه‪ .‬والجدير بالذكر أن انحدار نواة‬
‫‪Nadaraya-Watson‬يف عام ‪ 1964‬هو عرض بسيط للتعلم اآللي مع آليات االنتباه ‪attention‬‬
‫‪ .mechanisms‬بعد ذلك‪ ،‬سوف نقدم دوال االنتباه التي تم استخدامها على نطاق واسعيف ‬
‫تصميم نماذج االنتباهيف التعلم العميق‪ .‬على وجه التحديد‪ ،‬سوف نوضح كيفية استخدام هذه‬
‫الدوال لتصميم انتباه باهدانو ‪ ،Bahdanau attention‬وهو نموذج اهتمام رائديف التعلم العميق‬
‫يمكن أن يتماشى بشكل ثنائي االتجاه وقابل للتفاضل‪.‬‬

‫مجهزة بأحدث تصميمات االنتباه متعدد الرؤوس ‪ multi-head attention‬واالنتباه الذاتي‬


‫‪ ،self-attention‬تعتمد بُنية المحوالت فقط على آليات االنتباه ‪.attention mechanisms‬‬
‫سننتقل إلى وصف التصميم األصلي المشفر‪-‬مفكك الشفرة للترجمة اآللية‪ .‬ثم سنبين كيف‬
‫يمكن المشفر الخاص به تمثيل الصور‪ ،‬مما يؤدي إلى تطوير محوالت الرؤية ‪vision‬‬
‫‪ . transformers‬عند تدريب نماذج كبيرة جدًا على مجموعات بيانات كبيرة جدًا (على سبيل‬
‫المثال‪ 300 ،‬مليون صورة)‪ ،‬تتفوق محوالت الرؤية على ‪ ResNets‬بشكل كبيريف تصنيف‬
‫الصور‪ ،‬مما يدل على قابلية التوسع الفائقة للمحوالت‪ .‬وبالتالي‪ ،‬تم استخدام المحوالت على‬
‫نطاق واسعيف التدريب المسبق على نطاق واسع‪ ،‬والتي يمكن تكييفها ألداء مهام مختلفة مع‬
‫تحديث النموذج (على سبيل المثال‪ ،‬الضبط الدقيق ‪ )fine tuning‬أو ال (على سبيل المثال‪،‬‬
‫عدد قليل من اللقطات ‪.)few shot‬يف النهاية‪ ،‬سنراجع كيفية التصفية المسبقة للمحوالت‬
‫كمشفرات فقط ‪( encoder-only‬على سبيل المثال‪ ،)BERT ،‬ومشفر‪-‬مفكك الشفرة‬
‫‪( encoder-decoder‬على سبيل المثال‪ ،)T5 ،‬ومفكك الشفرة فقط ‪( decoder-only‬على‬
‫سبيل المثال‪ ،‬سلسلة ‪ .) GPT‬يشير النجاح المقنع للتدريب المسبق على نطاق واسع باستخدام‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪280‬‬

‫المحوالتيف مجاالت متنوعة مثل اللغة والرؤية والكالم والتعلم المعزز إلى أن األداء األفضل‬
‫يستفيد من النماذج األكبر‪ ،‬والمزيد من بيانات التدريب‪ ،‬والمزيد من حوسبة التدريب‪.‬‬

‫‪Attention Cues‬‬ ‫‪11.1‬‬


‫شكرا لك على اهتمامك (انتباهك) بهذا الكتاب‪ .‬االهتمام مورد نادر‪:‬يف الوقت الحالي تقرأ هذا‬
‫الكتاب وتتجاهل الباقي‪ .‬وبالتالي‪ ،‬على غرار المال‪ ،‬يتم دفع انتباهك بتكلفة الفرصة البديلة‪.‬‬
‫للتأكد من أن استثمار اهتمامك اآلن يستحق العناء‪ ،‬فقد تحمسنا بشدة إليالء اهتمامنا بعناية‬
‫إلنتاج كتاب لطيف‪ .‬االنتباه (االهتمام) هو حجر األساسيف قوس الحياة ويمسك بمفتاح التميز‬
‫ألي عمل‪.‬‬

‫بما أن االقتصاد يدرس تخصيص الموارد النادرة‪ ،‬فنحنيف عصر اقتصاد االنتباه ‪attention‬‬
‫‪ ،economy‬حيث يتم التعامل مع االهتمام البشري على أنه سلعة محدودة وقيمة ونادرة يمكن‬
‫تبادلها‪ .‬تم تطوير العديد من نماذج األعمال لالستفادة منها‪.‬يف الموسيقى أو خدمات بث الفيديو‪،‬‬
‫إما أن نولي اهتمامًا إلعالناتهم أو ندفع المال إلخفائها‪ .‬للنمويف عالم األلعاب عبر اإلنترنت‪ ،‬إما‬
‫أن نولي اهتمامًا للمشاركةيف المعارك‪ ،‬التي تجذب العبين جددًا‪ ،‬أو ندفع المال لنصبح أقوياء‬
‫على الفور‪ .‬ال شيء يأتي بالمجان‪.‬‬

‫بشكل عام‪ ،‬المعلوماتيف بيئتنا ليست نادرة‪ ،‬االنتباه هو‪ .‬عند فحص مشهد مرئي‪ ،‬يتلقى العصب‬
‫البصري معلومات بترتيب ‪ 108‬بتاتيف الثانية‪ ،‬وهو ما يتجاوز بكثير ما يمكن لدماغنا معالجته‬
‫بشكل كامل‪ .‬لحسن الحظ‪ ،‬تعلم أسالفنا من التجربة (المعروفة أيضًا باسم البيانات) أنه ليست‬
‫كل المدخالت الحسية متساوية‪ .‬على مدار تاريخ البشرية‪ ،‬مكنت القدرة على توجيه االنتباه إلى‬
‫جزء بسيط من المعلومات ذات األهمية عقولنا من تخصيص الموارد بشكل أكثر ذكاءً للبقاء‬
‫والنمو والتواصل االجتماعي‪ ،‬مثل اكتشاف الحيوانات المفترسة والفرائس والرفاق‪.‬‬

‫‪Attention Cues in Biology‬‬ ‫‪11.1.1‬‬


‫لشرح كيفية نشر انتباهنايف العالم المرئي‪ ،‬ظهر إطار عمل مكون من عنصرين وانتشر‪ .‬تعود هذه‬
‫الفكرة إلى ويليام جيمسيف تسعينيات القرن التاسع عشر‪ ،‬والذي يُعتبر "أب علم النفس األمريكي"‬
‫(جيمس‪.)2007 ،‬يف هذا اإلطار‪ ،‬يقوم األشخاص بشكل انتقائي بتوجيه بؤرة االنتباه باستخدام‬
‫كل من اإلشارات الالإرادية ‪ nonvolitional cue‬واإلشارة اإلرادية ‪.volitional cue‬‬

‫تعتمد االشارة الالإرادية ‪ nonvolitional cue‬على بروز العناصريف البيئة ووضوحها‪ .‬تخيل أن‬
‫هناك خمسة أشياء أمامك‪ :‬جريدة وورقة بحث وفنجان قهوة ودفتر مالحظات وكتاب كمايف ‬
‫الشكل ‪ .11.1.1‬بينما تتم طباعة جميع المنتجات الورقية باللونين األسود واألبيض‪ ،‬فإن فنجان‬
‫القهوة باللون األحمر‪ .‬بعبارة أخرى‪ ،‬هذه القهوة بارزة بشكل جوهري وواضحةيف هذه البيئة‬
‫‪281‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫المرئية‪ ،‬وتلفت االنتباه تلقائيًا وال إراديًا‪ .‬لذلك تقوم بإحضار النقرة المركزية ‪( fovea‬مركز البقعة‬
‫حيث تكون حدة البصر أعلى) على القهوة كما هو موضحيف الشكل ‪.11.1.1‬‬

‫الشكل ‪ 11.1.1‬باستخدام اإلشارات الالإرادية القائمة على النقطة المحفزة ‪( saliency‬كوب‬


‫أحمر‪ ،‬غير ورقي)‪ ،‬يتم توجيه االنتباه بشكل ال إرادي إلى القهوة‪.‬‬

‫بعد شرب القهوة‪ ،‬تصبح محتويًا على الكافيين وترغبيف قراءة كتاب‪ .‬لذلك تدير رأسك‪ ،‬وتعيد‬
‫تركيز عينيك‪ ،‬وتنظر إلى الكتاب كما هو موضحيف الشكل ‪ .11.1.2‬يختلف عن الحالةيف الشكل‬
‫‪ 11.1.1‬حيث تحيزك القهوة نحو االختيار بناءً على النقطة المحفزة ‪،saliency‬يف هذه الحالة‬
‫التي تعتمد على المهمة‪ ،‬يمكنك تحديد الكتاب تحت التحكم المعرفي واإلرادي‪ .‬باستخدام‬
‫االشارة اإلرادية ‪ volitional cue‬بناءً على معايير االختيار المتغيرة‪ ،‬يكون هذا النوع من االنتباه‬
‫أكثر تعمقًا‪ .‬كما أنها أكثر قوة مع الجهد التطوعي للموضوع‪.‬‬

‫الشكل ‪ 11.1.2‬باستخدام االشارة اإلرادية (الرغبةيف قراءة كتاب) الذي يعتمد على المهمة‪ ،‬يتم‬
‫توجيه االنتباه إلى الكتاب تحت السيطرة اإلرادية‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪282‬‬

‫‪Queries, Keys, and Values‬‬ ‫‪11.1.2‬‬


‫مستوحاة من إشارات االنتباه الالإرادي واإلرادي التي تشرح النشر االنتباهي ‪attentional‬‬
‫‪ ،deployment‬فيما يلي سنصف إطار عمل لتصميم آليات االنتباه من خالل دمج إشارات‬
‫االنتباه هاتين‪.‬‬

‫بادئ ذي بدء‪ ،‬ضعيف اعتبارك الحالة األبسط حيث ال تتوفر سوى اإلشارات غير المنطقية‪ .‬لتحيز‬
‫التحديد على المدخالت الحسية‪ ،‬يمكننا ببساطة استخدام طبقة متصلة بالكامل ذات معلمات أو‬
‫حتى تجميع أقصى أو متوسط بدون معلمات‪.‬‬

‫لذلك‪ ،‬فإن ما يميز آليات االنتباه عن تلك الطبقات أو طبقات التجميع المتصلة بالكامل هو‬
‫تضمين اإلشارات اإلرادية‪.‬يف سياق آليات االنتباه‪ ،‬نشير إلى اإلشارات االرادية على أنها‬
‫استعالمات ‪ .queries‬بالنظر إلى أي استفسار‪ ،‬فإن آليات االنتباه تحيز االختيار ‪bias selection‬‬
‫على المدخالت الحسية ‪( sensory inputs‬على سبيل المثال‪ ،‬تمثيالت الميزات الوسيطة‬
‫‪ )intermediate feature representations‬عبر تجميع االنتباه ‪.attention pooling‬‬
‫تسمى هذه المدخالت الحسية القيم ‪values‬يف سياق آليات االنتباه‪ .‬بشكل عام‪ ،‬يتم إقران كل‬
‫قيمة بمفتاح ‪ ،key‬والذي يمكن التفكير فيه من خالل اإلشارة غير المنطقية لتلك المدخالت‬
‫الحسية‪ .‬كما هو مبينيف الشكل ‪ ،11.1.3‬يمكننا تصميم تجميع االنتباه بحيث يمكن أن يتفاعل‬
‫االستعالم المحدد (اإلشارات اإلرادية) مع المفاتيح (اإلشارات غير االرادية)‪ ،‬والتي توجه اختيار‬
‫التحيز على القيم (المدخالت الحسية)‪.‬‬

‫الشكل ‪ 11.1.3‬تحيز االختيار آلليات االنتباه على القيم (المدخالت الحسية) من خالل‬
‫تجميع االنتباه‪ ،‬والذي يتضمن االستعالمات (اإلشارات اإلرادية) والمفاتيح (اإلشارات غير‬
‫المنطقية)‪.‬‬
283 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

‫ يمكننا تصميم نموذج‬،‫ على سبيل المثال‬.‫الحظ أن هناك العديد من البدائل لتصميم آليات االنتباه‬
reinforcement ‫انتباه غير قابل للتفاضل يمكن تدريبه باستخدام أساليب التعلم المعزز‬
‫ ستكون‬،11.1.3 ‫ بالنظر إلى هيمنة إطار العمليف الشكل‬.)2014 ،Mnih et al.( learning
.‫النماذجيف هذا اإلطار محور اهتمامنايف هذا الفصل‬

Visualization of Attention 11.1.3


‫ حيث تكون‬،‫ كمتوسط وزني للمدخالت‬Average pooling ‫يمكن التعامل مع متوسط التجميع‬
،‫ يجمع االنتباه القيم اإلجمالية باستخدام متوسط االوزان‬،‫يف الممارسة العملية‬.‫األوزان موحدة‬
.‫حيث يتم حساب األوزان بين االستعالم المحدد والمفاتيح المختلفة‬

import tensorflow as tf
from d2l import tensorflow as d2l
‫ مصفوفات‬.show_heatmaps ‫ نحدد دالة‬،attention weights ‫لرسم أوزان االنتباه‬
‫ عدد‬،‫ عدد األعمدة للعرض‬،‫ لها الشكل (عدد الصفوف للعرض‬matrices ‫اإلدخال‬
.)‫ عدد المفاتيح‬،‫االستعالمات‬

#@save
def show_heatmaps(matrices, xlabel, ylabel, titles=None,
figsize=(2.5, 2.5),
cmap='Reds'):
"""Show heatmaps of matrices."""
d2l.use_svg_display()
num_rows, num_cols = len(matrices), len(matrices[0])
fig, axes = d2l.plt.subplots(num_rows, num_cols,
figsize=figsize,
sharex=True,
sharey=True, squeeze=False)
for i, (row_axes, row_matrices) in
enumerate(zip(axes, matrices)):
for j, (ax, matrix) in enumerate(zip(row_axes,
row_matrices)):
pcm = ax.imshow(matrix.numpy(), cmap=cmap)
if i == num_rows - 1:
ax.set_xlabel(xlabel)
if j == 0:
ax.set_ylabel(ylabel)
if titles:
ax.set_title(titles[j])
fig.colorbar(pcm, ax=axes, shrink=0.6);
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪284‬‬

‫للتوضيح‪ ،‬نعتبر حالة بسيطة حيث يكون وزن االنتباه واحدًا فقط عندما يكون االستعالم والمفتاح‬
‫متماثلين؛ وإال فهو صفر‪.‬‬

‫‪attention_weights = tf.reshape(tf.eye(10), (1, 1, 10,‬‬


‫))‪10‬‬
‫‪show_heatmaps(attention_weights, xlabel='Keys',‬‬
‫)'‪ylabel='Queries‬‬

‫في األقسام التالية‪ ،‬غالبًا ما نستدعي هذه الدالة لرسم أوزان االنتباه‪.‬‬

‫‪11.1.4‬‬
‫االهتمام (االنتباه) البشري ‪ Human attention‬هو مورد محدود وقيِّم ونادر‪.‬‬ ‫•‬
‫الموضوعات توجه االنتباه بشكل انتقائي باستخدام كل من اإلشارات غير االرادية‬ ‫•‬
‫واإلرادية‪ .‬األول يعتمد على النقطة المحفزة ‪ saliency‬واألخير يعتمد على المهمة‬
‫‪.task‬‬
‫تختلف آليات االنتباه عن الطبقات المتصلة بالكامل أو طبقات التجميع بسبب تضمين‬ ‫•‬
‫اإلشارات اإلرادية‪.‬‬
‫تعمل آليات االنتباه على تحيز االختيار ‪ bias selection‬على القيم (المدخالت‬ ‫•‬
‫الحسية) من خالل تجميع االنتباه‪ ،‬والذي يتضمن االستعالمات (اإلشارات اإلرادية)‬
‫والمفاتيح (اإلشارات غير المنطقية)‪ .‬المفاتيح والقيم مقترنة‪.‬‬
‫يمكننا رسم أوزان االنتباه بين االستعالمات والمفاتيح‪.‬‬ ‫•‬
‫‪285‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪11.1.5‬‬
‫‪ .1‬ماذا يمكن أن تكون االشارة اإلرادية عند فك تشفير رمز تسلسلي برمزيف الترجمة اآللية؟‬
‫ما هي اإلشارات غير االرادية والمدخالت الحسية؟‬
‫‪ .2‬أنشئ مصفوفة بشكل عشوائي واستخدم عملية ‪ softmax‬للتأكد من أن كل صف هو‬
‫توزيع احتمالي صالح‪ .‬ارسم أوزان االنتباه الناتج‪.‬‬

‫‪Attention Pooling‬‬ ‫‪11.2‬‬


‫أنت اآلن تعرف المكونات الرئيسية آلليات االنتباه ‪ attention mechanisms‬ضمن اإلطار‬
‫الموضحيف الشكل ‪ .11.1.3‬للتلخيص‪ ،‬تؤدي التفاعالت بين االستعالمات ‪( queries‬اإلشارات‬
‫اإلرادية ‪ )volitional cues‬والمفاتيح ‪( keys‬اإلشارات غير االرادية ‪)nonvolitional cues‬‬
‫إلى تجميع االنتباه ‪ .attention pooling‬يجمع االهتمام بشكل انتقائي القيم (المدخالت‬
‫الحسية ‪ )sensory inputs‬إلنتاج المخرجات‪.‬يف هذا القسم‪ ،‬سنصف تجميع االنتباه بمزيد من‬
‫التفصيل لمنحك رؤية عالية المستوى لكيفية عمل آليات االنتباهيف الممارسة العملية‪ .‬على وجه‬
‫التحديد‪ ،‬نموذج انحدار نواة ‪ Nadaraya-Watson‬المقترحيف عام ‪ 1964‬هو مثال بسيط ولكنه‬
‫كامل إلظهار التعلم اآللي بآليات االنتباه‪.‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Generating the Dataset‬‬ ‫‪11.2.1‬‬
‫لتبسيط األمور‪ ،‬دعنا نفكريف مشكلة االنحدار التالية‪ :‬بالنظر إلى مجموعة بيانات من أزواج‬
‫^‬
‫المدخالت والمخرجات }) 𝑛𝑦 ‪ ، {(𝑥1 , 𝑦1 ), … , (𝑥𝑛 ,‬كيف تعلم 𝑓 كيفية توقع المخرجات = 𝑦‬
‫)𝑥(𝑓 عن أي مدخالت جديدة؟‬

‫نقوم هنا بإنشاء مجموعة بيانات اصطناعية ‪ artificial dataset‬وفقًا للدالة غير الخطية التالية‬
‫بمصطلح الضوضاء 𝜖‪:‬‬

‫‪𝑦𝑖 = 2sin (𝑥𝑖 ) + 𝑥𝑖0.8 + 𝜖,‬‬

‫حيث 𝜖 تخضع لتوزيع طبيعي بمتوسط صفري وانحراف معياري ‪ .0.5‬يتم إنشاء كل من أمثلة‬
‫التدريب ‪ 50‬و‪ 50‬أمثلة التحقق‪ .‬لتصور نمط االنتباه بشكل أفضل الحقًا‪ ،‬يتم فرز مدخالت‬
‫التدريب‪.‬‬

‫‪class NonlinearData(d2l.DataModule):‬‬
‫‪def __init__(self, n, batch_size):‬‬
‫)(‪self.save_hyperparameters‬‬
‫‪f = lambda x: 2 * tf.sin(x) + x**0.8‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 286

self.x_train = tf.sort(tf.random.uniform((n,1))
* 5, 0)
self.y_train = f(self.x_train) +
tf.random.normal((n,1))
self.x_val = tf.range(0, 5, 5.0/n)
self.y_val = f(self.x_val)

def get_dataloader(self, train):


arrays = (self.x_train, self.y_train) if train
else (self.x_val, self.y_val)
return self.get_tensorloader(arrays, train)

n = 50
data = NonlinearData(n, batch_size=10)
f ‫ ودالة توليد بيانات الحقيقة‬،)‫توضح الدالة التالية جميع أمثلة التدريب (التي تمثلها الدوائر‬
.)"Pred" ‫ ودالة التنبؤ المكتسبة (المُسمى بـ‬،)"Truth" ‫بدون مصطلح الضوضاء (المُسمى‬

def plot_kernel_reg(y_hat):
d2l.plot(data.x_val, [data.y_val, y_hat.numpy()],
'x', 'y', legend=['Truth', 'Pred'],
xlim=[0, 5], ylim=[-1, 5])
d2l.plt.plot(data.x_train, data.y_train, 'o',
alpha=0.5);
Average Pooling 11.2.2
‫ استخدام‬:‫يف العالم لمشكلة االنحدار هذه‬estimator ‫ " مقدر‬dumbest ‫نبدأ مع ربما "أغبى‬
:‫متوسط التجميع إلى المتوسط على جميع مخرجات التدريب‬
1
𝑓(𝑥) = 𝑛 ∑𝑛𝑖=1 𝑦𝑖 , )11.2.2(

.‫ هذا المقدّر ليس ذكيًا حقًا‬،‫ كما نرى‬.‫الذي تم رسمه أدناه‬

y_hat = tf.repeat(tf.reduce_mean(data.y_train), n)
plot_kernel_reg(y_hat)
‫‪287‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪Nonparametric Attention Pooling‬‬ ‫‪11.2.3‬‬


‫من الواضح أن متوسط التجميع يتجاهل المدخالت 𝑖𝑥‪ .‬تم اقتراح فكرة أفضل من قبل‬
‫‪ )1964,Nadaraya( ،Nadaraya‬و ‪ )1964,Watson( ،Watson‬لوزن المخرجات 𝑖𝑦‬
‫وفقًا لمواقع إدخالها‪:‬‬
‫) 𝑖𝑥‪𝐾(𝑥−‬‬
‫‪𝑓(𝑥) = ∑𝑛𝑖=1‬‬ ‫𝑛∑‬
‫‪𝑦𝑖 ,‬‬ ‫(‪)11.2.3‬‬
‫) 𝑗𝑥‪𝑗=1 𝐾(𝑥−‬‬

‫حيث 𝐾 النواة ‪ .kernel‬المقدريف (‪ )11.2.3‬يسمى انحدار نواة ‪ .Nadaraya-Watson‬لن‬


‫نتعمق هنايف تفاصيل النوى‪ .‬استدعي إطار عمل آليات االنتباهيف الشكل ‪ .11.1.3‬من منظور‬
‫االنتباه‪ ،‬يمكننا إعادة كتابة (‪)11.2.3‬يف شكل أكثر عمومية لتجميع االنتباه ‪attention‬‬
‫‪:pooling‬‬

‫‪𝑓(𝑥) = ∑𝑛𝑖=1‬‬ ‫(‪𝛼(𝑥, 𝑥𝑖 )𝑦𝑖 ,)11.2.4‬‬

‫حيث 𝑥 هو االستعالم وهو زوج المفتاح والقيمة ) 𝑖𝑦 ‪ .(𝑥𝑖 ,‬بمقارنة (‪ )11.2.4‬و (‪،)11.2.2‬‬
‫فإن تجميع االنتباه هنا هو متوسط االوزان للقيم 𝑖𝑦‪ .‬يتم تعيين وزن االنتباه ) 𝑖𝑥 ‪𝛼(𝑥,‬يف ‬
‫(‪ )11.2.4‬إلى القيمة المقابلة 𝑖𝑦 بناءً على التفاعل بين االستعالم 𝑥 والمفتاح 𝑖𝑥 المصمم‬
‫بواسطة 𝛼‪ .‬بالنسبة ألي استعالم‪ ،‬تعتبر أوزان االنتباه الخاصة به على جميع أزواج المفتاح‪-‬القيمة‬
‫توزيعًا احتماليًا صالحًا‪ :‬فهي غير سالبة ويصل مجموعهم إلى واحد‪.‬‬

‫الكتساب حدس لتجميع االنتباه‪ ،‬ما عليك سوى التفكيريف نواة غاوسية ‪Gaussian kernel‬‬
‫مُعرَّفة على أنها‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 288

1 𝑢2
𝐾(𝑢) = exp (− ).
√2𝜋 2

:‫) يعطي‬11.2.3( ‫) و‬11.2.4( ‫إدخال النواة الغاوسيةيف‬


𝑛

𝑓(𝑥) =∑ 𝛼(𝑥, 𝑥𝑖 )𝑦𝑖


𝑖=1
𝑛 1
exp(− 2 (𝑥 − 𝑥𝑖 )2 )
=∑ 𝑦𝑖
𝑛 1 2
𝑖=1 ∑𝑗=1 exp (− 2 (𝑥 − 𝑥𝑗 ) )
𝑛
1
= ∑ softmax (− (𝑥 − 𝑥𝑖 )2 )𝑦𝑖 .
2
𝑖=1

‫ سيحظى المفتاح 𝑖𝑥 األقرب إلى االستعالم المعطى 𝑥 بمزيد من االنتباه من خالل‬،)11.2.6( ‫في‬
.𝑦𝑖 ‫ يتم تعيينه لقيمة المفتاح المقابلة‬larger attention weight ‫وزن انتباه أكبر‬

‫ هو نموذج غير معلمي‬Nadaraya-Watson ‫والجدير بالذكر أن انحدار نواة‬


‫) هو مثال لتجميع االنتباه الالمعلمي‬11.2.6( ‫ وبالتالي‬.nonparametric model
‫ نرسم التنبؤ بناءً على نموذج االنتباه‬،‫ فيما يلي‬.nonparametric attention pooling
‫ الخط المتوقع سلس وأقرب إلى الحقيقة األساسية من ذلك الناتج عن متوسط‬.‫الالمعلمي هذا‬
.average pooling ‫التجميع‬

def diff(queries, keys):


return tf.reshape(queries, (-1, 1)) -
tf.reshape(keys, (1, -1))

def attention_pool(query_key_diffs, values):


attention_weights = tf.nn.softmax(-
query_key_diffs**2/2, axis=1)
return tf.matmul(attention_weights, values),
attention_weights

y_hat, attention_weights = attention_pool(


diff(data.x_val, data.x_train), data.y_train)
plot_kernel_reg(y_hat)
‫‪289‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫اآلن دعونا نلقي نظرة على أوزان االنتباه‪ .‬هنا مدخالت التحقق من الصحة ‪validation inputs‬‬
‫هي استعالمات بينما مدخالت التدريب ‪ training inputs‬هي مفاتيح‪ .‬نظرًا ألنه يتم فرز كال‬
‫المدخالت‪ ،‬يمكننا أن نرى أنه كلما اقترب زوج المفتاح‪-‬االستعالم‪ ،‬زاد وزن االنتباهيف تجميع‬
‫االنتباه‪.‬‬

‫‪d2l.show_heatmaps([[attention_weights]],‬‬
‫‪xlabel='Sorted training inputs',‬‬
‫)'‪ylabel='Sorted validation inputs‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪290‬‬

‫‪Parametric Attention Pooling‬‬ ‫‪11.2.4‬‬


‫يتمتع انحدار نواة ‪ Nadaraya-Watson‬الالمعلمي بفائدة االتساق ‪ :consistency‬نظرًا‬
‫لبيانات كافية‪ ،‬يتقارب هذا النموذج مع الحل األمثل‪ .‬ومع ذلك‪ ،‬يمكننا بسهولة دمج المعلمات‬
‫القابلة للتعلميف تجميع االنتباه‪.‬‬

‫على سبيل المثال‪ ،‬يختلف قليالً عن (‪،)11.2.6‬يف المسافة التالية بين االستعالم 𝑥 والمفتاح 𝑖𝑥‬
‫يتم ضربه بمعامل قابل للتعلم 𝑤‪:‬‬

‫)𝑥(𝑓‬ ‫‪= ∑𝑛𝑖=1‬‬ ‫𝑖𝑦) 𝑖𝑥 ‪𝛼(𝑥,‬‬


‫‪1‬‬
‫) ‪exp(− ((𝑥−𝑥𝑖 )𝑤)2‬‬
‫‪= ∑𝑛𝑖=1‬‬ ‫‪2‬‬
‫‪1‬‬ ‫(‪𝑦𝑖 )11.2.7‬‬
‫𝑛∑‬
‫‪𝑗=1‬‬ ‫) ‪exp (− ((𝑥−𝑥𝑗 )𝑤)2‬‬
‫‪2‬‬
‫‪1‬‬
‫‪= ∑𝑛𝑖=1 softmax (− 2 ((𝑥 − 𝑥𝑖 )𝑤)2 )𝑦𝑖 .‬‬

‫في باقي القسم‪ ،‬سنقوم بتدريب هذا النموذج من خالل تعلم معامل تجميع االنتباهيف (‪.)11.2.7‬‬

‫‪Batch Matrix Multiplication‬‬ ‫‪11.2.4.1‬‬


‫لحساب االنتباه بشكل أكثر كفاءة للدفعات الصغيرة ‪ ،minibatches‬يمكننا االستفادة من أدوات‬
‫ضرب مصفوفة الدُفعات ‪ batch matrix multiplication‬التي توفرها أطر عمل التعلم‬
‫العميق‪.‬‬

‫افترض أن أول دفعة صغيرة تحتوي على 𝑛 مصفوفات 𝑛 𝐗 ‪ 𝐗1 , … ,‬بالشكل 𝑏 × 𝑎‪ ،‬بينما تحتوي‬
‫الدفعة الثانية على 𝑛 مصفوفات 𝑛𝐘 ‪ 𝐘1 , … ,‬بالشكل 𝑐 × 𝑏‪ .‬ينتج عن ضرب المصفوفة الدفعية‬
‫𝑛 مصفوفات 𝑛𝐘 𝑛 𝐗 ‪ 𝐗1 𝐘1 , … ,‬بالشكل 𝑐 × 𝑎‪ .‬لذلك‪ ،‬بالنظر إلى موترين من الشكل (𝑏‪،‬‬
‫𝑎‪ )𝑛،‬و ( 𝑐‪ ،)𝑛،𝑏 ،‬يكون شكل ناتج ضرب المصفوفة الدفعية هو (𝑐‪.)𝑛،𝑎 ،‬‬

‫))‪X = tf.ones((2, 1, 4‬‬


‫))‪Y = tf.ones((2, 4, 6‬‬
‫))‪d2l.check_shape(tf.matmul(X, Y), (2, 1, 6‬‬
‫في سياق آليات االنتباه‪ ،‬يمكننا استخدام ضرب مصفوفة الدفعات الصغيرة لحساب المتوسطات‬
‫الموزونة للقيميف الدفعات الصغيرة‪.‬‬

‫‪weights = tf.ones((2, 10)) * 0.1‬‬


‫))‪values = tf.reshape(tf.range(20.0), shape = (2, 10‬‬
‫‪tf.matmul(tf.expand_dims(weights, axis=1),‬‬
‫)(‪tf.expand_dims(values, axis=-1)).numpy‬‬
‫‪array([[[ 4.5]],‬‬

‫)‪[[14.5]]], dtype=float32‬‬
291 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

Defining the Model 11.2.4.2

‫ نحدد أدناه النسخة المعلمية من انحدار نواة‬،‫باستخدام ضرب مصفوفة الدفعات الصغيرة‬
.)11.2.7( ‫ استنادًا إلى تجميع االنتباه المعلمييف‬Nadaraya-Watson

class NWKernelRegression(d2l.Module):
def __init__(self, keys, values, lr):
super().__init__()
self.save_hyperparameters()
self.w = tf.Variable(tf.ones(1), trainable=True)

def forward(self, queries):


y_hat, self.attention_weights = attention_pool(
diff(queries, self.keys) * self.w,
self.values)
return y_hat

def loss(self, y_hat, y):


l = (tf.reshape(y_hat, -1) - tf.reshape(y, -1))
** 2 / 2
return tf.reduce_mean(l)

def configure_optimizers(self):
return d2l.SGD(self.lr)
Training 11.2.4.3
‫يف‬.‫ نقوم بتحويل مجموعة بيانات التدريب إلى مفاتيح وقيم لتدريب نموذج االنتباه‬،‫فيما يلي‬
‫القيمة‬-‫ يأخذ أي إدخال تدريب فقط أزواج المفتاح‬،‫ من أجل التبسيط‬،‫تجميع االنتباه المعلمي‬
.‫من جميع أمثلة التدريب للتنبؤ بمخرجاته‬

model = NWKernelRegression(data.x_train, data.y_train,


lr=1)
model.board.display = False
trainer = d2l.Trainer(max_epochs=5)
trainer.fit(model, data)
‫ يكون الخط المتوقع أقل سالسة من‬،‫ مجموعة بيانات التدريب بالضوضاء‬fit ‫في محاولة لتالئم‬
.‫نظيره الالمعلمي الذي تم رسمه مسبقًا‬

plot_kernel_reg(model.forward(data.x_val))
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪292‬‬

‫بالمقارنة مع تجميع االنتباه الالمعلمي‪ ،‬تصبح المنطقة ذات أوزان االنتباه الكبيرة أكثر حدةيف ‬
‫الضبط المعلمي‪.‬‬

‫‪d2l.show_heatmaps([[model.attention_weights]],‬‬
‫‪xlabel='Sorted training inputs',‬‬
‫)'‪ylabel='Sorted validation inputs‬‬

‫‪11.2.5‬‬
‫يعد انحدار نواة ‪ Nadaraya-Watson‬مثاالً على التعلم اآللي بآليات االنتباه‪.‬‬ ‫•‬
‫‪293‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫تجميع االنتباه النحدار نواة ‪ Nadaraya-Watson‬هو متوسط اوزان لمخرجات‬ ‫•‬


‫التدريب‪ .‬من منظور االنتباه‪ ،‬يتم تعيين وزن االنتباه إلى قيمة بناءً على دالة استعالم‬
‫والمفتاح المقترن بالقيمة‪.‬‬
‫يمكن أن يكون تجميع االنتباه إما غير معلمي ‪ nonparametric‬أو معلمي‬ ‫•‬
‫‪.parametric‬‬

‫‪11.2.6‬‬
‫‪ .1‬قم بزيادة عدد األمثلة التدريبية‪ .‬هل يمكنك تعلم انحدار نواة ‪Nadaraya-Watson‬‬
‫الالمعلمية بشكل أفضل؟‬
‫‪ .2‬ما هي قيمة ما تعلمناه 𝑤يف تجربة تجميع االنتباه المعلمية؟ لماذا تجعل المنطقة‬
‫الموزونة أكثر حدة عند رسم أوزان االنتباه؟‬
‫‪ .3‬كيف يمكننا إضافة المعلمات الفائقة إلى انحدار نواة ‪Nadaraya-Watson‬‬
‫الالمعلمي للتنبؤ بشكل أفضل؟‬
‫‪ .4‬صمم انتباهاً معلمياً آخر لتجميع االنتباه النحدار النواةيف هذا القسم‪ .‬درب هذا النموذج‬
‫الجديد وارسم أوزان انتباهه‪.‬‬

‫‪Attention Scoring Functions‬‬ ‫‪11.3‬‬


‫في القسم ‪ ،11.2‬استخدمنا نواة غاوسية لنمذجة التفاعالت بين االستعالمات والمفاتيح‪ .‬معالجة‬
‫أس النواة الغاوسيةيف (‪ )11.2.6‬كدالة لتسجيل االنتباه ‪( attention scoring function‬أو‬
‫دالة التسجيل ‪ scoring function‬لالختصار)‪ ،‬تم تغذية نتائج هذه الدالة بشكل أساسييف عملية‬
‫‪ .softmax‬نتيجة لذلك‪ ،‬حصلنا على توزيع احتمالي (أوزان االنتباه) على القيم المقترنة‬
‫بالمفاتيح‪.‬يف النهاية‪ ،‬ناتج تجميع االنتباه هو ببساطة مجموع االوزان للقيم بناءً على أوزان االنتباه‬
‫هذه‪.‬‬

‫الشكل ‪ 11.3.1‬حساب ناتج تجميع االنتباه كمتوسط الوزن للقيم‪.‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪294‬‬

‫على مستوى عالٍ‪ ،‬يمكننا استخدام الخوارزمية أعاله إلنشاء مثيل إلطار آليات االنتباهيف الشكل‬
‫‪ .11.1.3‬يوضح الشكل ‪ ،11.3.1‬الذي يشير إلى دالة تسجيل االنتباه من خالل 𝑎‪ ،‬كيف يمكن‬
‫حساب ناتج تجميع االنتباه كمجموع اوزان من القيم‪ .‬نظرًا ألن أوزان االنتباه هي توزيع احتمالي‪،‬‬
‫فإن مجموع االوزان هويف األساس متوسط موزون‪.‬‬

‫المفتاح–القيمة‬ ‫أزواج‬ ‫و𝑚‬ ‫𝑞‪𝐪 ∈ ℝ‬‬ ‫استعالمًا‬ ‫لدينا‬ ‫أن‬ ‫افترض‬ ‫رياضيًا‪،‬‬
‫) 𝑚𝐯 ‪ ،(𝐤1 , 𝐯1 ), … , (𝐤 𝑚 ,‬حيث كل 𝑘‪ 𝐤 𝑖 ∈ ℝ‬وكل 𝑣‪ .𝐯𝑖 ∈ ℝ‬يتم إنشاء مثيل تجميع االنتباه‬
‫𝑓 كمجموع الوزن للقيم‪:‬‬
‫𝑚‬

‫∑ = )) 𝑚𝐯 ‪𝑓(𝐪, (𝐤1 , 𝐯1 ), … , (𝐤 𝑚 ,‬‬ ‫‪𝛼(𝐪, 𝐤 𝑖 )𝐯𝑖 ∈ ℝ𝑣 ,‬‬


‫‪𝑖=1‬‬

‫حيث يتم حساب وزن االنتباه (‪ )scalar‬لالستعالم 𝐪 والمفتاح 𝑖 𝐤 من خالل عملية ‪softmax‬‬
‫لدالة تسجيل االنتباه 𝑎 التي تعين متجهين إلى القيمة القياسية ‪:scalar‬‬

‫)) 𝑖 𝐤 ‪exp (𝑎(𝐪,‬‬


‫= )) 𝑖 𝐤 ‪𝛼(𝐪, 𝐤 𝑖 ) = softmax(𝑎(𝐪,‬‬ ‫‪∈ ℝ.‬‬
‫𝑚∑‬
‫‪𝑗=1‬‬ ‫)) 𝑗𝐤 ‪exp (𝑎(𝐪,‬‬

‫كما نرى‪ ،‬تؤدي الخيارات المختلفة لدالة تسجيل االنتباه 𝑎 إلى سلوكيات مختلفة لتجميع االنتباه‬
‫‪.attention pooling‬يف هذا القسم‪ ،‬نقدم دالتين شائعتين للتسجيل سنستخدمهما لتطوير آليات‬
‫انتباه أكثر تعقيدًا الحقًا‪.‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Masked Softmax Operation‬‬ ‫‪Softmax‬‬ ‫‪11.3.1‬‬
‫كما ذكرنا للتو‪ ،‬يتم استخدام عملية ‪ softmax‬إلخراج توزيع احتمالي كأوزان لالنتباه‪.‬يف بعض‬
‫الحاالت‪ ،‬ال يجب تغذية جميع القيميف عملية تجميع االنتباه‪ .‬على سبيل المثال‪ ،‬من أجل معالجة‬
‫الدفعات الصغيرة الفعالةيف القسم ‪ ،10.5‬تكون بعض التسلسالت النصية محشوة ‪padded‬‬
‫برموز خاصة ‪ special tokens‬ال تحمل أي معنى‪ .‬لجذب االنتباه إلى الرموز ذات المعنى فقط‬
‫كقيم‪ ،‬يمكننا تحديد طول تسلسل صالح (في عدد الرموز) لتصفية تلك التي تتجاوز هذا النطاق‬
‫المحدد عند حساب ‪ .softmax‬بهذه الطريقة‪ ،‬يمكننا تنفيذ عملية ‪ softmax‬المقنعة هذهيف دالة‬
‫‪ masked_softmax‬التالية‪ ،‬حيث يتم إخفاء أي قيمة تتجاوز الطول الصالح على أنها صفر‪.‬‬

‫‪#@save‬‬
‫‪def masked_softmax(X, valid_lens):‬‬
‫‪"""Perform softmax operation by masking elements on‬‬
‫"""‪the last axis.‬‬
295 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

# X: 3D tensor, valid_lens: 1D or 2D tensor


def _sequence_mask(X, valid_len, value=0):
maxlen = X.shape[1]
mask = tf.range(start=0, limit=maxlen,
dtype=tf.float32)[
None, :] < tf.cast(valid_len[:, None],
dtype=tf.float32)

if len(X.shape) == 3:
return tf.where(tf.expand_dims(mask, axis=-
1), X, value)
else:
return tf.where(mask, X, value)

if valid_lens is None:
return tf.nn.softmax(X, axis=-1)
else:
shape = X.shape
if len(valid_lens.shape) == 1:
valid_lens = tf.repeat(valid_lens,
repeats=shape[1])

else:
valid_lens = tf.reshape(valid_lens, shape=-
1)
# On the last axis, replace masked elements with
a very large negative
# value, whose exponentiation outputs 0
X = _sequence_mask(tf.reshape(X, shape=(-1,
shape[-1])), valid_lens,
value=-1e6)
return tf.nn.softmax(tf.reshape(X, shape=shape),
axis=-1)
، 2 × 4 ‫ ضعيف اعتبارك مجموعة صغيرة من مثالين لمصفوفة‬،‫لتوضيح كيفية عمل هذه الدالة‬
softmax ‫ نتيجة لعملية‬.‫حيث يكون األطوال الصالحة لهذين المثالين اثنين وثالثة على التوالي‬
.‫ يتم إخفاء القيم التي تتجاوز األطوال الصالحة على أنها صفر‬،‫المقنعة‬

masked_softmax(tf.random.uniform(shape=(2, 2, 4)),
tf.constant([2, 3]))
<tf.Tensor: shape=(2, 2, 4), dtype=float32, numpy=
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪296‬‬

‫‪array([[[0.4517647 , 0.54823536, 0.‬‬ ‫‪, 0.‬‬


‫‪],‬‬
‫‪[0.4112412 , 0.5887589 , 0.‬‬ ‫‪, 0.‬‬
‫‪]],‬‬

‫‪[[0.24448606, 0.34571627, 0.40979767, 0.‬‬


‫‪],‬‬
‫‪[0.3740311 , 0.35151485, 0.27445397, 0.‬‬
‫>)‪]]], dtype=float32‬‬
‫وبالمثل‪ ،‬يمكننا أيضًا استخدام موتر ثنائي األبعاد لتحديد أطوال صالحة لكل صفيف كل مثال‬
‫مصفوفة‪.‬‬

‫‪masked_softmax(tf.random.uniform((2, 2, 4)),‬‬
‫))]]‪tf.constant([[1, 3], [2, 4‬‬
‫=‪<tf.Tensor: shape=(2, 2, 4), dtype=float32, numpy‬‬
‫‪array([[[1.‬‬ ‫‪, 0.‬‬ ‫‪, 0.‬‬ ‫‪, 0.‬‬
‫‪],‬‬
‫‪[0.26554373, 0.36378106, 0.37067524, 0.‬‬
‫‪]],‬‬

‫‪[[0.46347728, 0.5365227 , 0.‬‬ ‫‪, 0.‬‬


‫‪],‬‬
‫‪[0.16122091, 0.15872595, 0.29501283,‬‬
‫>)‪0.38504028]]], dtype=float32‬‬
‫‪Additive Attention‬‬ ‫‪11.3.2‬‬
‫بشكل عام‪ ،‬عندما تكون االستعالمات والمفاتيح متجهات ذات أطوال مختلفة‪ ،‬يمكننا استخدام‬
‫االنتباه اإلضافي كدالة لتسجيل النقاط‪ .‬بالنظر إلى االستعالم 𝑞‪ 𝐪 ∈ ℝ‬والمفتاح 𝑘‪ ، 𝐤 ∈ ℝ‬فإن‬
‫دالة تسجيل االنتباه اإلضافي ‪additive attention scoring function‬‬

‫‪𝑎(𝐪, 𝐤) = 𝐰𝑣⊤ tanh(𝐖𝑞 𝐪 + 𝐖𝑘 𝐤) ∈ ℝ,‬‬

‫حيث المعلمات القابلة للتعلم 𝑞×‪ 𝐖𝑘 ∈ ℝℎ×𝑘 ، 𝐖𝑞 ∈ ℝℎ‬و ‪ . 𝐰𝑣 ∈ ℝℎ‬أي ما يعادل‬


‫(‪ ،)11.3.3‬يتم تسلسل االستعالم والمفتاح وإدخالهمايف ‪ MLP‬بطبقة واحدة مخفية يكون عدد‬
‫الوحدات المخفية فيها ‪ ، ℎ‬وهي معلمة فائقة‪ .‬باستخدام دالة التنشيط ‪ tanh‬وتعطيل شروط‬
‫التحيز‪ ،‬فإننا ننفذ اهتمامًا إضافيًا فيما يلي‪.‬‬

‫‪#@save‬‬
‫‪class AdditiveAttention(tf.keras.layers.Layer):‬‬
297 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

"""Additive attention."""
def __init__(self, key_size, query_size,
num_hiddens, dropout, **kwargs):
super().__init__(**kwargs)
self.W_k = tf.keras.layers.Dense(num_hiddens,
use_bias=False)
self.W_q = tf.keras.layers.Dense(num_hiddens,
use_bias=False)
self.w_v = tf.keras.layers.Dense(1,
use_bias=False)
self.dropout = tf.keras.layers.Dropout(dropout)

def call(self, queries, keys, values, valid_lens,


**kwargs):
queries, keys = self.W_q(queries),
self.W_k(keys)
# After dimension expansion, shape of queries:
(batch_size, no. of
# queries, 1, num_hiddens) and shape of keys:
(batch_size, 1, no. of
# key-value pairs, num_hiddens). Sum them up
with broadcasting
features = tf.expand_dims(queries, axis=2) +
tf.expand_dims(
keys, axis=1)
features = tf.nn.tanh(features)
# There is only one output of self.w_v, so we
remove the last
# one-dimensional entry from the shape. Shape of
scores: (batch_size,
# no. of queries, no. of key-value pairs)
scores = tf.squeeze(self.w_v(features), axis=-1)
self.attention_weights = masked_softmax(scores,
valid_lens)
# Shape of values: (batch_size, no. of key-value
pairs, value
# dimension)
return tf.matmul(self.dropout(
self.attention_weights, **kwargs), values)
،‫ حيث األشكال (حجم الدُفعة‬، ‫ أعاله مع مثال لعبة‬AdditiveAttention ‫دعنا نوضح فئة‬
‫ حجم الميزة) لالستعالمات والمفاتيح والقيم هي‬،‫عدد الخطوات أو طول التسلسليف الرموز‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 298

‫ ناتج تجميع االنتباه له شكل (حجم‬.‫ على التوالى‬،) 2،10،4( ‫ و‬، )2،10،2( ، )2،1،20(
.)‫ حجم الميزة للقيم‬،‫ عدد خطوات االستعالمات‬،‫الدُفعة‬

queries, keys = tf.random.normal(shape=(2, 1, 20)),


tf.ones((2, 10, 2))
# The two value matrices in the values minibatch are
identical
values = tf.repeat(tf.reshape(
tf.range(40, dtype=tf.float32), shape=(1, 10, 4)),
repeats=2, axis=0)
valid_lens = tf.constant([2, 6])

attention = AdditiveAttention(key_size=2, query_size=20,


num_hiddens=8,
dropout=0.1)
attention(queries, keys, values, valid_lens,
training=False)
<tf.Tensor: shape=(2, 1, 4), dtype=float32, numpy=
array([[[ 2. , 3. , 4. , 5. ]],

[[10. , 11. , 12.000001, 13. ]]],


dtype=float32)>
‫ يحتوي على معلمات قابلة للتعلم‬additive attention ‫على الرغم من أن االنتباه اإلضافي‬
‫ فإن أوزان االنتباه تكون‬،‫ نظرًا ألن كل مفتاح هو نفسهيف هذا المثال‬،learnable parameters
.‫ ويتم تحديدها من خالل األطوال الصالحة المحددة‬،uniform ‫منتظم‬

d2l.show_heatmaps(tf.reshape(attention.attention_weights
, (1, 1, 2, 10)),
xlabel='Keys', ylabel='Queries')
‫‪299‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪Scaled Dot-Product Attention‬‬ ‫‪11.3.3‬‬


‫يمكن أن يكون التصميم األكثر كفاءة من الناحية الحسابية لدالة التسجيل مجرد ضرب نقطي‬
‫‪ .dot product‬ومع ذلك‪ ،‬تتطلب عملية الضرب النقطي أن يكون لكل من االستعالم والمفتاح‬
‫نفس طول المتجه‪ ،‬على سبيل المثال 𝑑‪ .‬افترض أن جميع عناصر االستعالم والمفتاح عبارة عن‬
‫متغيرات عشوائية مستقلة بمتوسط صفري وتباين الوحدة‪ .‬حاصل الضرب النقطي لكال المتجهين‬
‫له متوسط صفري وتباين قدره 𝑑‪ .‬للتأكد من أن تباين الضرب النقطي ال يزال واحدًا بغض النظر‬
‫عن طول المتجه‪ ،‬فإن دالة تسجيل انتباه المنتج النقطي المقاس ‪scaled dot-product‬‬
‫‪attention scoring function‬‬

‫𝑑√‪𝑎(𝐪, 𝐤) = 𝐪⊤ 𝐤/‬‬

‫قسمة الضرب النقطي على 𝑑√‪ .‬من الناحية العملية‪ ،‬غالبًا ما نفكريف الدفعات الصغيرة من أجل‬
‫الكفاءة‪ ،‬مثل االهتمام الحاسوبي لالستعالمات 𝑛 وأزواج القيمة والمفاتيح 𝑚‪ ،‬حيث تكون‬
‫االستعالمات والمفاتيح ذات طول 𝑑 والقيم ذات طول 𝑣‪ .‬يتم قياس انتباه الضرب النقطي‬
‫لالستعالمات 𝑑×𝑛‪ 𝐐 ∈ ℝ‬والمفاتيح 𝑑×𝑚‪ 𝐊 ∈ ℝ‬والقيم 𝑣×𝑚‪𝐕 ∈ ℝ‬‬

‫⊤ 𝐊𝐐‬
‫(‪softmax‬‬ ‫‪)𝐕 ∈ ℝ𝑛×𝑣 .‬‬
‫𝑑√‬
‫في التنفيذ التالي النتباه الضرب النقطي المقاس ‪ ،scaled dot product attention‬نستخدم‬
‫التسرب ‪ dropout‬من أجل تسوية النموذج‪.‬‬

‫‪#@save‬‬
‫‪class DotProductAttention(tf.keras.layers.Layer):‬‬
‫"""‪"""Scaled dot product attention.‬‬
‫‪def __init__(self, dropout, num_heads=None):‬‬
‫)(__‪super().__init‬‬
‫)‪self.dropout = tf.keras.layers.Dropout(dropout‬‬
‫‪self.num_heads = num_heads # To be covered‬‬
‫‪later‬‬

‫)‪# Shape of queries: (batch_size, no. of queries, d‬‬


‫‪# Shape of keys: (batch_size, no. of key-value‬‬
‫)‪pairs, d‬‬
‫‪# Shape of values: (batch_size, no. of key-value‬‬
‫)‪pairs, value dimension‬‬
‫‪# Shape of valid_lens: (batch_size,) or (batch_size,‬‬
‫)‪no. of queries‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 300

def call(self, queries, keys, values,


valid_lens=None, window_mask=None,
**kwargs):
d = queries.shape[-1]
scores = tf.matmul(queries, keys,
transpose_b=True)/tf.math.sqrt(
tf.cast(d, dtype=tf.float32))
if window_mask is not None: # To be covered
later
num_windows = window_mask.shape[0]
n, num_queries, num_kv_pairs = scores.shape
# Shape of window_mask: (num_windows, no. of
queries,
# no. of key-value pairs)
scores = tf.reshape(
scores,
(n//(num_windows*self.num_heads), num_windows,
self.num_heads, num_queries,
num_kv_pairs
)) + tf.expand_dims(
tf.expand_dims(window_mask, 1), 0)
scores = tf.reshape(scores, (n, num_queries,
num_kv_pairs))
self.attention_weights = masked_softmax(scores,
valid_lens)
return
tf.matmul(self.dropout(self.attention_weights,
**kwargs), values)
‫ نستخدم نفس المفاتيح والقيم واألطوال‬،‫ أعاله‬DotProductAttention ‫إلثبات فئة‬
‫ نجعل حجم‬،‫ بالنسبة لعملية الضرب النقطي‬.‫الصالحة من مثال اللعبة السابق لالهتمام اإلضافي‬
.‫ميزة االستعالمات هو نفسه حجم المفاتيح‬

queries = tf.random.normal(shape=(2, 1, 2))


attention = DotProductAttention(dropout=0.5)
attention(queries, keys, values, valid_lens,
training=False)
<tf.Tensor: shape=(2, 1, 4), dtype=float32, numpy=
array([[[ 2. , 3. , 4. , 5. ]],

[[10. , 11. , 12.000001, 13. ]]],


dtype=float32)>
‫‪301‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫كما هو الحاليف عرض االنتباه اإلضافي ‪ ،additive attention‬نظرًا ألن المفاتيح تحتوي على‬
‫نفس العنصر الذي ال يمكن تمييزه بأي استعالم‪ ،‬يتم الحصول على أوزان انتباه موحدة‬
‫‪.uniform attention weights‬‬

‫‪d2l.show_heatmaps(tf.reshape(attention.attention_weights‬‬
‫‪, (1, 1, 2, 10)),‬‬
‫)'‪xlabel='Keys', ylabel='Queries‬‬

‫‪11.3.4‬‬
‫يمكننا حساب ناتج تجميع االنتباه كمتوسط الوزن للقيم‪ ،‬حيث تؤدي االختيارات‬ ‫•‬
‫المختلفة لدالة تسجيل االنتباه إلى سلوكيات مختلفة لتجميع االنتباه‪.‬‬
‫عندما تكون االستعالمات والمفاتيح متجهات ذات أطوال مختلفة‪ ،‬يمكننا استخدام‬ ‫•‬
‫دالة تسجيل االنتباه اإلضافي‪ .‬عندما تكون متطابقة‪ ،‬تكون دالة تسجيل انتباه المنتج‬
‫النقطي المقاسة أكثر كفاءة من الناحية الحسابية‪.‬‬

‫‪11.3.5‬‬
‫‪ .1‬قم بتعديل المفاتيحيف مثال اللعبة وارسم أوزان االنتباه‪ .‬هل االنتباه اإلضافي وانتباه‬
‫المنتج النقطي المقاس ال يزاالن ينتجان نفس أوزان االنتباه؟ لما ولما ال؟‬
‫‪ .2‬باستخدام ضرب المصفوفة فقط‪ ،‬هل يمكنك تصميم دالة تسجيل جديدة‬
‫لالستعالمات والمفاتيح ذات أطوال متجهات مختلفة؟‬
‫‪ .3‬عندما يكون لالستعالمات والمفاتيح نفس طول المتجه‪ ،‬فهل يعد جمع المتجهات‬
‫تصميمًا أفضل من حاصل الضرب النقطي لدالة التسجيل؟ لما ولما ال؟‬

‫‪Bahdanau‬‬ ‫‪11.4‬‬
‫لقد درسنا مشكلة الترجمة اآلليةيف القسم ‪ ،10.7‬حيث صممنا معمارية المشفر‪-‬مفكك الشفرة‬
‫على أساس اثنين من ‪ RNNs‬لتعلم التسلسل‪-‬التسلسل ‪sequence to sequence‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪302‬‬

‫‪ .learning‬على وجه التحديد‪ ،‬يقوم مشفر ‪ RNN‬بتحويل تسلسل متغير الطول إلى متغير سياق‬
‫ذو شكل ثابت‪ ،‬ثم يقوم مفكك شفرة ‪ RNN‬بإنشاء رمز تسلسل اإلخراج (الهدف) بواسطة‬
‫الرمز ‪ token‬بناءً على الرموز المتولدة ومتغير السياق‪ .‬ومع ذلك‪ ،‬على الرغم من أن جميع رموز‬
‫اإلدخال (المصدر) ليست مفيدة لفك تشفير رمز معين‪ ،‬إال أن متغير السياق نفسه الذي يشفر‬
‫تسلسل اإلدخال بالكامل ال يزال مستخدمًايف كل خطوة فك تشفير‪.‬‬

‫في تحدٍ منفصل ولكنه مرتبط بتوليد الكتابة اليدوية لتسلسل نصي معين‪ ،‬صمم ‪ Graves‬نموذجًا‬
‫مختلفًا لالنتباه لمحاذاة أحرف النص مع تتبع القلم األطول بكثير‪ ،‬حيث تتحرك المحاذاةيف اتجاه‬
‫واحد فقط (‪ .)2013 ،Graves‬مستوحاة من فكرة تعلم المحاذاة‪ .Bahdanau et al ،‬اقترح‬
‫نموذج اهتمام متباين دون قيود المحاذاة أحادية االتجاه الشديدة (‪.)2014 ،Bahdanau et al.‬‬
‫عند توقع رمز‪ ،‬إذا لم تكن جميع الرموز لإلدخال ذات صلة‪ ،‬فإن النموذج يحاذي (أو يحضر‬
‫‪ )attends‬فقط ألجزاء من تسلسل اإلدخال ذات الصلة بالتنبؤ الحالي‪ .‬يتم تحقيق ذلك من خالل‬
‫معاملة متغير السياق كناتج لتجميع االنتباه‪.‬‬

‫‪Model‬‬ ‫‪11.4.1‬‬
‫عند وصف انتباه ‪ Bahdanau‬لمشفر‪-‬مفكك شفرة ‪ RNN‬أدناه‪ ،‬سوف نتبع نفس الترميزيف ‬
‫القسم ‪ .10.7‬النموذج الجديد القائم على االنتباه هو نفسه الموجوديف القسم ‪ 10.7‬فيما عدا أنه‬
‫يتم استبدال متغير السياق 𝐜يف (‪ )10.7.3‬بـ ‪𝐜𝑡 ′‬يف أي خطوة زمنية ‪ 𝐜𝑡 ′‬لفك التشفير‪ .‬لنفترض أن‬
‫هناك رموزًا 𝑇يف تسلسل اإلدخال‪ ،‬متغير السياقيف الخطوة الزمنية ‪ 𝑡 ′‬لفك التشفير هو ناتج تجميع‬
‫االنتباه‪:‬‬
‫𝑇‬

‫∑ = ‪𝐜𝑡 ′‬‬ ‫‪𝛼(𝐬𝑡 ′ −1 , 𝐡𝑡 )𝐡𝑡 ,‬‬


‫‪𝑡=1‬‬

‫حيث تكون الحالة المخفية ‪ 𝐬𝑡 ′ −1‬لوحدة لمفكك الشفرةيف الخطوة الزمنية ‪ 𝑡 ′ − 1‬هي‬
‫االستعالم‪ ،‬وتكون الحاالت المخفية 𝑡𝐡 للمشفر هي المفاتيح والقيم‪ ،‬ويتم حساب وزن االنتباه‬
‫𝛼 كمايف (‪ )11.3.2‬باستخدام دالة تسجيل االنتباه اإلضافي المقاسة بواسطة (‪.)11.3.3‬‬

‫تختلف قليالً عن معمارية مشفر‪-‬مفكك شفرة ‪vanilla RNN‬يف الشكل‪ ،10.7.2 .‬تم توضيح‬
‫نفس المعمارية مع انتباه ‪Bahdanau‬يف الشكل ‪.11.4.1‬‬
‫‪303‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫الشكل ‪ 11.4.1‬طبقاتيف نموذج مشفر‪-‬مفكك شفرة ‪ RNN‬مع اهتمام ‪.Bahdanau‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Defining the Decoder with‬‬ ‫‪11.4.2‬‬
‫‪Attention‬‬
‫لتنفيذ مشفر‪-‬مفكك شفرة ‪ RNN‬مع انتباه ‪ ،Bahdanau‬نحتاج فقط إلى إعادة تعريف مفكك‬
‫الشفرة ‪ .decoder‬لرسم أوزان االنتباه المكتسبة بشكل أكثر مالءمة‪ ،‬تحدد فئة‬
‫‪AttentionDecoder‬التالية الواجهة األساسية مفكك الشفرة بآليات االنتباه‪.‬‬

‫‪#@save‬‬
‫‪class AttentionDecoder(d2l.Decoder):‬‬
‫"""‪"""The base attention-based decoder interface.‬‬
‫‪def __init__(self):‬‬
‫)(__‪super().__init‬‬

‫‪@property‬‬
‫‪def attention_weights(self):‬‬
‫‪raise NotImplementedError‬‬
‫فئة‬ ‫شفرة ‪ RNN‬مع انتباه ‪Bahdanau‬يف ‬ ‫مفكك‬ ‫نطبق‬ ‫دعنا‬ ‫اآلن‬
‫‪Seq2SeqAttentionDecoder‬التالية‪ .‬تتم تهيئة حالة مفكك الشفرة بـ (‪ )1‬حاالت‬
‫الطبقة النهائية المشفرة المخفيةيف جميع خطوات الوقت (كمفاتيح وقيم االنتباه) ؛ (‪ )2‬الحالة‬
‫المخفية لجميع طبقات المشفريف الخطوة الزمنية النهائية (لتهيئة الحالة المخفية لمفكك‬
‫الشفرة)؛ و (‪ )3‬الطول الصالح للمشفر (الستبعاد رموز الحشويف تجميع االنتباه)‪.‬يف كل خطوة‬
‫زمنية لمفكك الشفرة‪ ،‬تُستخدم الحالة المخفية للطبقة النهائية لمفكك الشفرةيف الخطوة الزمنية‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 304

‫ يتم تسلسل كل من إخراج االنتباه وتضمين المدخالت‬،‫ نتيجة لذلك‬.‫السابقة كاستعالم لالنتباه‬
.RNN ‫كمدخالت لمفكك شفرة‬

class Seq2SeqAttentionDecoder(AttentionDecoder):
def __init__(self, vocab_size, embed_size,
num_hiddens, num_layers,
dropout=0):
super().__init__()
self.attention =
d2l.AdditiveAttention(num_hiddens, num_hiddens,

num_hiddens, dropout)
self.embedding =
tf.keras.layers.Embedding(vocab_size, embed_size)
self.rnn =
tf.keras.layers.RNN(tf.keras.layers.StackedRNNCells(
[tf.keras.layers.GRUCell(num_hiddens,
dropout=dropout)
for _ in range(num_layers)]),
return_sequences=True,

return_state=True)
self.dense = tf.keras.layers.Dense(vocab_size)

def init_state(self, enc_outputs, enc_valid_lens):


# Shape of outputs: (batch_size, num_steps,
num_hiddens).
# Length of list hidden_state is num_layers,
where the shape of its
# element is (batch_size, num_hiddens)
outputs, hidden_state = enc_outputs
return (tf.transpose(outputs, (1, 0, 2)),
hidden_state,
enc_valid_lens)

def call(self, X, state, **kwargs):


# Shape of output enc_outputs: # (batch_size,
num_steps, num_hiddens)
# Length of list hidden_state is num_layers,
where the shape of its
# element is (batch_size, num_hiddens)
305 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

enc_outputs, hidden_state, enc_valid_lens =


state
# Shape of the output X: (num_steps, batch_size,
embed_size)
X = self.embedding(X) # Input X has shape:
(batch_size, num_steps)
X = tf.transpose(X, perm=(1, 0, 2))
outputs, self._attention_weights = [], []
for x in X:
# Shape of query: (batch_size, 1,
num_hiddens)
query = tf.expand_dims(hidden_state[-1],
axis=1)
# Shape of context: (batch_size, 1,
num_hiddens)
context = self.attention(query, enc_outputs,
enc_outputs,
enc_valid_lens,
**kwargs)
# Concatenate on the feature dimension
x = tf.concat((context, tf.expand_dims(x,
axis=1)), axis=-1)
out = self.rnn(x, hidden_state, **kwargs)
hidden_state = out[1:]
outputs.append(out[0])

self._attention_weights.append(self.attention.attention_
weights)
# After fully connected layer transformation,
shape of outputs:
# (batch_size, num_steps, vocab_size)
outputs = self.dense(tf.concat(outputs, axis=1))
return outputs, [enc_outputs, hidden_state,
enc_valid_lens]

@property
def attention_weights(self):
return self._attention_weights
4 ‫ باستخدام الدفعات الصغيرة من‬Bahdanau ‫ نختبر مفكك الشفرة المنفذ مع انتباه‬،‫فيما يلي‬
.‫ خطوات زمنية‬7 ‫مدخالت تسلسلية من‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 306

vocab_size, embed_size, num_hiddens, num_layers = 10, 8,


16, 2
batch_size, num_steps = 4, 7
encoder = d2l.Seq2SeqEncoder(vocab_size, embed_size,
num_hiddens, num_layers)
decoder = Seq2SeqAttentionDecoder(vocab_size,
embed_size, num_hiddens,
num_layers)
X = tf.zeros((batch_size, num_steps))
state = decoder.init_state(encoder(X, training=False),
None)
output, state = decoder(X, state, training=False)
d2l.check_shape(output, (batch_size, num_steps,
vocab_size))
d2l.check_shape(state[0], (batch_size, num_steps,
num_hiddens))
d2l.check_shape(state[1][0], (batch_size, num_hiddens))
Training 11.4.3
‫ وننشئ مثيلًا للمشفر ومفكك الشفرة‬،‫ نحدد هنا المعلمات الفائقة‬،10.7.6 ‫على غرار القسم‬
.‫ ونقوم بتدريب هذا النموذج على الترجمة اآللية‬،Bahdanau ‫بانتباه‬

data = d2l.MTFraEng(batch_size=128)
embed_size, num_hiddens, num_layers, dropout = 256, 256,
2, 0.2
with d2l.try_gpu():
encoder = d2l.Seq2SeqEncoder(
len(data.src_vocab), embed_size, num_hiddens,
num_layers, dropout)
decoder = Seq2SeqAttentionDecoder(
len(data.tgt_vocab), embed_size, num_hiddens,
num_layers, dropout)
model = d2l.Seq2Seq(encoder, decoder,
tgt_pad=data.tgt_vocab['<pad>'],
lr=0.005)
trainer = d2l.Trainer(max_epochs=50,
gradient_clip_val=1)
trainer.fit(model, data)
307 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

‫ نستخدمه لترجمة بعض الجمل اإلنجليزية إلى الفرنسية وحساب نقاطهم‬،‫بعد تدريب النموذج‬
BLEU ‫في‬

engs = ['go .', 'i lost .', 'he\'s calm .', 'i\'m home
.']
fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je
suis chez moi .']
preds, _ = model.predict_step(
data.build(engs, fras), d2l.try_gpu(),
data.num_steps)
for en, fr, p in zip(engs, fras, preds):
translation = []
for token in data.tgt_vocab.to_tokens(p):
if token == '<eos>':
break
translation.append(token)
print(f'{en} => {translation}, bleu,'
f'{d2l.bleu(" ".join(translation), fr,
k=2):.3f}')
go . => ['va', '!'], bleu,1.000
i lost . => ["j'ai", 'perdu', '.'], bleu,1.000
he's calm . => ['il', 'est', 'mouillé', '.'], bleu,0.658
i'm home . => ['je', 'suis', 'chez', 'moi', '.'],
bleu,1.000
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪308‬‬

‫من خالل رسم أوزان االنتباه عند ترجمة الجملة اإلنجليزية األخيرة‪ ،‬يمكننا أن نرى أن كل استعالم‬
‫يعين أوزانًا غير موحدة على أزواج المفتاح‪-‬القيمة‪ .‬يوضح أنهيف كل خطوة من خطوات فك‬
‫التشفير‪ ،‬يتم تجميع أجزاء مختلفة من تسلسل اإلدخال بشكل انتقائييف تجميع االنتباه‪.‬‬

‫(‪_, dec_attention_weights = model.predict_step‬‬


‫‪data.build([engs[-1]], [fras[-1]]), d2l.try_gpu(),‬‬
‫)‪data.num_steps, True‬‬
‫(‪attention_weights = tf.reshape‬‬
‫‪tf.concat([step[0][0][0] for step in‬‬
‫‪dec_attention_weights], 0),‬‬
‫))‪(1, 1, -1, data.num_steps‬‬

‫‪# Plus one to include the end-of-sequence token‬‬


‫‪d2l.show_heatmaps(attention_weights[:, :, :, :len(engs[-‬‬
‫‪1].split()) + 1],‬‬
‫‪xlabel='Key positions', ylabel='Query‬‬
‫)'‪positions‬‬

‫‪11.4.4‬‬
‫عند توقع رمز ‪ ،token‬إذا لم تكن جميع الرموز لإلدخال ذات صلة‪ ،‬فإن مشفر‪-‬مفكك‬ ‫•‬
‫شفرة ‪ RNN‬مع انتباه ‪ Bahdanau‬تجمع بشكل انتقائي أجزاء مختلفة من تسلسل‬
‫اإلدخال‪ .‬يتم تحقيق ذلك من خالل معاملة متغير السياق كناتج لتجميع االنتباه‬
‫اإلضافي‪.‬‬
‫‪309‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫في مشفر‪-‬مفكك شفرة‪ ، RNN‬يتعامل انتباه ‪ Bahdanau‬مع الحالة المخفية‬ ‫•‬


‫لمفكك الشفرةيف الخطوة الزمنية السابقة على أنها االستعالم‪ ،‬والحاالت المخفيةيف ‬
‫جميع الخطوات الزمنية كمفاتيح وقيم‪.‬‬

‫‪11.4.5‬‬
‫‪ .1‬استبدل ‪ GRU‬بـ ‪LSTM‬يف التجربة‪.‬‬
‫‪ .2‬قم بتعديل التجربة الستبدال دالة تسجيل االنتباه اإلضافي ‪additive attention‬‬
‫‪ scoring function‬بالمنتج النقطي المقاس ‪ .scaled dot-product‬كيف تؤثر‬
‫على كفاءة التدريب؟‬

‫‪Multi-Head Attention‬‬ ‫‪11.5‬‬


‫من الناحية العملية‪ ،‬بالنظر إلى نفس مجموعة االستعالمات والمفاتيح والقيم‪ ،‬قد نرغبيف أن‬
‫يجمع نموذجنا المعرفة من السلوكيات المختلفة لنفس آلية االنتباه‪ ،‬مثل التقاط التبعيات من‬
‫نطاقات مختلفة (على سبيل المثال‪ ،‬المدى األقصر مقابل المدى األطول) ضمن تسلسل‪.‬‬
‫وبالتالي‪ ،‬قد يكون من المفيد السماح آللية انتباهنا باالستخدام المشترك لمساحات تمثيل فرعية‬
‫مختلفة من االستعالمات والمفاتيح والقيم‪.‬‬

‫الشكل ‪ 11.5.1‬االنتباه متعدد الرؤوس‪ ،‬حيث يتم ربط عدة رؤوس متسلسلة ثم تحويلها خطيًا‪.‬‬

‫تحقيقًا لهذه الغاية‪ ،‬بدالً من إجراء تجميع واحد لالنتباه‪ ،‬يمكن تحويل االستعالمات والمفاتيح‬
‫والقيم باستخدام اإلسقاطات الخطية المكتسبة بشكل مستقل ‪ .ℎ‬ثم يتم إدخال هذه االستعالمات‬
‫والمفاتيح والقيم المتوقعة على شكل ‪ℎ‬يف تجميع االنتباه بشكل متوازٍ‪.‬يف النهاية‪ ،‬يتم ربط نواتج‬
‫تجميع االنتباه ‪ ℎ‬وتحويلها بإسقاط خطي مكتسب آخر إلنتاج الناتج النهائي‪ .‬يُطلق على هذا‬
‫التصميم االهتمام متعدد الرؤوس ‪ ،multi-head attention‬حيث يكون كل من مخرجات‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪310‬‬

‫تجميع االنتباه ‪ ℎ‬رأسًا (‪ .)2017 ،Vaswani et al.‬باستخدام طبقات متصلة بالكامل إلجراء‬
‫تحويالت خطية قابلة للتعلم‪ ،‬يصف الشكل ‪ 11.5.1‬االنتباه متعدد الرؤوس‪.‬‬

‫‪Model‬‬ ‫‪11.5.1‬‬
‫قبل تقديم االنتباه متعدد الرؤوس‪ ،‬دعنا نضفى الطابع الرسمي على هذا النموذج رياضيًا‪ .‬بالنظر‬
‫إلى االستعالم 𝑞𝑑‪ 𝐪 ∈ ℝ‬والمفتاح 𝑘𝑑‪ 𝐤 ∈ ℝ‬والقيمة 𝑣𝑑‪ ،𝐯 ∈ ℝ‬يتم حساب كل رأس انتباه‬
‫(‪ 𝐡𝑖 )𝑖 = 1, … , ℎ‬على أنه‬
‫)𝑞(‬ ‫)𝑘(‬ ‫)𝑣(‬
‫‪𝐡𝑖 = 𝑓(𝐖𝑖 𝐪, 𝐖𝑖 𝐤, 𝐖𝑖 𝐯) ∈ ℝ𝑝𝑣 ,‬‬
‫)𝑣(‬ ‫)𝑘(‬ ‫)𝑞(‬
‫𝑖𝐖‪،‬‬ ‫𝑖𝐖و 𝑣𝑑× 𝑣𝑝‪∈ ℝ‬‬ ‫𝑖𝐖و 𝑘𝑑× 𝑘𝑝‪∈ ℝ‬‬ ‫حيث المعلمات القابلة للتعلم 𝑞𝑑× 𝑞𝑝‪∈ ℝ‬‬
‫وهو عبارة عن تجميع لالنتباه‪ ،‬مثل االهتمام اإلضافي واهتمام المنتج النقطي المقاسيف القسم‬
‫‪ . 11.3‬ناتج االنتباه متعدد الرؤوس هو تحول خطي آخر عبر معلمات قابلة للتعلم ∈ 𝑜𝐖‬
‫𝑣𝑝‪ ℝ𝑝𝑜 ×ℎ‬لتسلسل الرؤوس ‪:ℎ‬‬

‫‪𝐡1‬‬
‫‪𝐖𝑜 [ ⋮ ] ∈ ℝ𝑝𝑜 .‬‬
‫‪𝐡ℎ‬‬

‫بناءً على هذا التصميم‪ ،‬قد يحضر كل رأس أجزاء مختلفة من اإلدخال‪ .‬يمكن التعبير عن دوال‬
‫أكثر تعقيدًا من متوسط الوزن البسيط‪.‬‬

‫‪import tensorflow as tf‬‬


‫‪from d2l import tensorflow as d2l‬‬
‫‪Implementation‬‬ ‫‪11.5.2‬‬
‫في تنفيذنا‪ ،‬نختار انتباه المنتج النقطي المقاس لكل رأس من االنتباه متعدد الرؤوس‪ .‬لتجنب‬
‫النمو الكبيريف التكلفة الحسابية وتكلفة المعلمات‪ ،‬قمنا بتعيين ‪.𝑝𝑞 = 𝑝𝑘 = 𝑝𝑣 = 𝑝𝑜 /ℎ‬‬
‫الحظ أنه يمكن حساب الرؤوس ‪ ℎ‬بالتوازي إذا قمنا بتعيين عدد مخرجات التحويالت الخطية‬
‫لالستعالم والمفتاح والقيمة الى 𝑜𝑝 = ‪.𝑝𝑞 ℎ = 𝑝𝑘 ℎ = 𝑝𝑣 ℎ‬يف التنفيذ التالي‪ 𝑝𝑜 ،‬يتم تحديده‬
‫عبر الوسيطة ‪.num_hiddens‬‬

‫‪#@save‬‬
‫‪class MultiHeadAttention(d2l.Module):‬‬
‫"""‪"""Multi-head attention.‬‬
‫‪def __init__(self, key_size, query_size, value_size,‬‬
‫‪num_hiddens,‬‬
‫‪num_heads, dropout, bias=False,‬‬
‫‪**kwargs):‬‬
311 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

super().__init__()
self.num_heads = num_heads
self.attention =
d2l.DotProductAttention(dropout, num_heads)
self.W_q = tf.keras.layers.Dense(num_hiddens,
use_bias=bias)
self.W_k = tf.keras.layers.Dense(num_hiddens,
use_bias=bias)
self.W_v = tf.keras.layers.Dense(num_hiddens,
use_bias=bias)
self.W_o = tf.keras.layers.Dense(num_hiddens,
use_bias=bias)

def call(self, queries, keys, values, valid_lens,


window_mask=None,
**kwargs):
# Shape of queries, keys, or values:
# (batch_size, no. of queries or key-value
pairs, num_hiddens)
# Shape of valid_lens: (batch_size,) or
(batch_size, no. of queries)
# After transposing, shape of output queries,
keys, or values:
# (batch_size * num_heads, no. of queries or
key-value pairs,
# num_hiddens / num_heads)
queries = self.transpose_qkv(self.W_q(queries))
keys = self.transpose_qkv(self.W_k(keys))
values = self.transpose_qkv(self.W_v(values))

if valid_lens is not None:


# On axis 0, copy the first item (scalar or
vector) for num_heads
# times, then copy the next item, and so on
valid_lens = tf.repeat(valid_lens,
repeats=self.num_heads, axis=0)

# Shape of output: (batch_size * num_heads, no.


of queries,
# num_hiddens / num_heads)
output = self.attention(queries, keys, values,
valid_lens,
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 312

window_mask, **kwargs)

# Shape of output_concat: (batch_size, no. of


queries, num_hiddens)
output_concat = self.transpose_output(output)
return self.W_o(output_concat)
MultiHeadAttention ‫ تستخدم فئة‬،‫للسماح بالحساب المتوازي لرؤوس متعددة‬
‫ تعكس طريقة‬،‫ على وجه التحديد‬.‫المذكورة أعاله طريقتين للتبديل على النحو المحدد أدناه‬
.transpose_qkv ‫ عملية طريقة‬transpose_output

@d2l.add_to_class(MultiHeadAttention) #@save
def transpose_qkv(self, X):
"""Transposition for parallel computation of
multiple attention heads."""
# Shape of input X: (batch_size, no. of queries or
key-value pairs,
# num_hiddens). Shape of output X: (batch_size, no.
of queries or
# key-value pairs, num_heads, num_hiddens /
num_heads)
X = tf.reshape(X, shape=(X.shape[0], X.shape[1],
self.num_heads, -1))
# Shape of output X: (batch_size, num_heads, no. of
queries or key-value
# pairs, num_hiddens / num_heads)
X = tf.transpose(X, perm=(0, 2, 1, 3))
# Shape of output: (batch_size * num_heads, no. of
queries or key-value
# pairs, num_hiddens / num_heads)
return tf.reshape(X, shape=(-1, X.shape[2],
X.shape[3]))

@d2l.add_to_class(MultiHeadAttention) #@save
def transpose_output(self, X):
"""Reverse the operation of transpose_qkv."""
X = tf.reshape(X, shape=(-1, self.num_heads,
X.shape[1], X.shape[2]))
X = tf.transpose(X, perm=(0, 2, 1, 3))
return tf.reshape(X, shape=(X.shape[0], X.shape[1],
-1))
‫‪313‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫دعونا نختبر فئة ‪ MultiHeadAttention‬المنفذة لدينا باستخدام مثال لعبة حيث المفاتيح‬
‫والقيم هي نفسها‪ .‬نتيجة لذلك‪ ،‬يكون شكل ناتج االنتباه متعدد الرؤوس هو (حجم_الدفعة‬
‫المخفية‬ ‫الحاالت‬ ‫عدد‬ ‫‪،num_queries‬‬ ‫عدد_االستعالمات‬ ‫‪،batch_size‬‬
‫‪.)num_hiddens‬‬

‫‪num_hiddens, num_heads = 100, 5‬‬


‫‪attention = MultiHeadAttention(num_hiddens, num_hiddens,‬‬
‫‪num_hiddens,‬‬
‫‪num_hiddens, num_heads,‬‬
‫)‪0.5‬‬

‫‪batch_size, num_queries, num_kvpairs, valid_lens = 2, 4,‬‬


‫)]‪6, tf.constant([3, 2‬‬
‫))‪X = tf.ones((batch_size, num_queries, num_hiddens‬‬
‫))‪Y = tf.ones((batch_size, num_kvpairs, num_hiddens‬‬
‫‪d2l.check_shape(attention(X, Y, Y, valid_lens,‬‬
‫‪training=False),‬‬
‫))‪(batch_size, num_queries, num_hiddens‬‬
‫‪11.5.3‬‬
‫يجمع االنتباه متعدد الرؤوس بين معرفة نفس تجميع االنتباه عبر مساحات تمثيل فرعية‬ ‫•‬
‫مختلفة من االستعالمات والمفاتيح والقيم‪.‬‬
‫لحساب رؤوس متعددة لالنتباه متعدد الرؤوس بشكل متوازٍ‪ ،‬هناك حاجة إلى معالجة‬ ‫•‬
‫موتر مناسبة‪.‬‬

‫‪11.5.4‬‬
‫‪ .1‬ارسم أوزان االنتباه لرؤوس متعددةيف هذه التجربة‪.‬‬
‫‪ .2‬افترض أن لدينا نموذجًا مدربًا يعتمد على االنتباه متعدد الرؤوس ونريد تقليم رؤوس‬
‫االنتباه األقل أهمية لزيادة سرعة التنبؤ‪ .‬كيف يمكننا تصميم تجارب لقياس أهمية رأس‬
‫االنتباه؟‬

‫‪Self-Attention and‬‬ ‫‪11.6‬‬


‫‪Positional Encoding‬‬
‫في التعلم العميق‪ ،‬غالبًا ما نستخدم شبكات ‪ CNN‬أو ‪ RNN‬لتشفير التسلسل ‪.sequence‬‬
‫اآلن مع آليات االنتباه ‪ ،attention mechanisms‬تخيل أننا نقوم بتغذية سلسلة من الرموزيف ‬
‫تجميع االنتباه بحيث تعمل نفس المجموعة من الرموز كاستعالمات ومفاتيح وقيم‪ .‬على وجه‬
‫التحديد‪ ،‬يحضر كل استعالم جميع أزواج المفتاح‪-‬القيمة ويولد ناتج انتباه واحد‪ .‬نظرًا ألن‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪314‬‬

‫االستعالمات والمفاتيح والقيم تأتي من نفس المكان‪ ،‬فإن هذا يؤدي إلى االنتباه الذاتي ‪self-‬‬
‫‪ ،)2017 ،Vaswani et al. ،2017 ،Lin et al.( attention‬والذي يُسمى أيضًا االنتباه‬
‫الداخلي ‪Paulus et ،2016 ،Parikh et al. ،2016 ،Cheng et al.( intra-attention‬‬
‫‪.)2017 ،al.‬يف هذا القسم‪ ،‬سنناقش ترميز التسلسل باستخدام االنتباه الذاتي‪ ،‬بمايف ذلك‬
‫استخدام معلومات إضافية لترتيب التسلسل‪.‬‬

‫‪import numpy as np‬‬


‫‪import tensorflow as tf‬‬
‫‪from d2l import tensorflow as d2l‬‬
‫‪Self-Attention‬‬ ‫‪11.6.1‬‬
‫بالنظر إلى تسلسل من رموز اإلدخال 𝑛𝐱 ‪ 𝐱1 , … ,‬حيث أي (𝑛 ≤ 𝑖 ≤ ‪ ، 𝐱𝑖 ∈ ℝ )1‬فإن‬
‫𝑑‬

‫االنتباه الذاتي الخاص به ينتج تسلسلًا بنفس الطول 𝑛𝐲 ‪ ، 𝐲1 , … ,‬حيث‬

‫𝑑‪𝐲𝑖 = 𝑓(𝐱𝑖 , (𝐱1 , 𝐱1 ), … , (𝐱𝑛 , 𝐱𝑛 )) ∈ ℝ‬‬

‫حسب تعريف تجميع االنتباه 𝑓يف (‪ .)11.3.1‬باستخدام االنتباه متعدد الرؤوس ‪multi-head‬‬
‫‪ ،attention‬يحسب مقتطف الكود التالي االنتباه الذاتي لموتّر ذي شكل (حجم الدُفعة‪ ،‬عدد‬
‫الخطوات الزمنية أو طول التسلسل بالرموز‪ .) 𝑑 ،‬موتر اإلخراج له نفس الشكل‪.‬‬

‫‪num_hiddens, num_heads = 100, 5‬‬


‫‪attention = d2l.MultiHeadAttention(num_hiddens,‬‬
‫‪num_hiddens, num_hiddens,‬‬
‫‪num_hiddens,‬‬
‫)‪num_heads, 0.5‬‬

‫‪batch_size, num_queries, valid_lens = 2, 4,‬‬


‫)]‪tf.constant([3, 2‬‬
‫))‪X = tf.ones((batch_size, num_queries, num_hiddens‬‬
‫‪d2l.check_shape(attention(X, X, X, valid_lens,‬‬
‫‪training=False),‬‬
‫))‪(batch_size, num_queries, num_hiddens‬‬
‫‪Comparing CNNs,‬‬ ‫‪RNNs CNNs‬‬ ‫‪11.6.2‬‬
‫‪RNNs, and Self-Attention‬‬
‫دعونا نقارن معماريات لتعيين تسلسل من الرموز إلى تسلسل آخر متساوي الطول‪ ،‬حيث يتم‬
‫تمثيل كل رمز إدخال أو إخراج بواسطة متجه ذي أبعاد‪ .‬على وجه التحديد‪ ،‬سننظريف شبكات‬
‫‪ CNN‬و‪ RNNs‬واالنتباه الذاتي‪ .‬سنقارن التعقيد الحسابي والعمليات المتسلسلة وأطوال‬
‫المسار القصوى‪ .‬الحظ أن العمليات المتسلسلة تمنع الحساب المتوازي‪،‬يف حين أن المسار‬
‫‪315‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫األقصر بين أي مجموعة من مواضع التسلسل يجعل من السهل تعلم التبعيات بعيدة المدى ضمن‬
‫التسلسل (‪.)2001 ،Hochreiter et al.‬‬

‫الشكل ‪ 11.6.1‬مقارنة ‪( CNN‬تم حذف الرموز للحشو) و‪ RNN‬ومعماريات االنتباه‬


‫الذاتي‪.‬‬

‫ضعيف اعتبارك طبقة تالفيفية حجم نواتها 𝑘‪ .‬سنقدم مزيدًا من التفاصيل حول معالجة التسلسل‬
‫باستخدام شبكات ‪CNN‬يف فصول الحقة‪.‬يف الوقت الحالي‪ ،‬نحتاج فقط إلى معرفة أنه نظرًا ألن‬
‫طول التسلسل هو 𝑛 ‪ ،‬فإن عدد قنوات اإلدخال واإلخراج كالهما 𝑑 ‪ ،‬فإن التعقيد الحسابي‬
‫للطبقة التالفيفية هو 𝑑‪ .‬وكما يوضح الشكل ‪ ،11.6.1‬فإن شبكات ‪ CNN‬مرتبة بشكل هرمي‪،‬‬
‫لذا توجد هناك )‪ 𝒪(1‬عمليات تسلسلية ويكون أقصى طول للمسير هو )𝑘‪ .𝒪(𝑛/‬على سبيل‬
‫المثال‪ ،‬وضمن المجال المؤثر لشبكة ‪ CNN‬ذات طبقتين بحجم نواة ‪3‬يف الشكل ‪.11.6.1‬‬

‫عند تحديث الحالة المخفية لـ ‪ ،RNNs‬فإن ضرب مصفوفة الوزن 𝑑 × 𝑑 والحالة المخفية‬
‫ذات األبعاد 𝑑 لها تعقيد حسابي قدره ) ‪ .𝒪(𝑑 2‬نظرًا ألن طول التسلسل هو 𝑛 ‪ ،‬فإن التعقيد‬
‫الحسابي للطبقة المتكررة هو ) ‪ .𝒪(𝑛𝑑2‬وفقاً للشكل ‪ ،11.6.1‬توجد )𝑛(𝒪 عمليات متسلسلة‬
‫ال يمكن موازنتها ويكون طول المسير األقصى كذلك )𝑛(𝒪‪.‬‬

‫في االنتباه الذاتي‪ ،‬تكون االستعالمات والمفاتيح والقيم كلها مصفوفات 𝑑 × 𝑛‪ .‬ضعيف اعتبارك‬
‫انتباه الضرب النقطي المقاسيف (‪ ،)11.3.5‬حيث يتم ضرب المصفوفة 𝑑 × 𝑛 بمصفوفة‬
‫𝑛 × 𝑑 ‪ ،‬ثم يتم ضرب المصفوفة الناتجة 𝑛 × 𝑛يف مصفوفة 𝑑 × 𝑛‪ .‬نتيجة لذلك‪ ،‬االنتباه الذاتي‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪316‬‬

‫له تعقيد حسابي )𝑑 ‪ .𝒪(𝑛2‬كما نرىيف الشكل ‪ ،11.6.1‬يرتبط كل رمز بشكل مباشر بأي رمز‬
‫آخر من خالل االنتباه الذاتي‪ .‬لذلك‪ ،‬يمكن أن يكون الحساب موازيًا للعمليات المتسلسلة )‪𝒪(1‬‬
‫ويكون الحد األقصى لطول المسار وكذلك )‪.𝒪(1‬‬

‫الكليف الكل‪ ،‬تتمتع كل من شبكات ‪ CNN‬واالنتباه الذاتي بحساب موازٍ واالنتباه الذاتي بأقصر‬
‫طول للمسار‪ .‬ومع ذلك‪ ،‬فإن التعقيد الحسابي التربيعي فيما يتعلق بطول التسلسل يجعل االنتباه‬
‫الذاتي بطيئًا للغاية للتسلسالت الطويلة جدًا‪.‬‬

‫‪Positional Encoding‬‬ ‫‪11.6.3‬‬


‫على عكس ‪ RNNs‬التي تعالج بشكل متكرر الرموز للتسلسل واحدًا تلو اآلخر‪ ،‬يتخلى االنتباه‬
‫الذاتي عن العمليات المتسلسلة لصالح الحساب المتوازي‪ .‬الستخدام معلومات ترتيب التسلسل‪،‬‬
‫يمكننا حقن معلومات موضعية مطلقة أو نسبية عن طريق إضافة ترميز موضعي ‪positional‬‬
‫‪ encoding‬إلى تمثيالت اإلدخال‪ .‬يمكن تعلم الترميزات الموضعية أو إصالحها‪ .‬فيما يلي‪،‬‬
‫نصف ترميزًا موضعيًا ثابتًا استنادًا إلى دوال الجيب وجيب التمام (‪.)2017 ،Vaswani et al.‬‬

‫افترض أن تمثيل اإلدخال 𝑑×𝑛‪ 𝐗 ∈ ℝ‬يحتوي على ذات األبعاد المضمنة 𝑑 لرموز 𝑛 التسلسل‪.‬‬
‫إخراج الترميز الموضعي 𝐏 ‪ 𝐗 +‬باستخدام مصفوفة تضمين موضعية 𝑑×𝑛‪ 𝐏 ∈ ℝ‬من نفس‬
‫الشكل‪ ،‬يكون العنصر الموجوديف الصف ‪ 𝑖 th‬والعمود ‪ (2𝑗)th‬أو العمود ‪ (2𝑗 + 1)th‬هو‬
‫𝑖‬
‫𝑗‪𝑝𝑖,2‬‬ ‫( ‪= sin‬‬ ‫‪),‬‬
‫𝑑‪100002𝑗/‬‬
‫𝑖‬
‫(‪)11.6.2‬‬
‫‪𝑝𝑖,2𝑗+1‬‬ ‫‪= cos‬‬ ‫‪(100002𝑗/𝑑 ).‬‬

‫للوهلة األولى‪ ،‬يبدو تصميم الدالة المثلثية هذا غريبًا‪ .‬قبل شرح هذا التصميم‪ ،‬دعنا نطبقه أوالًيف ‬
‫فئة ‪ PositionalEncoding‬التالية‪.‬‬

‫‪#@save‬‬
‫‪class PositionalEncoding(tf.keras.layers.Layer):‬‬
‫"""‪"""Positional encoding.‬‬
‫‪def __init__(self, num_hiddens, dropout,‬‬
‫‪max_len=1000):‬‬
‫)(__‪super().__init‬‬
‫)‪self.dropout = tf.keras.layers.Dropout(dropout‬‬
‫‪# Create a long enough P‬‬
‫))‪self.P = np.zeros((1, max_len, num_hiddens‬‬
‫‪X = np.arange(max_len,‬‬
‫(‪dtype=np.float32).reshape‬‬
‫(‪-1,1)/np.power(10000, np.arange‬‬
317 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

0, num_hiddens, 2, dtype=np.float32) /
num_hiddens)
self.P[:, :, 0::2] = np.sin(X)
self.P[:, :, 1::2] = np.cos(X)

def call(self, X, **kwargs):


X = X + self.P[:, :X.shape[1], :]
return self.dropout(X, **kwargs)
‫ تتوافق الصفوف مع المواضع داخل تسلسل وتمثل األعمدة‬، 𝐏 ‫في مصفوفة التضمين الموضعي‬
‫ لمصفوفة‬7th ‫ و‬6th ‫ يمكننا أن نرى أن االعمدة‬،‫يف المثال أدناه‬.‫أبعاد ترميز موضعية مختلفة‬
6th ‫ يرجع سبب اإلزاحة بين‬.9th ‫ و‬8th ‫التضمين الموضعية وأعمدة لها تردد أعلى من األعمدة‬
.‫ ) إلى تبديل داالت الجيب وجيب التمام‬9th ‫ و‬8th ‫ (نفس األعمدة‬7th ‫و‬

encoding_dim, num_steps = 32, 60


pos_encoding = PositionalEncoding(encoding_dim, 0)
X = pos_encoding(tf.zeros((1, num_steps, encoding_dim)),
training=False)
P = pos_encoding.P[:, :X.shape[1], :]
d2l.plot(np.arange(num_steps), P[0, :, 6:10].T,
xlabel='Row (position)',
figsize=(6, 2.5), legend=["Col %d" % d for d in
np.arange(6, 10)])

Absolute Positional Information 11.6.3.1


‫لمعرفة كيف يرتبط التردد المنخفض بشكل رتيب على طول بُعد التشفير بالمعلومات الموضعية‬
.0,1, … ,7 ‫ دعنا نطبع التمثيالت الثنائية لـ‬،absolute positional information ‫المطلقة‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪318‬‬

‫كما نرى‪ ،‬فإن أقل بت‪ ،‬وثاني أدنى بت‪ ،‬وثالث أدنى بت‪ ،‬تتناوب على كل رقم‪ ،‬وكل رقمين‪،‬‬
‫وكل أربعة أرقام‪ ،‬على التوالي‪.‬‬

‫‪for i in range(8):‬‬
‫)'}‪print(f'{i} in binary is {i:>03b‬‬
‫‪0 in binary is 000‬‬
‫‪1 in binary is 001‬‬
‫‪2 in binary is 010‬‬
‫‪3 in binary is 011‬‬
‫‪4 in binary is 100‬‬
‫‪5 in binary is 101‬‬
‫‪6 in binary is 110‬‬
‫‪7 in binary is 111‬‬
‫في التمثيالت الثنائية‪ ،‬يكون للبت األعلى تردد أقل من البت األقل‪ .‬وبالمثل‪ ،‬كما هو موضحيف ‬
‫خريطة الحرارة أدناه‪ ،‬يقلل الترميز الموضعي الترددات على طول بُعد الترميز باستخدام الدوال‬
‫المثلثية‪ .‬نظرًا ألن المخرجات عبارة عن أرقام عائمة‪ ،‬فإن مثل هذه التمثيالت المستمرة تكون‬
‫أكثر كفاءةيف استخدام المساحة من التمثيالت الثنائية‪.‬‬

‫‪P = tf.expand_dims(tf.expand_dims(P[0, :, :], axis=0),‬‬


‫)‪axis=0‬‬
‫‪d2l.show_heatmaps(P, xlabel='Column (encoding‬‬
‫‪dimension)',‬‬
‫‪ylabel='Row (position)', figsize=(3.5,‬‬
‫)'‪4), cmap='Blues‬‬
‫‪319‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪Relative Positional Information‬‬ ‫‪11.6.3.2‬‬


‫إلى جانب التقاط المعلومات الموضعية المطلقة‪ ،‬يتيح الترميز الموضعي أعاله أيضًا للنموذج أن‬
‫يتعلم بسهولة الحضور من خالل المواضع النسبية ‪ .relative positions‬هذا ألنه بالنسبة ألي‬
‫إزاحة موضع ثابت‪ ،‬يمكن تمثيل الترميز الموضعييف الموضع بإسقاط خطي ‪linear‬‬
‫‪ projection‬لذلك الموضع‪.‬‬

‫يمكن تفسير هذا اإلسقاط رياضيًا‪ .‬للداللة 𝑑‪، 𝜔𝑗 = 1/100002𝑗/‬أي زوج من‬
‫) ‪(𝑝𝑖,2𝑗 , 𝑝𝑖,2𝑗+1‬يف (‪ )11.6.2‬يمكن إسقاطه خطيًا الى يمكن إسقاط ألي إزاحة ثابتة 𝛿‪:‬‬

‫𝑗‪cos (𝛿𝜔𝑗 ) sin (𝛿𝜔𝑗 ) 𝑝𝑖,2‬‬


‫[‬ ‫[]‬ ‫]‬
‫‪−sin (𝛿𝜔𝑗 ) cos (𝛿𝜔𝑗 ) 𝑝𝑖,2𝑗+1‬‬
‫) 𝑗𝜔𝑖( ‪cos (𝛿𝜔𝑗 )sin (𝑖𝜔𝑗 ) + sin (𝛿𝜔𝑗 )cos‬‬
‫=‬ ‫[‬ ‫]‬
‫) 𝑗𝜔𝑖( ‪−sin (𝛿𝜔𝑗 )sin (𝑖𝜔𝑗 ) + cos (𝛿𝜔𝑗 )cos‬‬
‫(‪)11.6.3‬‬
‫) 𝑗𝜔)𝛿 ‪sin ((𝑖 +‬‬
‫=‬ ‫[‬ ‫]‬
‫) 𝑗𝜔)𝛿 ‪cos ((𝑖 +‬‬
‫𝑗‪𝑝𝑖+𝛿,2‬‬
‫=‬ ‫𝑝[‬ ‫‪],‬‬
‫‪𝑖+𝛿,2𝑗+1‬‬

‫حيث ال تعتمد مصفوفة اإلسقاط ‪ 2 × 2‬على أي مؤشر موضع 𝑖‪.‬‬

‫‪11.6.4‬‬
‫في االنتباه الذاتي ‪ ،self-attention‬تأتي االستعالمات والمفاتيح والقيم من نفس‬ ‫•‬
‫المكان‪.‬‬
‫تتمتع كل من شبكات ‪ CNN‬واالنتباه الذاتي بحسابات موازية ويكون االنتباه الذاتي‬ ‫•‬
‫بأقصر طول للمسار‪ .‬ومع ذلك‪ ،‬فإن التعقيد الحسابي التربيعي فيما يتعلق بطول‬
‫التسلسل يجعل االنتباه الذاتي بطيئًا للغاية للتسلسالت الطويلة جدًا‪.‬‬
‫الستخدام معلومات ترتيب التسلسل‪ ،‬يمكننا حقن معلومات موضعية مطلقة أو نسبية‬ ‫•‬
‫عن طريق إضافة ترميز موضعي ‪ positional encoding‬إلى تمثيالت اإلدخال‪.‬‬

‫‪11.6.5‬‬
‫‪ .1‬افترض أننا نصمم بُنية عميقة لتمثيل تسلسل من خالل تكديس طبقات االنتباه الذاتي‬
‫مع الترميز الموضعي‪ .‬ماذا يمكن أن تكون المشاكل؟‬
‫‪ .2‬هل يمكنك تصميم طريقة ترميز موضعي قابلة للتعلم؟‬
‫‪ .3‬هل يمكننا تخصيص تضمينات متعلمة ‪ learned embeddings‬مختلفة وفقًا‬
‫الزاحات مختلفة بين االستعالمات والمفاتيح التي تتم مقارنتهايف االنتباه الذاتي؟‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪320‬‬

‫تلميح‪ :‬يمكنك الرجوع إلى التضمينات ذات الموضع النسبي (‪،Huang et al.‬‬
‫‪.)2018 ،Shaw et al. ،2018‬‬

‫‪The Transformer Architecture‬‬ ‫‪11.7‬‬


‫لقد قارنا شبكات ‪ CNN‬و‪ RNN‬واالنتباه الذاتييف القسم ‪ .11.6.2‬والجدير بالذكر أن االنتباه‬
‫الذاتي يتمتع بكل من الحساب المتوازي وأقصر طول أقصى للمسار‪ .‬لذلك‪ ،‬بطبيعة الحال‪ ،‬من‬
‫الجذاب تصميم معماريات عميقة باستخدام االنتباه الذاتي‪ .‬على عكس نماذج االنتباه الذاتي‬
‫السابقة التي ال تزال تعتمد على ‪ RNNs‬لتمثيل المدخالت (‪Lin et ،2016 ،Cheng et al.‬‬
‫‪ ،)2017 ،Paulus et al. ،2017 ،al.‬يعتمد نموذج المحوالت ‪ transformer model‬فقط‬
‫على آليات االنتباه دون أي تالفيف أو طبقة متكررة (‪ .)2017 ،Vaswani et al‬على الرغم من‬
‫اقتراحهايف األصل لتعلم التسلسل لتسلسل ‪ sequence to sequence learning‬على البيانات‬
‫النصية‪ ،‬إال أن المحوالت كانت منتشرةيف مجموعة واسعة من تطبيقات التعلم العميق الحديثة‪،‬‬
‫مثل مجاالت اللغة والرؤية والكالم والتعلم المعزز‪.‬‬

‫الشكل ‪ 11.7.1‬معمارية المحوالت‪.‬‬


‫‪321‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪Model‬‬ ‫‪11.7.1‬‬
‫كمثال على معمارية المشفر‪-‬مفكك الشفرة ‪ ،encoder-decoder architecture‬يعرض‬
‫الشكل ‪ 11.7.1‬المعمارية الكلية للمحول‪ .‬كما نرى‪ ،‬يتكون المحول من مشفر ومفكك شفرة‪.‬‬
‫يختلف عن انتباه ‪ Bahdanau‬لتعلم التسلسل إلى التسلسليف الشكل ‪ ،11.4.1‬تتم إضافة إدخال‬
‫(المصدر) واإلخراج (الهدف) المتسلسل مع الترميز الموضعي قبل إدخالهيف المشفر ومفكك‬
‫الشفرة الذي يكدس الوحدات بناءً على االنتباه الذاتي‪.‬‬

‫نقدم اآلن نظرة عامة على بُنية المحوالتيف الشكل ‪ .11.7.1‬على مستوى عالٍ‪ ،‬يكون مشفر‬
‫المحول ‪ transformer encoder‬عبارة عن كومة من طبقات متعددة متطابقة‪ ،‬حيث تحتوي‬
‫كل طبقة على طبقتين فرعيتين (يُشار إليهما على أنهما طبقة فرعية ‪ .)sublayer‬األول هو‬
‫تجميع االنتباه الذاتي متعدد الرؤوس والثاني عبارة عن شبكة تغذية لألماميف موضعها‪ .‬على وجه‬
‫التحديد‪،‬يف االنتباه الذاتي للمشفر‪ ،‬تكون االستعالمات والمفاتيح والقيم كلها من مخرجات طبقة‬
‫التشفير السابقة‪ .‬مستوحى من تصميم ‪ResNet‬يف القسم ‪ ،8.6‬يتم استخدام اتصال متبقي حول‬
‫كلتا الطبقتين الفرعيتين‪.‬يف المحول‪ ،‬ألي إدخال 𝑑‪𝐱 ∈ ℝ‬يف أي موضعيف التسلسل‪ ،‬نطلب‬
‫𝑑‪ sublayer(𝐱) ∈ ℝ‬حتى يكون االتصال المتبقي 𝑑‪ 𝐱 + sublayer(𝐱) ∈ ℝ‬ممكنًا‪ .‬هذه‬
‫اإلضافة من االتصال المتبقي يتبعها مباشرة تسوية الطبقة (‪ .)2016 ،Ba et al.‬نتيجة لذلك‪،‬‬
‫يقوم مشفر المحول بإخراج تمثيل متجه ذات األبعاد 𝑑 لكل موضعيف تسلسل اإلدخال‪.‬‬

‫مفكك شفرة المحوالت ‪ transformer decoder‬هي أيضًا كومة من طبقات متطابقة متعددة‬
‫مع توصيالت متبقية وتسوية طبقة‪ .‬إلى جانب الطبقتين الفرعيتين الموصوفتينيف المشفر‪ ،‬تُدرج‬
‫وحدة مفكك الشفرة طبقة فرعية ثالثة‪ ،‬تُعرف باسم انتباه مشفر‪-‬مفكك الشفرة ‪encoder-‬‬
‫‪ ،decoder attention‬بين هاتين الطبقتين‪.‬يف انتباه مشفر‪-‬مفكك الشفرة‪ ،‬تكون االستعالمات‬
‫من مخرجات طبقة وحدة مفكك الشفرة السابقة‪ ،‬والمفاتيح والقيم من مخرجات مشفر المحول‪.‬‬
‫في وحدة مفكك الشفرة‪ ،‬يكون االنتباه الذاتي واالستعالمات والمفاتيح والقيم كلها من مخرجات‬
‫طبقة مفكك الشفرة السابقة‪ .‬ومع ذلك‪ ،‬يُسمح لكل موضعيف مفكك الشفرة بالحضور فقط إلى‬
‫جميع المواضعيف مفكك الشفرة حتى ذلك الموضع‪ .‬يحافظ هذا االنتباه المقنع ‪masked‬‬
‫‪ attention‬على خاصية االنحدار التلقائي‪ ،‬مما يضمن أن التنبؤ يعتمد فقط على رموز اإلخراج‬
‫التي تم إنشاؤها‪.‬‬

‫لقد وصفنا بالفعل ونفذنا االنتباه متعدد الرؤوس استنادًا إلى عمليات ضرب نقطية مقاسة‬
‫‪scaled dot-products‬يف القسم ‪ 11.5‬والترميز الموضعييف القسم ‪ .11.6.3‬فيما يلي سنقوم‬
‫بتنفيذ باقي نموذج المحوالت‪.‬‬

‫‪import numpy as np‬‬


‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪322‬‬

‫‪import pandas as pd‬‬


‫‪import tensorflow as tf‬‬
‫‪from d2l import tensorflow as d2l‬‬
‫‪Positionwise Feed-‬‬ ‫‪11.7.2‬‬
‫‪Forward Networks‬‬
‫تعمل شبكة التغذية األمامية الموضعية ‪ positionwise feed-forward network‬على‬
‫تحويل التمثيليف جميع مواضع التسلسل باستخدام نفس ‪ .MLP‬هذا هو السببيف أننا نطلق عليه‬
‫اسم الموضع ‪.positionwise‬يف التنفيذ أدناه‪ ،‬سيتم تحويل اإلدخال ‪ X‬مع الشكل (حجم الدُفعة‪،‬‬
‫عدد الخطوات الزمنية أو طول التسلسل بالرموز‪ ،‬عدد الوحدات المخفية أو بُعد الميزة) بواسطة‬
‫‪ MLP‬ثنائي الطبقات إلى شكل موتر إخراج (حجم الدُفعة‪ ،‬عدد الخطوات الزمنية‪،‬‬
‫‪.)ffn_num_outputs‬‬

‫‪#@save‬‬
‫‪class PositionWiseFFN(tf.keras.layers.Layer):‬‬
‫"""‪"""Positionwise feed-forward network.‬‬
‫‪def __init__(self, ffn_num_hiddens,‬‬
‫‪ffn_num_outputs):‬‬
‫)(__‪super().__init‬‬
‫= ‪self.dense1‬‬
‫)‪tf.keras.layers.Dense(ffn_num_hiddens‬‬
‫)(‪self.relu = tf.keras.layers.ReLU‬‬
‫= ‪self.dense2‬‬
‫)‪tf.keras.layers.Dense(ffn_num_outputs‬‬

‫‪def call(self, X):‬‬


‫)))‪return self.dense2(self.relu(self.dense1(X‬‬
‫يوضح المثال التالي أن البعد األعمق للموتر يتغير إلى عدد المخرجاتيف شبكة التغذية األمامية‬
‫الموضعية‪ .‬نظرًا ألن نفس ‪ MLP‬يتحوليف جميع المواضع‪ ،‬عندما تكون المدخالتيف جميع‬
‫هذه المواضع هي نفسها‪ ،‬فإن مخرجاتها متطابقة أيضًا‪.‬‬

‫)‪ffn = PositionWiseFFN(4, 8‬‬


‫]‪ffn(tf.ones((2, 3, 4)))[0‬‬
‫=‪<tf.Tensor: shape=(3, 8), dtype=float32, numpy‬‬
‫‪array([[ 0.31384668, 0.01483253, -0.38529113,‬‬
‫‪0.22501771, -0.0185459 ,‬‬
‫‪-0.15193778, -0.65797377, -0.7980111 ],‬‬
‫‪[ 0.31384668, 0.01483253, -0.38529113,‬‬
‫‪0.22501771, -0.0185459 ,‬‬
‫‪-0.15193778, -0.65797377, -0.7980111 ],‬‬
‫‪323‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪[ 0.31384668, 0.01483253, -0.38529113,‬‬


‫‪0.22501771, -0.0185459 ,‬‬
‫‪-0.15193778, -0.65797377, -0.7980111 ]],‬‬
‫>)‪dtype=float32‬‬
‫‪Residual Connection and‬‬ ‫‪11.7.3‬‬
‫‪Layer Normalization‬‬
‫دعنا اآلن نركز على مكون "اإلضافة والمعيار ‪" add & norm‬يف الشكل ‪ .11.7.1‬كما وصفنايف ‬
‫بداية هذا القسم‪ ،‬هذا اتصال متبقي ‪ residual connection‬يتبعه مباشرة تسوية طبقة ‪layer‬‬
‫‪ .normalization‬كالهما مفتاح للبنى العميقة الفعالة‪.‬‬

‫في القسم ‪ ،8.5‬أوضحنا كيف أحدث تسوية الدُفعات وإعادة المقاييس عبر األمثلة داخل‬
‫‪ .minibatch‬كما تمت مناقشتهيف القسم ‪ ،8.5.2.3‬فإن تسوية الطبقة هي نفسها تسوية الدُفعات‬
‫باستثناء أن األول يتم تسويته عبر بُعد الميزة‪ ،‬وبالتالي االستمتاع بفوائد استقاللية المقياس‬
‫واستقاللية حجم الدُفعة‪ .‬على الرغم من تطبيقاته المنتشرةيف الرؤية الحاسوبية‪ ،‬فإن تسوية‬
‫الدفعات عادة ما يكون أقل فعالية من الناحية التجريبية من تسوية الطبقةيف مهام معالجة اللغة‬
‫الطبيعية‪ ،‬والتي غالبًا ما تكون مدخالتها متواليات متغيرة الطول‪.‬‬

‫يقارن مقتطف الشفرة التالي التسوية عبر أبعاد مختلفة حسب تسوية الطبقة وتسوية الدُفعات‪.‬‬

‫)(‪ln = tf.keras.layers.LayerNormalization‬‬
‫)(‪bn = tf.keras.layers.BatchNormalization‬‬
‫)‪X = tf.constant([[1, 2], [2, 3]], dtype=tf.float32‬‬
‫))‪print('layer norm:', ln(X), '\nbatch norm:', bn(X‬‬
‫(‪layer norm: tf.Tensor‬‬
‫‪[[-0.998006‬‬ ‫]‪0.9980061‬‬
‫)‪[-0.9980061 0.998006 ]], shape=(2, 2), dtype=float32‬‬
‫(‪batch norm: tf.Tensor‬‬
‫] ‪[[0.99950033 1.9990007‬‬
‫)‪[1.9990007 2.998501 ]], shape=(2, 2), dtype=float32‬‬
‫اآلن يمكننا تنفيذ فئة ‪ AddNorm‬باستخدام اتصال متبقي متبوعًا بتسوية الطبقة‪ .‬يتم تطبيق‬
‫التسرب ‪ Dropout‬أيضًا للتنظيم ‪.regularization‬‬

‫‪#@save‬‬
‫‪class AddNorm(tf.keras.layers.Layer):‬‬
‫‪"""Residual connection followed by layer‬‬
‫"""‪normalization.‬‬
‫‪def __init__(self, norm_shape, dropout):‬‬
‫)(__‪super().__init‬‬
‫)‪self.dropout = tf.keras.layers.Dropout(dropout‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 324

self.ln =
tf.keras.layers.LayerNormalization(norm_shape)

def call(self, X, Y, **kwargs):


return self.ln(self.dropout(Y, **kwargs) + X)
‫يتطلب االتصال المتبقي أن يكون المدخالن من نفس الشكل بحيث يكون لموتّر اإلخراج أيضًا‬
.‫نفس الشكل بعد عملية اإلضافة‬

# Normalized_shape is: [i for i in


range(len(input.shape))][1:]
add_norm = AddNorm([1, 2], 0.5)
d2l.check_shape(add_norm(tf.ones((2, 3, 4)), tf.ones((2,
3, 4)),
training=False), (2, 3, 4))
Encoder 11.7.4
.‫ فلنبدأ بتنفيذ طبقة واحدة داخل المشفر‬،‫مع جميع المكونات األساسية لتجميع مشفر المحوالت‬
‫ االنتباه الذاتي‬:‫ التالية على طبقتين فرعيتين‬TransformerEncoderBlock ‫تحتوي فئة‬
‫ حيث يتم استخدام اتصال متبقي متبوعًا‬، ‫متعدد الرؤوس وشبكات التغذية األمامية الموضعية‬
.‫بتسوية الطبقة حول كلتا الطبقتين الفرعيتين‬

#@save
class TransformerEncoderBlock(tf.keras.layers.Layer):
"""Transformer encoder block."""
def __init__(self, key_size, query_size, value_size,
num_hiddens,
norm_shape, ffn_num_hiddens, num_heads,
dropout, bias=False):
super().__init__()
self.attention = d2l.MultiHeadAttention(
key_size, query_size, value_size,
num_hiddens, num_heads, dropout,
bias)
self.addnorm1 = AddNorm(norm_shape, dropout)
self.ffn = PositionWiseFFN(ffn_num_hiddens,
num_hiddens)
self.addnorm2 = AddNorm(norm_shape, dropout)

def call(self, X, valid_lens, **kwargs):


Y = self.addnorm1(X, self.attention(X, X, X,
valid_lens, **kwargs),
325 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

**kwargs)
return self.addnorm2(Y, self.ffn(Y), **kwargs)
.‫ أي طبقةيف مشفر المحول ال تغير شكل المدخالت الخاصة بها‬،‫كما نرى‬

X = tf.ones((2, 100, 24))


valid_lens = tf.constant([3, 2])
norm_shape = [i for i in range(len(X.shape))][1:]
encoder_blk = TransformerEncoderBlock(24, 24, 24, 24,
norm_shape, 48, 8, 0.5)
d2l.check_shape(encoder_blk(X, valid_lens,
training=False), X.shape)
‫ نقوم بتكديس عدد من مثيالت فئات‬،‫في تنفيذ مشفر المحوالت التالي‬
‫ نظرًا ألننا نستخدم الترميز الموضعي‬.‫ المذكورة أعاله‬TransformerEncoderBlock
‫ فإننا نضرب قيم تضمين المدخالت القابلة للتعلم‬،1 ‫ و‬-1 ‫الثابت الذي تكون قيمه دائمًا بين‬
‫بواسطة الجذر التربيعي لبعد التضمين إلعادة القياس قبل تلخيص تضمين اإلدخال والترميز‬
.‫الموضعي‬

#@save
class TransformerEncoder(d2l.Encoder):
"""Transformer encoder."""
def __init__(self, vocab_size, key_size, query_size,
value_size,
num_hiddens, norm_shape,
ffn_num_hiddens, num_heads,
num_blks, dropout, bias=False):
super().__init__()
self.num_hiddens = num_hiddens
self.embedding =
tf.keras.layers.Embedding(vocab_size, num_hiddens)
self.pos_encoding =
d2l.PositionalEncoding(num_hiddens, dropout)
self.blks = [TransformerEncoderBlock(
key_size, query_size, value_size,
num_hiddens, norm_shape,
ffn_num_hiddens, num_heads, dropout, bias)
for _ in range(
num_blks)]

def call(self, X, valid_lens, **kwargs):


# Since positional encoding values are between -
1 and 1, the embedding
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪326‬‬

‫‪# values are multiplied by the square root of‬‬


‫‪the embedding dimension‬‬
‫‪# to rescale before they are summed up‬‬
‫* )‪X = self.pos_encoding(self.embedding(X‬‬
‫(‪tf.math.sqrt‬‬
‫‪tf.cast(self.num_hiddens,‬‬
‫)‪dtype=tf.float32)), **kwargs‬‬
‫)‪self.attention_weights = [None] * len(self.blks‬‬
‫‪for i, blk in enumerate(self.blks):‬‬
‫)‪X = blk(X, valid_lens, **kwargs‬‬
‫[‪self.attention_weights‬‬
‫= ]‪i‬‬
‫‪blk.attention.attention.attention_weights‬‬
‫‪return X‬‬
‫أدناه نحدد معلمات فائقة إلنشاء مشفر المحول من طبقتين‪ .‬شكل إخراج مشفر المحول هو‬
‫(حجم الدُفعة‪ ،‬عدد الخطوات الزمنية‪.)num_hiddens ،‬‬

‫‪Decoder‬‬ ‫‪11.7.5‬‬
‫كما هو مبينيف الشكل ‪ ،11.7.1‬يتكون مفكك شفرة المحول من عدة طبقات متطابقة‪ .‬يتم تنفيذ‬
‫كل طبقةيف فئة ‪ TransformerDecoderBlock‬التالية ‪ ،‬والتي تحتوي على ثالث طبقات‬
‫فرعية‪ :‬االنتباه الذاتي لمفكك الشفرة ‪ ،‬وانتباه المشفر‪-‬مفكك الشفرة ‪ ،‬وشبكات التغذية األمامية‬
‫الموضعية‪ .‬تستخدم هذه الطبقات الفرعية اتصالًا متبقيًا حولها متبوعًا بتطبيع الطبقة‪.‬‬

‫كما وصفنا سابقًايف هذا القسم‪،‬يف مفكك الشفرة االنتباه الذاتي متعددة الرؤوس المقنعة (الطبقة‬
‫الفرعية األولى)‪ ،‬تأتي االستعالمات والمفاتيح والقيم من مخرجات طبقة مفكك الشفرة السابقة‪.‬‬
‫عند تدريب نماذج التسلسل إلى التسلسل‪ ،‬تعرف الرموزيف جميع المواضع (الخطوات الزمنية)‬
‫لتسلسل اإلخراج‪ .‬ومع ذلك‪ ،‬أثناء التنبؤ‪ ،‬يتم إنشاء تسلسل اإلخراج رمزًا؛ وبالتالي‪،‬يف أي خطوة‬
‫زمنية لمفكك الشفرة‪ ،‬يمكن استخدام الرموز التي تم إنشاؤها فقطيف االنتباه الذاتي لمفكك‬
‫الشفرة‪ .‬للحفاظ على االنحدار التلقائييف مفكك الشفرة‪ ،‬يحدد االنتباه الذاتي المقنع‬
‫‪ dec_valid_lens‬بحيث ال يحضر أي استعالم سوى جميع المواضعيف مفكك الشفرة‬
‫حتى موضع االستعالم‪.‬‬

‫‪class TransformerDecoderBlock(tf.keras.layers.Layer):‬‬
‫‪# The i-th block in the transformer decoder‬‬
‫‪def __init__(self, key_size, query_size, value_size,‬‬
‫‪num_hiddens,‬‬
‫‪norm_shape, ffn_num_hiddens, num_heads,‬‬
‫‪dropout, i):‬‬
327 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

super().__init__()
self.i = i
self.attention1 = d2l.MultiHeadAttention(
key_size, query_size, value_size,
num_hiddens, num_heads, dropout)
self.addnorm1 = AddNorm(norm_shape, dropout)
self.attention2 = d2l.MultiHeadAttention(
key_size, query_size, value_size,
num_hiddens, num_heads, dropout)
self.addnorm2 = AddNorm(norm_shape, dropout)
self.ffn = PositionWiseFFN(ffn_num_hiddens,
num_hiddens)
self.addnorm3 = AddNorm(norm_shape, dropout)

def call(self, X, state, **kwargs):


enc_outputs, enc_valid_lens = state[0], state[1]
# During training, all the tokens of any output
sequence are processed
# at the same time, so state[2][self.i] is None
as initialized. When
# decoding any output sequence token by token
during prediction,
# state[2][self.i] contains representations of
the decoded output at
# the i-th block up to the current time step
if state[2][self.i] is None:
key_values = X
else:
key_values = tf.concat((state[2][self.i],
X), axis=1)
state[2][self.i] = key_values
if kwargs["training"]:
batch_size, num_steps, _ = X.shape
# Shape of dec_valid_lens: (batch_size,
num_steps), where every
# row is [1, 2, ..., num_steps]
dec_valid_lens = tf.repeat(
tf.reshape(tf.range(1, num_steps + 1),
shape=(-1, num_steps)),
repeats=batch_size, axis=0)
else:
dec_valid_lens = None
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 328

# Self-attention
X2 = self.attention1(X, key_values, key_values,
dec_valid_lens,
**kwargs)
Y = self.addnorm1(X, X2, **kwargs)
# Encoder-decoder attention. Shape of
enc_outputs:
# (batch_size, num_steps, num_hiddens)
Y2 = self.attention2(Y, enc_outputs,
enc_outputs, enc_valid_lens,
**kwargs)
Z = self.addnorm2(Y, Y2, **kwargs)
return self.addnorm3(Z, self.ffn(Z), **kwargs),
state
‫مفكك الشفرة لالنتباه واإلضافةيف‬-‫لتسهيل عمليات الضرب النقطي المقاسةيف عمليات المشفر‬
‫) لمفكك الشفرة هو نفس بُعد‬num_hiddens( ‫ يكون بُعد السمة‬،‫التوصيالت المتبقية‬
.‫المشفر‬

decoder_blk = TransformerDecoderBlock(24, 24, 24, 24,


[1, 2], 48, 8, 0.5, 0)
X = tf.ones((2, 100, 24))
state = [encoder_blk(X, valid_lens), valid_lens, [None]]
d2l.check_shape(decoder_blk(X, state,
training=False)[0], X.shape)
‫ مثيالت‬num_blks ‫اآلن نقوم ببناء مفكك شفرة المحوالت بالكامل المكونة من‬
‫ طبقة متصلة بالكامل تحسب التنبؤ لجميع‬،‫يف النهاية‬.TransformerDecoderBlock
‫ يتم تخزين كل من أوزان االنتباه الذاتي لمفكك‬.vocab_size ‫رموز اإلخراج الممكنة بحجم‬
.‫مفكك الشفرة من أجل الرسم الالحق‬-‫الشفرة وأوزان االنتباه الخاصة بالمشفر‬

class TransformerDecoder(d2l.AttentionDecoder):
def __init__(self, vocab_size, key_size, query_size,
value_size,
num_hiddens, norm_shape,
ffn_num_hiddens, num_heads,
num_blks, dropout):
super().__init__()
self.num_hiddens = num_hiddens
self.num_blks = num_blks
self.embedding =
tf.keras.layers.Embedding(vocab_size, num_hiddens)
329 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

self.pos_encoding =
d2l.PositionalEncoding(num_hiddens, dropout)
self.blks = [TransformerDecoderBlock(
key_size, query_size, value_size,
num_hiddens, norm_shape,
ffn_num_hiddens, num_heads, dropout, i)
for i in range(num_blks)]
self.dense = tf.keras.layers.Dense(vocab_size)

def init_state(self, enc_outputs, enc_valid_lens):


return [enc_outputs, enc_valid_lens, [None] *
self.num_blks]

def call(self, X, state, **kwargs):


X = self.pos_encoding(self.embedding(X) *
tf.math.sqrt(
tf.cast(self.num_hiddens,
dtype=tf.float32)), **kwargs)
# 2 attention layers in decoder
self._attention_weights = [[None] *
len(self.blks) for _ in range(2)]
for i, blk in enumerate(self.blks):
X, state = blk(X, state, **kwargs)
# Decoder self-attention weights
self._attention_weights[0][i] = (

blk.attention1.attention.attention_weights)
# Encoder-decoder attention weights
self._attention_weights[1][i] = (

blk.attention2.attention.attention_weights)
return self.dense(X), state

@property
def attention_weights(self):
return self._attention_weights
Training 11.7.6
‫ نحدد هنا أن كالً من مشفر المحول‬.‫مفكك الشفرة باتباع بُ نية المحول‬-‫لنبدأ نموذج المشفر‬
،10.7.6 ‫ على غرار القسم‬.‫ومفكك شفرة المحول لهما طبقتان باستخدام االنتباه رباعي الرؤوس‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 330

‫نقوم بتدريب نموذج المحول على تعلم التسلسل لتسلسل على مجموعة بيانات الترجمة اآللية‬
.‫الفرنسية‬-‫اإلنجليزية‬

data = d2l.MTFraEng(batch_size=128)
num_hiddens, num_blks, dropout = 256, 2, 0.2
ffn_num_hiddens, num_heads = 64, 4
key_size, query_size, value_size = 256, 256, 256
norm_shape = [2]
with d2l.try_gpu():
encoder = TransformerEncoder(
len(data.src_vocab), key_size, query_size,
value_size, num_hiddens,
norm_shape, ffn_num_hiddens, num_heads,
num_blks, dropout)
decoder = TransformerDecoder(
len(data.tgt_vocab), key_size, query_size,
value_size, num_hiddens,
norm_shape, ffn_num_hiddens, num_heads,
num_blks, dropout)
model = d2l.Seq2Seq(encoder, decoder,
tgt_pad=data.tgt_vocab['<pad>'],
lr=0.001)
trainer = d2l.Trainer(max_epochs=50,
gradient_clip_val=1)
trainer.fit(model, data)
331 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

‫ نستخدم نموذج المحول لترجمة بعض الجمل اإلنجليزية إلى الفرنسية وحساب‬،‫بعد التدريب‬
.BLEU ‫نقاطهميف‬

engs = ['go .', 'i lost .', 'he\'s calm .', 'i\'m home
.']
fras = ['va !', 'j\'ai perdu .', 'il est calme .', 'je
suis chez moi .']
preds, _ = model.predict_step(
data.build(engs, fras), d2l.try_gpu(),
data.num_steps)
for en, fr, p in zip(engs, fras, preds):
translation = []
for token in data.tgt_vocab.to_tokens(p):
if token == '<eos>':
break
translation.append(token)
print(f'{en} => {translation}, bleu,'
f'{d2l.bleu(" ".join(translation), fr,
k=2):.3f}')
go . => ['va', '!'], bleu,1.000
i lost . => ["j'ai", 'perdu', '.'], bleu,1.000
he's calm . => ['il', 'est', 'mouillé', 'est',
'mouillé', 'est', 'mouillé', 'mouillé', '.'], bleu,0.343
i'm home . => ['je', 'suis', 'chez', 'moi', 'suis',
'chez', 'moi', 'suis', 'chez'], bleu,0.522
‫ شكل‬.‫دعونا نتخيل أوزان انتباه المحوالت عند ترجمة الجملة اإلنجليزية األخيرة إلى الفرنسية‬
‫ وعدد الخطوات أو‬،‫ وعدد رؤوس االنتباه‬،‫أوزان االنتباه الذاتي للمشفر هو (عدد طبقات المشفر‬
.)‫القيمة‬-‫ وعدد الخطوات أو عدد أزواج المفتاح‬،‫عدد االستعالمات‬

_, dec_attention_weights = model.predict_step(
data.build([engs[-1]], [fras[-1]]), d2l.try_gpu(),
data.num_steps, True)
enc_attention_weights = tf.reshape(
tf.concat(model.encoder.attention_weights, 0),
(num_blks, num_heads, -1, data.num_steps))
d2l.check_shape(enc_attention_weights,
(num_blks, num_heads, data.num_steps,
data.num_steps))
‫ نظرًا‬.‫ تأتي كل من االستعالمات والمفاتيح من تسلسل اإلدخال نفسه‬،‫في االنتباه الذاتي للمشفر‬
‫ فال يوجد استعالم‬،‫ مع تحديد طول صالح لتسلسل اإلدخال‬،‫ألن الرموز للحشو ال تحمل معنى‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪332‬‬

‫يحضر لمواضع الرموز للحشو‪ .‬فيما يلي‪ ،‬يتم تقديم طبقتين من أوزان االنتباه متعددة الرؤوس‬
‫صفًا تلو اآلخر‪ .‬يحضر كل رئيس بشكل مستقل بناءً على فضاءات تمثيل منفصلة من‬
‫االستعالمات والمفاتيح والقيم‪.‬‬

‫(‪d2l.show_heatmaps‬‬
‫‪enc_attention_weights, xlabel='Key positions',‬‬
‫‪ylabel='Query positions',‬‬
‫‪titles=['Head %d' % i for i in range(1, 5)],‬‬
‫))‪figsize=(7, 3.5‬‬

‫لرسم كل من أوزان االنتباه الذاتي مفكك الشفرة وأوزان االنتباه الخاصة بالمشفر‪-‬مفكك الشفرة‪،‬‬
‫نحتاج إلى مزيد من التالعب بالبيانات‪ .‬على سبيل المثال‪ ،‬نمأل أوزان االنتباه المقنعة بصفر‪.‬‬
‫الحظ أن أوزان االنتباه الذاتي لمفكك الشفرة وأوزان االنتباه بالمشفر‪-‬مفكك الشفرة لها نفس‬
‫االستعالمات‪ :‬رمز بداية التسلسل متبوعًا برموز اإلخراج وربما الرموز لنهاية التسلسل‪.‬‬

‫‪dec_attention_weights_2d = [head[0] for step in‬‬


‫‪dec_attention_weights‬‬
‫‪for attn in step‬‬
‫‪for blk in attn for head in‬‬
‫]‪blk‬‬
‫(‪dec_attention_weights_filled = tf.convert_to_tensor‬‬

‫‪np.asarray(pd.DataFrame(dec_attention_weights_2d).fillna‬‬
‫(‬
‫))‪0.0).values).astype(np.float32‬‬
333 ‫ آليات االنتباه والمحوالت‬:‫الفصل الحادي عشر‬

dec_attention_weights =
tf.reshape(dec_attention_weights_filled, shape=(
-1, 2, num_blks, num_heads, data.num_steps))
dec_self_attention_weights, dec_inter_attention_weights
= tf.transpose(
dec_attention_weights, perm=(1, 2, 3, 0, 4))

d2l.check_shape(dec_self_attention_weights,
(num_blks, num_heads, data.num_steps,
data.num_steps))
d2l.check_shape(dec_inter_attention_weights,
(num_blks, num_heads, data.num_steps,
data.num_steps))
‫ ال يوجد استعالم يحضر أزواج‬،‫نظرًا لخاصية االنحدار التلقائي لالنتباه الذاتي لمفكك الشفرة‬
.‫القيمة والمفتاح بعد موضع االستعالم‬

d2l.show_heatmaps(
dec_self_attention_weights[:, :, :, :],
xlabel='Key positions', ylabel='Query positions',
titles=['Head %d' % i for i in range(1, 5)],
figsize=(7, 3.5))

‫ ال يوجد‬،‫ عبر الطول الصحيح المحدد لتسلسل اإلدخال‬،‫على غرار الحالةيف االنتباه الذاتي للمشفر‬
.‫استعالم من تسلسل اإلخراج يحضر تلك الرموز للحشو من تسلسل اإلدخال‬

d2l.show_heatmaps(
dec_inter_attention_weights, xlabel='Key positions',
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪334‬‬

‫‪ylabel='Query positions', titles=['Head %d' % i for‬‬


‫‪i in range(1, 5)],‬‬
‫))‪figsize=(7, 3.5‬‬

‫على الرغم من اقتراح بُنية المحوالتيف األصل للتعلم من التسلسل إلى التسلسل‪ ،‬كما سنكتشف‬
‫الحقًايف الكتاب‪ ،‬غالبًا ما يتم استخدام إما مشفر المحوالت أو مفكك شفرة المحوالت بشكل‬
‫فردييف مهام التعلم العميق المختلفة‪.‬‬

‫‪11.7.7‬‬
‫المحول ‪ transformer‬هو مثال على بُنية المشفر‪-‬مفكك الشفرة ‪encoder-‬‬ ‫•‬
‫‪ ،decoder architecture‬على الرغم من أنه يمكن استخدام المشفر أو مفكك‬
‫الشفرة بشكل فردييف الممارسة العملية‪.‬‬
‫في المحول‪ ،‬يتم استخدام االنتباه الذاتي متعدد الرؤوس لتمثيل تسلسل اإلدخال‬ ‫•‬
‫وتسلسل اإلخراج‪ ،‬على الرغم من أن مفكك الشفرة يجب أن يحافظ على خاصية‬
‫االنحدار التلقائي عبر إصدار مقنع‪.‬‬
‫تعتبر كل من االتصاالت المتبقية وتسوية الطبقةيف المحول مهمة لتدريب نموذج عميق‬ ‫•‬
‫للغاية‪.‬‬
‫تعمل شبكة التغذية األمامية الموضعيةيف نموذج المحوالت على تحويل التمثيليف جميع‬ ‫•‬
‫مواضع التسلسل باستخدام نفس ‪.MLP‬‬
‫‪335‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪11.7.8‬‬
‫‪ .1‬قم بتدريب محول أعمقيف التجارب‪ .‬كيف تؤثر على سرعة التدريب وأداء الترجمة؟‬
‫‪ .2‬هل من الجيد استبدال االنتباه المحسّن للضرب النقطي بانتباه إضافييف المحول؟‬
‫لماذا؟‬
‫‪ .3‬لنمذجة اللغة‪ ،‬هل يجب أن نستخدم مشفر المحول أو مفكك شفرة المحول أو كليهما؟‬
‫كيف تصمم هذه الطريقة؟‬
‫‪ .4‬ما الذي يمكن أن يمثل تحديات للمحوالت إذا كانت تسلسالت اإلدخال طويلة جدًا؟‬
‫لماذا؟‬
‫‪ .5‬كيفية تحسين كفاءة الحوسبة والذاكرة للمحوالت؟ تلميح‪ :‬يمكنك الرجوع إلى مقالة‬
‫االستطالع التي أعدها ‪.)2020 ،Tay et al( .Tay et al‬‬

‫‪Transformers for Vision‬‬ ‫‪11.8‬‬


‫تم اقتراح بنية المحوالتيف البداية لتعلم التسلسل الى تسلسل‪ ،‬مثل الترجمة اآللية‪ .‬مع الفعالية‬
‫العالية‪ ،‬أصبحت المحوالت الحقًا النموذج المفضليف العديد من مهام معالجة اللغة الطبيعية‬
‫(‪Radford ،2018 ،Radford et al. ،2018 ،Devlin et al. ،2020 ،Brown et al.‬‬
‫‪ .)2020 ،Raffel et al. ،2019 ،et al.‬ومع ذلك‪،‬يف مجال الرؤية الحاسوبية‪ ،‬استندت العمارة‬
‫المهيمنة إلى شبكات ‪( CNN‬القسم ‪ .)8‬هل يمكننا تكييف المحوالت لبيانات الصورة‬
‫النموذجية؟ أثار هذا السؤال اهتمامًا كبيرًايف مجتمع الرؤية الحاسوبية‪Ramachandran et ( .‬‬
‫‪ )2019 ،al.‬الستبدال االلتفاف باالنتباه الذاتي‪ .‬ومع ذلك‪ ،‬فإن استخدامه لألنماط المتخصصة‬
‫في االنتباه يجعل من الصعب توسيع نطاق النماذج على مسرعات األجهزة‪Cordonnier ( .‬‬
‫‪ ) 2020 ،.et al‬أثبت نظريًا أن االنتباه الذاتي يمكن أن يتعلم التصرف بشكل مشابه لاللتفاف‪.‬‬
‫بشكل تجريبي‪ ،‬تم أخذ الرقع (‪ 2 × 2 )patches‬من الصور كمدخالت‪ ،‬لكن حجم الرقعة‬
‫الصغير يجعل النموذج قابل للتطبيق فقط على بيانات الصورة ذات الدقة المنخفضة‪.‬‬

‫بدون قيود محددة على حجم الرقعة‪ ،‬تستخرج محوالت الرؤية ‪vision transformers‬‬
‫(‪ )ViTs‬رقعاً من الصور وتغذيهايف مشفر المحول ‪ transformer encoder‬للحصول على‬
‫تمثيل عالمي‪ ،‬والذي سيتم تحويله أخيرًا من أجل التصنيف (‪.)2021 ،Dosovitskiy et al.‬‬
‫والجدير بالذكر أن المحوالت تُظهر قابلية تطوير أفضل من شبكات ‪ :CNN‬عند تدريب نماذج‬
‫أكبر على مجموعات بيانات أكبر‪ ،‬تتفوق محوالت الرؤية على شبكات ‪ ResNets‬بهامش كبير‪.‬‬
‫على غرار االرضية لتصميم معمارية الشبكةيف معالجة اللغة الطبيعية‪ ،‬أصبحت المحوالت أيضًا‬
‫مغيرًا للعبةيف الرؤية الحاسوبية‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪336‬‬

‫‪Model‬‬ ‫‪11.8.1‬‬
‫الشكل ‪ 11.8.1‬يصور العمارة النموذجية لمحوالت الرؤية ‪ .vision transformers‬تتكون هذه‬
‫البنية من جذع ‪ stem‬يقوم بتحويل الصور الى رقع ‪ ،patches‬وجسم ‪ body‬يعتمد على مشفر‬
‫المحوالت متعدد الطبقات ‪ ،multi-layer transformer encoder‬ورأس ‪ head‬يحول‬
‫التمثيل العام إلى تسمية اإلخراج ‪.output label‬‬

‫شكل ‪ 11.8.1‬معمارية محوالت الرؤية‪.‬يف هذا المثال‪ ،‬يتم تقسيم الصورة إلى ‪ 9‬رقع ‪.patches‬‬
‫يتم تحويل الرمز المميز "<‪ ">cls‬و‪ 9‬رقع صورة مسطحة عبر تضمين التصحيح و𝑛 كتل مشفر‬
‫المحوالت إلى ‪ 10‬تمثيالت‪ ،‬على التوالي‪ .‬يتم أيضًا تحويل تمثيل "<‪ ">cls‬إلى تسمية اإلخراج‪.‬‬

‫ضعيف اعتبارك صورة إدخال باالرتفاع ‪ ℎ‬والعرض 𝑤 والقنوات 𝑐‪ .‬تحديد ارتفاع وعرض الرقعة‬
‫على حد سواء‪ ،‬يتم تقسيم الصورة إلى سلسلة من الرقع ‪ ، 𝑚 = ℎ𝑤/𝑝2‬حيث يتم تسوية كل‬
‫رقعة إلى متجه طول ‪ .𝑐𝑝2‬بهذه الطريقة‪ ،‬يمكن معالجة رقع الصور بشكل مشابه للرموز ‪tokens‬‬
‫في تسلسل النص بواسطة مشفر المحوالت ‪ .transformer encoders‬يتم عرض عالمة مميزة‬
‫‪337‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫خاصة "<‪( ">cls‬فئة) ورقع الصورة المسطحة 𝑚 خطيًايف سلسلة من المتجهات ‪، 𝑚 + 1‬‬
‫مُلخَّصة بتضمينات موضعية قابلة للتعلم‪ .‬يحول مشفر المحول متعدد الطبقات متجهات اإلدخال‬
‫إلى نفس المقدار من تمثيالت متجه اإلخراج بنفس الطول‪ .‬إنه يعمل تمامًا بنفس طريقة مشفر‬
‫المحول األصلييف الشكل ‪ ،11.7.1‬ويختلف فقطيف موضع التسوية‪ .‬نظرًا ألن الرمز "<‪">cls‬‬
‫يحضر جميع رقع الصور عبر االنتباه الذاتي (انظر الشكل ‪ ،)11.6.1‬فإن تمثيله من خرج مشفر‬
‫المحول سيتحول إلى تسمية اإلخراج‪.‬‬

‫‪import torch‬‬
‫‪from torch import nn‬‬
‫‪from d2l import torch as d2l‬‬
‫‪Patch Embedding‬‬ ‫‪11.8.2‬‬
‫لتنفيذ محول الرؤية‪ ،‬لنبدأ بتضمين الرقعةيف الشكل ‪ .11.8.1‬يمكن تبسيط تقسيم الصورة إلى‬
‫رقع وإسقاط هذه الرقع المسطحة خطيًا كعملية التفاف واحدة‪ ،‬حيث يتم تعيين كل من حجم‬
‫النواة وحجم الخطوة على حجم الرقعة ‪.patch size‬‬

‫‪class PatchEmbedding(nn.Module):‬‬
‫‪def __init__(self, img_size=96, patch_size=16,‬‬
‫‪num_hiddens=512):‬‬
‫)(__‪super().__init‬‬
‫‪def _make_tuple(x):‬‬
‫‪if not isinstance(x, (list, tuple)):‬‬
‫)‪return (x, x‬‬
‫‪return x‬‬
‫‪img_size, patch_size = _make_tuple(img_size),‬‬
‫)‪_make_tuple(patch_size‬‬
‫‪self.num_patches = (img_size[0] //‬‬
‫( * )]‪patch_size[0‬‬
‫)]‪img_size[1] // patch_size[1‬‬
‫‪self.conv = nn.LazyConv2d(num_hiddens,‬‬
‫‪kernel_size=patch_size,‬‬
‫)‪stride=patch_size‬‬

‫‪def forward(self, X):‬‬


‫‪# Output shape: (batch size, no. of patches, no.‬‬
‫)‪of channels‬‬
‫)‪return self.conv(X).flatten(2).transpose(1, 2‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 338

‫ مخرجات تضمين الرقعة‬، ‫ كمدخالت‬img_size ‫ أخذ صور بارتفاع وعرض‬،‫في المثال التالي‬
‫( رقع يتم عرضها خطيًا على متجهات بطول‬img_size//patch_size)**2
.num_hiddens

img_size, patch_size, num_hiddens, batch_size = 96, 16,


512, 4
patch_emb = PatchEmbedding(img_size, patch_size,
num_hiddens)
X = torch.randn(batch_size, 3, img_size, img_size)
d2l.check_shape(patch_emb(X),
(batch_size, (img_size//patch_size)**2,
num_hiddens))
/home/d2l-worker/miniconda3/envs/d2l-en-release-
0/lib/python3.9/site-
packages/torch/nn/modules/lazy.py:178: UserWarning: Lazy
modules are a new feature under heavy development so
changes to the API or functionality can happen at any
moment.
warnings.warn('Lazy modules are a new feature under
heavy development '
Vision Transformer Encoder 11.8.3
‫ من حيث الموضع لمشفّر‬FFN ‫ الخاص بمشفر محول الرؤية اختالفًا طفيفًا عن‬MLP ‫يختلف‬
‫ هنا تستخدم دالة التنشيط الوحدة الخطية للخطأ‬،ً‫ أوال‬.)11.7.2 ‫المحول األصلي (انظر القسم‬
‫ والتي يمكن اعتبارها نسخة أكثر سالسة‬،)GELU( Gaussian error linear unit ‫الغاوسي‬
‫ على‬dropout ‫ يتم تطبيق التسرب‬،‫ ثانيًا‬.)2016,Hendrycks and Gimpel(ReLU ‫من‬
.‫ من أجل التنظيم‬MLP ‫إخراج كل طبقة متصلة بالكامليف‬

class ViTMLP(nn.Module):
def __init__(self, mlp_num_hiddens, mlp_num_outputs,
dropout=0.5):
super().__init__()
self.dense1 = nn.LazyLinear(mlp_num_hiddens)
self.gelu = nn.GELU()
self.dropout1 = nn.Dropout(dropout)
self.dense2 = nn.LazyLinear(mlp_num_outputs)
self.dropout2 = nn.Dropout(dropout)

def forward(self, x):


return
self.dropout2(self.dense2(self.dropout1(self.gelu(
‫‪339‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫)))))‪self.dense1(x‬‬
‫يتبع تنفيذ كتلة مشفر محول الرؤية تصميم ما قبل التسوية الوارديف الشكل ‪ ،11.8.1‬حيث يتم‬
‫تطبيق التسوية مباشرة قبل االنتباه متعدد الرؤوس أو ‪ .MLP‬على عكس ما بعد التسوية (" ‪add‬‬
‫‪" & norm‬يف الشكل ‪ ،)11.7.1‬حيث يتم وضع التسوية مباشرة بعد التوصيالت المتبقية‪ ،‬يؤدي‬
‫التسوية المسبقة إلى تدريب أكثر فعالية أو كفاءة للمحوالت (‪،2018 ،Baevski and Auli‬‬
‫‪ Xiong ، 2019 ،Wang et‬وآخرون ‪.)2020 ،‬‬

‫‪class ViTBlock(nn.Module):‬‬
‫‪def __init__(self, num_hiddens, norm_shape,‬‬
‫‪mlp_num_hiddens,‬‬
‫‪num_heads, dropout, use_bias=False):‬‬
‫)(__‪super().__init‬‬
‫)‪self.ln1 = nn.LayerNorm(norm_shape‬‬
‫= ‪self.attention‬‬
‫‪d2l.MultiHeadAttention(num_hiddens, num_heads,‬‬
‫‪dropout,‬‬
‫)‪use_bias‬‬
‫)‪self.ln2 = nn.LayerNorm(norm_shape‬‬
‫‪self.mlp = ViTMLP(mlp_num_hiddens, num_hiddens,‬‬
‫)‪dropout‬‬

‫‪def forward(self, X, valid_lens=None):‬‬


‫)‪X = self.ln1(X‬‬
‫(‪return X + self.mlp(self.ln2‬‬
‫)))‪X + self.attention(X, X, X, valid_lens‬‬
‫كما هو الحاليف القسم ‪ ،11.7.4‬فإن أي كتلة مشفر لمحول الرؤية ال تغير شكل إدخالها‪.‬‬

‫))‪X = torch.ones((2, 100, 24‬‬


‫)‪encoder_blk = ViTBlock(24, 24, 48, 8, 0.5‬‬
‫)(‪encoder_blk.eval‬‬
‫)‪d2l.check_shape(encoder_blk(X), X.shape‬‬
‫‪Putting It All Together‬‬ ‫‪11.8.4‬‬
‫إن المرور األمامي لمحوالت الرؤية أدناه واضح ومباشر‪ .‬أوالً‪ ،‬يتم إدخال صور اإلدخاليف مثيل‬
‫‪ ، PatchEmbedding‬والذي يتم ربط مخرجاته مع تضمين الرمز "<‪ .">cls‬يتم تلخيصهايف ‬
‫التضمينات الموضعية القابلة للتعلم قبل التسرب ‪ .dropout‬ثم يتم إدخال اإلخراجيف مشفر‬
‫المحوالت التي تكدس ‪ num_blks‬من مثيالت فئة ‪ .ViTBlock‬أخيرًا‪ ،‬يتم عرض تمثيل‬
‫الرمز المميز "<‪ ">cls‬بواسطة رأس الشبكة‪.‬‬

‫‪class ViT(d2l.Classifier):‬‬
‫ تقنيات التعلم العميق الحديثة‬:‫التعمق في التعلم العميق‬ 340

"""Vision transformer."""
def __init__(self, img_size, patch_size,
num_hiddens, mlp_num_hiddens,
num_heads, num_blks, emb_dropout,
blk_dropout, lr=0.1,
use_bias=False, num_classes=10):
super().__init__()
self.save_hyperparameters()
self.patch_embedding = PatchEmbedding(
img_size, patch_size, num_hiddens)
self.cls_token = nn.Parameter(torch.zeros(1, 1,
num_hiddens))
num_steps = self.patch_embedding.num_patches + 1
# Add the cls token
# Positional embeddings are learnable
self.pos_embedding = nn.Parameter(
torch.randn(1, num_steps, num_hiddens))
self.dropout = nn.Dropout(emb_dropout)
self.blks = nn.Sequential()
for i in range(num_blks):
self.blks.add_module(f"{i}", ViTBlock(
num_hiddens, num_hiddens,
mlp_num_hiddens,
num_heads, blk_dropout, use_bias))
self.head =
nn.Sequential(nn.LayerNorm(num_hiddens),
nn.Linear(num_hiddens,
num_classes))

def forward(self, X):


X = self.patch_embedding(X)
X = torch.cat((self.cls_token.expand(X.shape[0],
-1, -1), X), 1)
X = self.dropout(X + self.pos_embedding)
for blk in self.blks:
X = blk(X)
return self.head(X[:, 0])
Training 11.8.5
‫ يشبه تمامًا كيفية تدريب‬Fashion-MNIST ‫إن تدريب محول الرؤية على مجموعة بيانات‬
.8 ‫يف القسم‬CNN ‫شبكات‬
‫‪341‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪img_size, patch_size = 96, 16‬‬


‫‪num_hiddens, mlp_num_hiddens, num_heads, num_blks = 512,‬‬
‫‪2048, 8, 2‬‬
‫‪emb_dropout, blk_dropout, lr = 0.1, 0.1, 0.1‬‬
‫‪model = ViT(img_size, patch_size, num_hiddens,‬‬
‫‪mlp_num_hiddens, num_heads,‬‬
‫)‪num_blks, emb_dropout, blk_dropout, lr‬‬
‫)‪trainer = d2l.Trainer(max_epochs=10, num_gpus=1‬‬
‫‪data = d2l.FashionMNIST(batch_size=128,‬‬
‫))‪resize=(img_size, img_size‬‬
‫)‪trainer.fit(model, data‬‬

‫‪11.8.6‬‬
‫قد تالحظ أنه بالنسبة لمجموعات البيانات الصغيرة مثل ‪ ،Fashion-MNIST‬فإن محول‬
‫الرؤية المطبق لدينا ال يتفوق على ‪ResNet‬يف القسم ‪ .8.6‬يمكن إجراء مالحظات مماثلة حتى‬
‫على مجموعة بيانات ‪ 1.2( ImageNet‬مليون صورة)‪ .‬هذا ألن المحوالت تفتقر إلى تلك‬
‫المبادئ المفيدةيف االلتفاف‪ ،‬مثل ثبات الترجمة ‪ translation invariance‬والمحلية ‪locality‬‬
‫(القسم ‪ .)7.1‬ومع ذلك‪ ،‬تتغير الصورة عند تدريب نماذج أكبر على مجموعات بيانات أكبر‬
‫(على سبيل المثال‪ 300 ،‬مليون صورة)‪ ،‬حيث تتفوق محوالت الرؤية على شبكات ‪ResNets‬‬
‫بهامش كبيريف تصنيف الصور‪ ،‬مما يدل على التفوق الجوهري للمحوالتيف قابلية التوسع‬
‫‪ .)2021 ،Dosovitskiy et al.( scalability‬أدى إدخال محوالت الرؤية إلى تغيير مشهد‬
‫تصميم الشبكة لنمذجة بيانات الصورة‪ .‬وسرعان ما تم عرضها على مجموعة بيانات ‪ImageNet‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪342‬‬

‫باستخدام استراتيجيات تدريب فعالة للبيانات من ‪ .)2021,Touvron et al.( ،DeiT‬ومع‬


‫ذلك‪ ،‬فإن التعقيد التربيعي لالنتباه الذاتي (القسم ‪ )11.6‬يجعل بُنية المحوالت أقل مالءمة‬
‫للصور عالية الدقة‪ .‬نحو شبكة العمود الفقري لألغراض العامةيف الرؤية الحاسوبية‪ ،‬عالجت‬
‫محوالت ‪ Swin‬التعقيد الحسابي التربيعي فيما يتعلق بحجم الصورة (القسم ‪ )11.6.2‬وأضافت‬
‫مقدمات تشبه االلتفاف الخلفي ‪ ،back convolution-like priors‬مما أدى إلى توسيع قابلية‬
‫تطبيق المحوالت إلى مجموعة من مهام الرؤية الحاسوبية التي تتجاوز تصنيف الصور مع أحدث‬
‫النتائج (‪.)2021 ،.Liu et al‬‬

‫‪11.8.7‬‬
‫‪ .1‬كيف تؤثر قيمة ‪img_size‬على وقت التدريب؟‬
‫‪ .2‬بدالً من إسقاط تمثيل الرمز "<‪ ">cls‬على اإلخراج‪ ،‬كيف يتم عرض تمثيالت الرقعة‬
‫المتوسطة؟ قم بتنفيذ هذا التغيير وانظر كيف يؤثر على الدقة‪.‬‬
‫‪ .3‬هل يمكنك تعديل المعلمات الفائقة لتحسين دقة محول الرؤية؟‬

‫‪Large-‬‬ ‫‪11.9‬‬
‫‪Scale Pretraining with Transformers‬‬
‫حتى اآلنيف تصنيف الصور وتجارب الترجمة اآللية‪ ،‬تم تدريب النماذج على مجموعات البيانات‬
‫مع أمثلة المدخالت والمخرجات من البداية ألداء مهام محددة‪ .‬على سبيل المثال‪ ،‬تم تدريب‬
‫أحد المحوالت باستخدام أزواج من اإلنجليزية والفرنسية (القسم ‪ )11.7‬بحيث يمكن لهذا‬
‫النموذج ترجمة إدخال النص اإلنجليزي إلى الفرنسية‪ .‬نتيجة لذلك‪ ،‬يصبح كل نموذج خبيرًا‬
‫محددًا حساسًا حتى للتحول الطفيفيف توزيع البيانات (القسم ‪ .)4.7‬بالنسبة للنماذج المعممة‬
‫بشكل أفضل‪ ،‬أو حتى المتخصصين األكثر كفاءة الذين يمكنهم أداء مهام متعددة مع أو بدون‬
‫تكيف‪ ،‬فإن نماذج التدريب المسبق ‪ pretraining models‬على البيانات الكبيرة كانت شائعة‬
‫بشكل متزايد‪.‬‬

‫بالنظر إلى بيانات أكبر للتدريب المسبق‪ ،‬تعمل بنية المحوالت بشكل أفضل مع زيادة حجم‬
‫النموذج وحساب التدريب‪ ،‬مما يدل على سلوك القياس المتفوق‪ .‬على وجه التحديد‪ ،‬يتم قياس‬
‫أداء نماذج اللغة القائمة على المحوالت كقانون قوة مع مقدار معلمات النموذج ورموز التدريب‬
‫وحساب التدريب (‪ .)2020 ،Kaplan et al.‬تتضح قابلية تطوير المحوالت أيضًا من خالل‬
‫األد اء المعزز بشكل كبير من محوالت الرؤية األكبر المدربة على بيانات أكبر (تمت مناقشتهايف ‬
‫القسم ‪ .)11.8‬تشمل قصص النجاح األحدث غاتو ‪ ،Gato‬وهو نموذج عام يمكنه لعب أتاري‪،‬‬
‫والتعليق على الصور‪ ،‬والدردشة‪ ،‬والعمل كإنسان آلي (‪ Gato .)2022 ،Reed et al‬هو محول‬
‫واحد يتسع بش كل جيد عند اختباره مسبقًا على طرائق متنوعة بمايف ذلك النص والصور وعزم‬
‫‪343‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫الدوران المشترك وضغط األزرار‪ .‬والجدير بالذكر أن كل هذه البيانات متعددة الوسائط يتم‬
‫تسلسلها إلى تسلسل مسطح من الرموز ‪ ،tokens‬والتي يمكن معالجتها على غرار الرموز النصية‬
‫‪( text tokens‬القسم ‪ )11.7‬أو رقع الصور ‪( image patches‬القسم ‪ )11.8‬بواسطة‬
‫المحوالت‪.‬‬

‫قبل النجاح المقنع لمحوالت التدريب المسبق للبيانات متعددة الوسائط‪ ،‬كانت المحوالت مقيدة‬
‫على نطاق واسع بكمية كبيرة من النصوص‪ .‬تم اقتراح معمارية المحوالتيف الشكل ‪11.7.1‬يف ‬
‫األصل للترجمة اآللية‪ ،‬وتتألف من مشفر لتمثيل تسلسالت اإلدخال ومفكك شفرة لتوليد‬
‫متواليات الهدف‪.‬يف المقام األول‪ ،‬يمكن استخدام المحوالتيف ثالثة أوضاع مختلفة‪ :‬المشفر‬
‫فقط ‪ ،encoder-only‬والمشفر‪-‬مفكك الشفرة ‪ encoder-decoder‬ومفكك الشفرة فقط‬
‫‪.decoder-only‬يف ختام هذا الفصل‪ ،‬سنراجع هذه األوضاع الثالثة ونوضح قابلية التوسعيف ‬
‫المحوالت قبل التدريب‪.‬‬

‫‪Encoder-Only‬‬ ‫‪11.9.1‬‬
‫عند استخدام مشفر المحول فقط‪ ،‬يتم تحويل سلسلة من الرموز لإلدخال إلى نفس عدد‬
‫التمثيالت التي يمكن إسقاطها بشكل أكبريف اإلخراج (على سبيل المثال‪ ،‬التصنيف)‪ .‬يتكون‬
‫مشفر المحوالت من طبقات االنتباه الذاتي‪ ،‬حيث تحضر جميع الرموز لإلدخال مع بعضها‬
‫البعض‪ .‬على سبيل المثال‪ ،‬محوالت الرؤية الموضحةيف الشكل ‪ 11.8.1‬هي عبارة عن مشفر‬
‫فقط ‪ ،encoder-only‬حيث تقوم بتحويل سلسلة من رقع صورة اإلدخال إلى تمثيل رمز‬
‫"<‪ .">cls‬نظرًا ألن هذا التمثيل يعتمد على جميع الرموز لإلدخال‪ ،‬فإنه يتم عرضه بشكل أكبريف ‬
‫تسميات التصنيف‪ .‬تم استلهام هذا التصميم من محول سابق يعمل بالمشفر فقط تم اختباره‬
‫مسبقًا على النص‪( BERT :‬تمثيالت التشفير ثنائية االتجاه من المحوالت ‪Bidirectional‬‬
‫‪.)2018 ،Devlin et al.( )Encoder Representations from Transformers‬‬

‫تم تدريب ‪ BERT‬مسبقًا على تسلسالت النص باستخدام نمذجة اللغة ال ُمقنعة ‪masked‬‬
‫‪ :language modeling‬يتم إدخال نص اإلدخال مع الرموز ال ُمقنعة ‪ masked tokens‬عشوائيًا‬
‫في مشفر المحوالت للتنبؤ بالرموز المقنعة‪ .‬كما هو موضحيف الشكل ‪ ،11.9.1‬تسلسل النص‬
‫األصلي "‪ "I‬و "‪ "love‬و "‪ "this‬و "‪ "red‬و "‪ "car‬مُجهز مسبقًا بالرمز "<‪ ">cls‬و "<‪">mask‬‬
‫يستبدل الرمز بشكل عشوائي "‪“ love‬؛ ثم يتم التقليل من خطأ االنتروبيا بين الرمز المقنع "‪"love‬‬
‫وتنبؤاته أثناء التدريب المسبق‪ .‬الحظ أنه ال يوجد قيديف نمط االنتباه الخاص بمشفرات‬
‫المحوالت (يمين الشكل ‪ ) 11.9.1‬لذلك يمكن لجميع الرموز أن تتعامل مع بعضها البعض‪.‬‬
‫وبالتالي‪ ،‬فإن التنبؤ بـ "‪ " love‬يعتمد على رموز اإلدخال قبل وبعدهيف التسلسل‪ .‬هذا هو السبب‬
‫في أن ‪ BERT‬هو "مشفر ثنائي االتجاه ‪ ." bidirectional encoder‬بدون الحاجة إلى وضع‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪344‬‬

‫التسميات اليدوية ‪ ،manual labeling‬يمكن استخدام بيانات نصية كبيرة الحجم من الكتب‬
‫وويكيبيديا للتدريب المسبق على ‪.BERT‬‬

‫‪Pretraining BERT‬‬ ‫‪11.9.1.1‬‬

‫الشكل ‪ 11.9.1‬على اليسار‪ :‬التدريب المسبق لـ ‪ BERT‬بنمذجة اللغة المقنعة‪ .‬يعتمد توقع‬
‫رمز "‪ " love‬المقنع على جميع رموز اإلدخال قبل وبعد "‪ ." love‬على اليمين‪ :‬نمط االنتباهيف ‬
‫مشفر المحوالت‪ .‬كل رمز مميز على طول المحور الرأسي يحضر جميع رموز اإلدخال على‬
‫طول المحور األفقي‪.‬‬

‫‪Fine-Tuning BERT‬‬ ‫‪11.9.1.2‬‬


‫يمكن ضبط ‪ BERT‬المدروس مسبقًا لمهام الترميز النهائية التي تتضمن نصًا واحدًا أو أزواجًا‬
‫نصية‪ .‬أثناء الضبط الدقيق ‪ ،Fine-Tuning‬يمكن إضافة طبقات إضافية إلى ‪ BERT‬باستخدام‬
‫معلمات عشوائية‪ :‬سيتم تحديث هذه المعلمات ومعلمات ‪ BERT‬سابقة التدريب لتالئم ‪fit‬‬
‫بيانات التدريب الخاصة بمهام ‪.downstream‬‬
‫‪345‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫يوضح الشكل ‪ 11.9.2‬ضبط ‪ BERT‬لتحليل المشاعر ‪ .sentiment analysis‬مشفر المحول‬


‫عبارة عن ‪ BERT‬تم اختباره مسبقًا‪ ،‬والذي يأخذ تسلسل نصي كمدخل ويغذي تمثيل "<‪">cls‬‬
‫(تمثيل عالمي للمدخالت)يف طبقة إضافية متصلة بالكامل للتنبؤ بالمشاعر‪ .‬أثناء الضبط الدقيق‪،‬‬
‫يتم تقليل فقدان االنتروبيا بين التنبؤ والتسمية على بيانات تحليل المشاعر عبر خوارزميات قائمة‬
‫على التدرج‪ ،‬حيث يتم تدريب الطبقة اإلضافية من نقطة الصفر بينما يتم تحديث معلمات‬
‫‪ BERT‬المحددة مسبقًا‪ .‬يقوم ‪ BERT‬بأكثر من مجرد تحليل المشاعر‪ .‬طورت التمثيالت‬
‫اللغوية العامة التي تعلمها ‪ BERT‬المكونة من ‪ 350‬مليون متغير من ‪ 250‬مليار رمز تدريب من‬
‫أحدث ما توصلت إليه مهام اللغة الطبيعية مثل تصنيف النص الفردي ‪single text‬‬
‫‪ ،classification‬وتصنيف أزواج النص ‪ text pair classification‬أو االنحدار ‪،regression‬‬
‫ووضع عالمات على النص ‪ ،text tagging‬واإلجابة على األسئلة ‪.question answering‬‬

‫قد تالحظ أن هذه المهام النهائية تتضمن فهم أزواج النص‪ .‬يتسبب تدريب ‪ BERT‬المسبقيف ‬
‫خسارة أخرى للتنبؤ بما إذا كانت إحدى الجمل تتبع األخرى مباشرة‪ .‬ومع ذلك‪ ،‬تم العثور الحقًا‬
‫على هذه الخسارة غير مفيدة عند إجراء اختبار مسبق لـ ‪ ،RoBERTa‬وهو متغير ‪ BERT‬من‬
‫نفس الحجم‪ ،‬على ‪ 2000‬مليار رمز (‪ .)2019 ،Liu et al.‬مشتقات أخرى من ‪ BERT‬حسنت‬
‫معماريات النماذج أو أهداف ما قبل التدريب‪ ،‬مثل ‪( ALBERT‬فرض مشاركة المعلمات)‪،‬‬
‫(‪( SpanBERT ،)2019,Lan et al.‬تمثل وتوقع مساحات النص ‪representing and‬‬
‫‪( DistilBERT )2020,Joshi et al.( ،)predicting spans of text‬خفيف الوزن عبر‬
‫تقطير المعرفة ‪،)2019 ،Sanh et al.( )lightweight via knowledge distillation‬‬
‫و‪( ELECTRA‬اكتشاف الرموز المستبدلة ‪،Clark et al.( )replaced token detection‬‬
‫‪ .)2020‬عالوة على ذلك‪ ،‬استوحى ‪ BERT‬المحوالت من التدريب المسبقيف الرؤية‬
‫الحاسوبية‪ ،‬مثل محوالت الرؤية (‪ ،)2021 ،Dosovitskiy et al.‬ومحوالت ‪Liu ( ،Swin‬‬
‫‪ ،)2021,et al.‬و‪( MAE‬المشفرات التلقائية المقنعة ‪He et ( )masked autoencoders‬‬
‫‪.)2022 ،al.‬‬

‫‪Encoder-Decoder‬‬ ‫‪11.9.2‬‬
‫نظرًا ألن مشفر المحول يحول سلسلة من رموز اإلدخال إلى نفس عدد تمثيالت اإلخراج‪ ،‬ال‬
‫يمكن لوضع المشفر فقط إنشاء سلسلة من الطول التعسفي كما هو الحاليف الترجمة اآللية‪ .‬تم‬
‫اقتراح بُ نية المحوالتيف األصل للترجمة اآللية‪ ،‬وتحتوي أيضًا على مفكك الشفرة تتنبأ بشكل‬
‫تلقائي بالتسلسل المستهدف للطول التعسفي ‪ ،‬رمزًا رمزًا ‪ ،‬مشروطًا بكل من إخراج المشفر‬
‫وإخراج مفكك الشفرة‪ )1( :‬للتكييف على إخراج المشفر ‪ ،‬يسمح االنتباه المتبادل للمشفر‪-‬‬
‫مفكك الشفرة (االنتباه متعدد الرؤوس لمفكك الشفرةيف الشكل ‪ )11.7.1‬للرموز المستهدفة‬
‫بالحضور إلى جميع الرموز لإلدخال ؛ (‪ )2‬يتحقق التكييف على خرج مفكك الشفرة من خالل‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪346‬‬

‫نمط انتباه سببي ‪( causal attention pattern‬االنتباه المقنع متعدد الرؤوس لمفكك الشفرة‬
‫في الشكل ‪ ، ) 11.7.1‬حيث ال يمكن ألي رمز مستهدف أن يحضر إال إلى الرموز السابقة والحالية‬
‫في التسلسل المستهدف‪.‬‬

‫للتدريب المسبق لمشفر‪-‬مفكك شفرة المحوالت بما يتجاوز بيانات الترجمة اآللية التي تحمل‬
‫عالمات بشرية‪ ،‬فإن ‪ )2019,Lewis et al.( ،BART‬و ‪ )2020,Raffel et al.( ،T5‬هما‬
‫محوالت مقترحةيف نفس الوقت لمشفر‪-‬مفكك شفرة تم تدريبهما مسبقًا على نصوص كبيرة‬
‫الحجم‪ .‬يحاول كالهما إعادة بناء النص األصلييف أهدافهم المدربة سابقاً‪ ،‬بينما يؤكد األول على‬
‫المدخالت المزعجة ‪( noising input‬على سبيل المثال‪ ،‬اإلخفاء والحذف والتبديل والتناوب)‬
‫واألخير يسلط الضوء على توحيد المهام المتعددة مع دراسات االجتثاث الشاملة‪.‬‬

‫‪T5‬‬ ‫‪11.9.2.1‬‬
‫كمثال على مشفر‪-‬مفكك شفرة المحوالت سابقة التدريب ‪ ،‬يوحِّد ‪( T5‬محول نقل النص إلى‬
‫نص ‪ )Text-to-Text Transfer Transformer‬العديد من المهام مثل مشكلة النص إلى‬
‫النص نفسه‪ :‬بالنسبة ألي مهمة ‪ ،‬يكون إدخال المشفر هو وصف المهمة (على سبيل المثال ‪،‬‬
‫"تلخيص ‪ )":" ، " Summarize‬متبوعًا بإدخال مهمة (على سبيل المثال ‪ ،‬سلسلة من الرموز‬
‫المميزة من مقالة ‪ ، )a sequence of tokens from an article‬ويتنبأ مفكك الشفرة بإخراج‬
‫ب المهمة (على سبيل المثال ‪ ،‬سلسلة من الرموز المميزة تلخص مقالة اإلدخال ‪sequence of‬‬
‫‪ .)tokens summarizing the input article‬ألداء النص إلى نص‪ ،‬يتم تدريب ‪ T5‬على‬
‫إنشاء بعض نص الهدف المشروط على إدخال النص‪.‬‬

‫الشكل ‪ 11.9.3‬على اليسار‪ :‬التدريب المسبق على ‪ T5‬من خالل توقع فترات متتالية‪ .‬الجملة‬
‫األصلية هي "‪ ،”car" ،”red" ،”this" ،”love" ،”I‬حيث يتم استبدال "‪ "love‬برمز "<‪،“>X‬‬
‫‪347‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫ومتتالية "‪ "car" ،”red‬استبدالها برمز مميز "<‪ .">Y‬التسلسل المستهدف ينتهي برمز خاص‬
‫"<‪ .">Z‬على اليمين‪ :‬نمط االنتباهيف مشفر‪-‬مفكك شفرة المحوالت‪.‬يف االنتباه الذاتي للمشفر‬
‫(المربع السفلي)‪ ،‬تحضر جميع الرموز لإلدخال بعضها البعض؛يف االنتباه المتبادل للمشفر‬
‫ومفكك الشفرة (المستطيل العلوي)‪ ،‬يحضر كل رمز مستهدف جميع الرموز لإلدخال؛يف االنتباه‬
‫الذاتي لمفكك الشفرة (المثلث العلوي)‪ ،‬يحضر كل رمز مميز الهدف الرموز الحالية والماضية‬
‫فقط (السببية ‪.)causal‬‬

‫للحصول على مدخالت ومخرجات من أي نص أصلي‪ ،‬يتم تدريب ‪ T5‬مسبقًا على التنبؤ بفترات‬
‫متتالية‪ .‬على وجه التحديد‪ ،‬يتم استبدال الرموز من النص بشكل عشوائي برموز خاصة حيث يتم‬
‫استبدال كل فترة متتالية بالرمز نفسه‪ .‬تأمل المثاليف الشكل ‪ ،11.9.3‬حيث النص األصلي هو‬
‫"‪ ."car" ،”red" ،”this" ،”love" ،”I‬يتم استبدال الرموز "‪ "car" ،”red" ،”love‬بشكل عشوائي‬
‫برموز خاصة‪ .‬نظرًا ألن "‪ "red‬و "‪ "car‬يمثالن امتدادًا متتاليًا‪ ،‬يتم استبدالهما بنفس الرمز الخاص‪.‬‬
‫نتيجة لذلك‪ ،‬تسلسل اإلدخال هو "”‪" ،“>"<X ،I‬هذا"‪ ،“>Y<" ،‬والتسلسل الهدف هو "<‪،“>X‬‬
‫"‪ ،" >Z< "،" car "،" red " ،“>Y<" ،”love‬حيث" <‪" >Z‬هو رمز آخر يشير إلى النهاية‪ .‬كما هو‬
‫مبينيف الشكل ‪ ،11.9.3‬فإن مفكك الشفرة لديه نمط انتباه سببي لمنع نفسه من االنتباه بالرموز‬
‫المستقبلية أثناء التنبؤ بالتسلسل‪.‬‬

‫في ‪ ،T5‬يُشار أيضًا إلى التنبؤ بامتداد متتالي ‪ consecutive span‬على أنه إعادة بناء نص تالف‬
‫‪ .reconstructing corrupted text‬مع هذا الهدف‪ ،‬يتم تدريب ‪ T5‬مسبقًا على ‪ 1000‬مليار‬
‫رمز من بيانات )‪ ،C4 (Colossal Clean Crawled Corpus‬والتي تتكون من نص إنجليزي‬
‫نظيف من الويب (‪.)2020 ،Raffel et al.‬‬

‫‪Fine-Tuning T5 T5‬‬ ‫‪11.9.2.2‬‬


‫على غرار ‪ ،BERT‬يحتاج ‪ T5‬إلى ضبط دقيق (تحديث معلمات ‪ )T5‬على بيانات التدريب‬
‫الخاصة بالمهمة ألداء هذه المهمة‪ .‬تشمل االختالفات الرئيسية عن الضبط الدقيق لـ ‪ BERT‬ما‬
‫يلي‪ )1( :‬يتضمن إدخال ‪ T5‬أوصاف المهام؛ (‪ )2‬يمكن أن يولد ‪ T5‬تسلسالت ذات طول‬
‫تعسفي باستخدام مفكك شفرة المحول؛ (‪ )3‬ال توجد طبقات إضافية مطلوبة‪.‬‬

‫يوضح الشكل ‪ 11.9.4‬ضبط ‪ T5‬بدقة باستخدام تلخيص النص كمثال‪.‬يف هذه المهمة المتلقية‬
‫للمعلومات‪ ،‬تعتبر الرموز لوصف المهمة ”‪ “Summarize”, “:‬متبوعة برموز المقالة المميزة هي‬
‫مدخالت إلى للمشفر‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪348‬‬

‫الشكل ‪ 11.9.4‬الضبط الدقيق لـ ‪ T5‬لتلخيص النص‪ .‬يتم تغذية كل من وصف المهمة ورموز‬
‫المقالةيف مشفر المحول للتنبؤ بالملخص‪.‬‬

‫بعد الضبط الدقيق‪ ،‬حققت )‪ T5 (T5-11B‬التي تبلغ ‪ 11‬مليار معلمة نتائج متطورة على معايير‬
‫الترميز المتعددة (مثل التصنيف) والتوليد (على سبيل المثال‪ ،‬التلخيص)‪ .‬منذ إطالقه‪ ،‬تم‬
‫استخدام ‪ T5‬على نطاق واسعيف األبحاث الالحقة‪ .‬على سبيل المثال‪ ،‬تم تصميم محوالت‬
‫التبديل على أساس ‪ T5‬لتنشيط مجموعة فرعية من المعلمات لتحسين الكفاءة الحسابية‬
‫(‪.)2022 ،Fedus et al.‬يف نموذج تحويل النص إلى صورة يسمى ‪ ،Imagen‬يتم إدخال النص‬
‫إلى مشفر ‪ T5‬مجمد ‪ )T5-XXL( frozen T5 encoder‬مع ‪ 4.6‬مليار معلمة ( ‪Saharia‬‬
‫‪ .)2022 ،et al.‬تشير األمثلة الواقعية لتحويل النص إلى صورةيف الشكل ‪ 11.9.5‬إلى أن مشفر‬
‫‪ T5‬وحده قد يمثل النص بشكل فعال حتى بدون ضبطه بدقة‪.‬‬

‫الشكل ‪ 11.9.5‬أمثلة على تحويل النص إلى صورة من خالل نموذج ‪ ،Imagen‬الذي يكون‬
‫مشفر النص الخاص به من ‪( T5‬األرقام مأخوذة من ‪.))Saharia et al. (2022‬‬
‫‪349‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪Decoder-Only‬‬ ‫‪11.9.3‬‬
‫لقد راجعنا مشفر المحوالت فقط ومشفر‪-‬مفكك الشفرة المحوالت‪ .‬بدالً من ذلك‪ ،‬تزيل‬
‫مفكك شفرة المحوالت فقط كامل المشفر والطبقة الفرعية لمفكك الشفرة مع االنتباه المتبادل‬
‫للمشفر‪-‬مفكك الشفرة من بُنية المشفر‪-‬مفكك الشفرة األصلية الموضحةيف الشكل ‪.11.7.1‬‬
‫في الوقت الحاضر‪ ،‬كانت مفكك شفرة المحوالت فقط هي العمارة الفعليةيف نمذجة اللغة على‬
‫نطاق واسع (القسم ‪ ،)9.3‬والتي تستفيد من مجموعات النصوص غير المصنفة الوفيرةيف العالم‬
‫عبر التعلم تحت اإلشراف الذاتي‪.‬‬

‫‪GPT-2 GPT 11.9.3.1‬‬


‫باستخدام النمذجة اللغوية كهدف للتدريب‪ ،‬يختار نموذج ‪( GPT‬التدريب المسبق التوليدي‬
‫‪ )generative pre-training‬مفكك شفرة المحوالت كعمودها الفقري (‪،Radford et al.‬‬
‫‪.)2018‬‬

‫الشكل ‪ 11.9.6‬اليسار‪ :‬التدريب المسبق على ‪ GPT‬بنمذجة اللغة‪ .‬التسلسل المستهدف هو‬
‫تسلسل اإلدخال الذي تم إزاحته بواسطة رمز واحد‪ .‬كل من "<‪ ">bos‬و "<‪ ">eos‬هما رمزان‬
‫مميزان يرمزان إلى بداية ونهاية التسلسالت‪ ،‬على التوالي‪ .‬اليمين‪ :‬نمط االنتباهيف مفكك شفرة‬
‫المحوالت‪ .‬كل رمز مميز على طول المحور الرأسي يحضر فقط الرموز السابقة على طول‬
‫المحور األفقي (سببي)‪.‬‬

‫بعد تدريب نموذج اللغة االنحدار الذاتي كما هو موضحيف القسم ‪ ،9.3.3‬يوضح الشكل ‪11.9.6‬‬
‫التدريب المسبق لـ ‪ GPT‬باستخدام مشفر المحوالت‪ ،‬حيث يكون التسلسل المستهدف هو‬
‫تسلسل اإلدخال الذي تم إزاحته برمز واحد‪ .‬الحظ أن نمط االنتباه السببييف وحدة مفكك شفرة‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪350‬‬

‫المحوالت يفرض أن كل رمز ال يمكن أن يحضر إال إلى الرموز السابقة (ال يمكن للتنبؤ بالرمز‬
‫المميز أن يحضر إلى الرموز المستقبلية)‪.‬‬

‫تحتوي ‪ GPT‬على ‪ 100‬مليون معلمة وتحتاج إلى ضبطها لمهام ‪ downstream‬الفردية‪ .‬تم‬
‫تقديم نموذج لغة مفكك شفرة محول أكبر بكثير‪ ، GPT-2 ،‬بعد عام واحد ( ‪Radford et‬‬
‫‪ .)2019 ،al.‬بالمقارنة مع مفكك شفرة المحوالت األصليةيف ‪ ،GPT‬تم اعتماد التسوية المسبقة‬
‫‪( pre-normalization‬الذي تمت مناقشتهيف القسم ‪ )11.8.3‬والتهيئة المحسنة وقياس الوزن‬
‫في ‪ .GPT-2‬حصل ‪ GPT-2‬الذي تم تدريبه مسبقًا على ‪ 40‬غيغابايت من النص‪ ،‬والذي يبلغ‬
‫حجمه ‪ 1.5‬مليار معلمة‪ ،‬على أحدث النتائج المتعلقة بمعايير نمذجة اللغة والنتائج الواعدةيف ‬
‫مهام أخرى متعددة دون تحديث المعلمات أو ال ُبنية‪.‬‬

‫‪GPT-3 11.9.3.2‬‬
‫أظهر ‪ GPT-2‬إمكانية استخدام نفس نموذج اللغة لمهام متعددة دون تحديث النموذج‪ .‬يعد‬
‫هذا أكثر كفاءة من الناحية الحسابية من الضبط الدقيق‪ ،‬والذي يتطلب تحديثات النموذج عبر‬
‫حساب التدرج‪.‬‬

‫الشكل ‪ 11.9.7‬التعلم بدون لقطة ‪ Zero-shot‬ولقطة واحدة ‪ one-shot‬ولقطات قليلة‬


‫‪ few-shot‬باستخدام نماذج اللغة (مفكك شفرة المحوالت)‪ .‬ال حاجة لتحديث المعلمة‪.‬‬

‫قبل شرح االستخدام األكثر كفاءة من الناحية الحسابية لنماذج اللغة دون تحديث المعلمة‪ ،‬تذكر‬
‫القسم ‪ 9.5‬أنه يمكن تدريب نموذج اللغة إلنشاء تسلسل نصي مشروط ببعض تسلسل نص‬
‫‪351‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫البادئة‪ .‬وبالتالي‪ ،‬قد ينتج عن نموذج اللغة الذي تم اختباره مسبقًا إخراج المهمة كتسلسل بدون‬
‫تحديث المعلمة‪ ،‬بشرط تسلسل اإلدخال مع وصف المهمة‪ ،‬وأمثلة اإلدخال والمخرجات الخاصة‬
‫بالمهمة‪ ،‬والموجه ‪( prompt‬إدخال المهمة)‪ .‬يمكن تصنيف نموذج التعلم هذا بشكل أكبر إلى‬
‫‪ ،one-shot ،zero-shot‬و‪ ،few-shot‬عندما ال يكون هناك أمثلة على المدخالت‬
‫والمخرجات الخاصة بالمهمة‪ ،‬أو أمثلة قليلة‪ ،‬على التوالي (الشكل ‪.)11.9.7‬‬

‫الشكل ‪ 11.9.8‬األداء اإلجمالي لـ ‪ GPT-3‬لجميع المعايير المعيارية المقومة بالدقة البالغ‬


‫عددها ‪( 42‬التسمية التوضيحية مقتبسة والشكل مأخوذ من ‪.))Brown et al. (2020‬‬

‫تم اختبار هذه اإلعدادات الثالثةيف ‪ ،)2020,Brown et al.( ،GPT-3‬الذي يستخدم أكبر‬
‫إصدار له البيانات وحجم النموذج بحوالي أمرين من حيث الحجم أكبر من تلك الموجودةيف ‬
‫‪ .GPT-2‬يستخدم ‪ GPT-3‬نفس بُنية مفكك شفرة المحوالتيف سلفها المباشر ‪GPT-2‬‬
‫فيما عدا أن أنماط االنتباه (يمين الشكل ‪ )11.9.6‬تكون متناثرةيف الطبقات المتناوبة‪ .‬نظرًا ألن‬
‫‪ GPT-3‬مُدرب مسبقًا بـ ‪ 300‬مليار رمز‪ ،‬فإنه يعمل بشكل أفضل مع حجم نموذج أكبر‪ ،‬حيث‬
‫يزيد أداء عدد قليل من اللقطات بسرعة أكبر (الشكل ‪ .)11.9.8‬على الرغم من التمتع بكفاءة‬
‫حسابية‪ ،‬إال أن التعلم قليل اللقطات لـ ‪ GPT-3‬كان أقل من أداء النماذج الحديثة التي تم ضبطها‬
‫والتي تتطلب تحديثات النموذج‪ .‬ومع ذلك‪ ،‬فقد قام ‪ GPT-3‬بتشغيل مجموعة واسعة من‬
‫التطبيقات النهائية عبر الويب‪ :‬فقد كان ينتج ‪ 4.5‬مليار كلمة كل يوم حوالي تسعة أشهر من إصدار‬
‫‪ API‬الخاص به‪.‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪352‬‬

‫‪Scalability‬‬ ‫‪11.9.4‬‬
‫يوضح الشكل ‪ 11.9.8‬بشكل تجريبي قابلية التوسع للمحوالتيف نموذج اللغة ‪.GPT-3‬‬
‫بالنسبة لنمذجة اللغة‪ ،‬اقترحت دراسات تجريبية أكثر شموالً حول قابلية توسيع المحوالت تدريب‬
‫محوالت أكبر بمزيد من البيانات والحسابات (‪.)2020 ،Kaplan et al.‬‬

‫الشكل ‪ 11.9.9‬يتحسن أداء نموذج لغة المحوالت بسالسة ألننا نزيد من حجم النموذج‬
‫وحجم مجموعة البيانات وكمية الحوسبة المستخدمة للتدريب‪ .‬لتحقيق األداء األمثل‪ ،‬يجب‬
‫رفع مستوى جميع العوامل الثالثة جنبًا إلى جنب‪ .‬لألداء التجريبي عالقة قانون القوة مع كل‬
‫عامل على حدة عندما ال يتم اختناقهما من قبل العاملين اآلخرين (التسمية التوضيحية مقتبسة‬
‫والشكل مأخوذ من ‪.))2020( .Kaplan et al‬‬

‫كما هو مبينيف الشكل ‪ ،11.9.9‬يمكن مالحظة دقة قانون القدرة المقاس ‪power-law‬‬
‫‪scaling‬يف األداء فيما يتعلق بحجم النموذج (عدد المعلمات‪ ،‬باستثناء طبقات التضمين)‪،‬‬
‫وحجم مجموعة البيانات (عدد الرموز للتدريب)‪ ،‬وكمية حساب التدريب (‪PetaFLOP / s-‬‬
‫‪ ،days‬باستثناء طبقات التضمين)‪ .‬بشكل عام‪ ،‬تؤدي زيادة كل هذه العوامل الثالثة جنبًا إلى جنب‬
‫إلى أداء أفضل‪ .‬ومع ذلك‪ ،‬ال تزال كيفية زيادتها جنبًا إلى جنب مسألة نقاش (( ‪Hoffmann et‬‬
‫‪.)2022 ،.al‬‬

‫الشكل ‪ 11.9.10‬دورات تدريب نموذج لغة المحوالت (الشكل مأخوذ من ‪.Kaplan et al‬‬
‫(‪.))2020‬‬
‫‪353‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫إلى جانب األداء المتزايد‪ ،‬تتمتع الطرز الكبيرة أيضًا بكفاءة أفضل للعينة من النماذج الصغيرة‪.‬‬
‫يوضح الشكل ‪ 11.9.10‬أن النماذج الكبيرة تحتاج إلى عدد أقل من عينات التدريب (الرموز التي‬
‫تمت معالجتها) ألداء نفس المستوى الذي تحققه النماذج الصغيرة‪ ،‬ويتم قياس األداء بسالسة‬
‫باستخدام الحساب‪.‬‬

‫الشكل ‪ 11.9.11‬أداء ‪( GPT-3‬خطأ التحقق من االنتروبيا المتقاطعة) يتبع اتجاه قانون القوة‬
‫مع مقدار الحساب المستخدم للتدريب‪ .‬سلوك قانون القوة الذي لوحظيف ‪.Kaplan et al‬‬
‫(‪ )2020‬يستمر لخطوتين إضافيتين من حيث الحجم مع انحرافات صغيرة فقط عن المنحنى‬
‫المتوقع‪ .‬تُستثنى معلمات التضمين من عدد الحسابات والمعلمات (التسمية التوضيحية‬
‫مقتبسة والرقم مأخوذ من (‪.))2020,Brown et al.‬‬

‫سلوكيات القياس التجريبيةيف (‪ )2020,Kaplan et al‬تم اختبارهايف نماذج المحوالت الكبيرة‬


‫الالحقة‪ .‬على سبيل المثال‪ ،‬دعمت ‪ GPT-3‬هذه الفرضية بأمرين آخرين من حيث الحجميف ‬
‫الشكل ‪.11.9.11‬‬

‫لقد ألهمت قابلية تطوير المحوالتيف سلسلة ‪ GPT‬نماذج لغة المحوالت الالحقة‪ .‬بينما تم اتباع‬
‫مفكك شفرة المحوالتيف ‪ GPT-3‬إلى حد كبيريف ‪OPT (Open Pretrained‬‬
‫)‪ )2022,Zhang et al.( ،Transformers‬باستخدام ‪ 7/1‬فقط من البصمة الكربونية للسابق‪،‬‬
‫التعمق في التعلم العميق‪ :‬تقنيات التعلم العميق الحديثة‬ ‫‪354‬‬

‫تم استخدام مفكك شفرة محول ‪GPT-2‬يف تدريب ‪ - 530‬ميجاترون ‪ -‬تورينج ‪NLG‬‬
‫((‪ )2022 ،.Smith et al‬بمليار متغير مع ‪ 270‬مليار من رموز التدريب‪ .‬بعد تصميم ‪GPT-‬‬
‫‪ ،2‬حقق ‪ )2021,Rae et al.( ،Gopher‬الذي يبلغ حجمه ‪ 280‬مليار معلمة والذي تم تدريبه‬
‫مسبقًا بـ ‪ 300‬مليار رمز أداءً متطورًا عبر الغالبيةيف حوالي ‪ 150‬مهمة متنوعة‪ .‬إن وراثة نفس ال ُبنية‬
‫واستخدام نفس الميزانية الحسابية لـ ‪)2022,Hoffmann et al.( ،Chinchilla ،Gopher‬‬
‫هو نموذج أصغر بكثير (‪ 70‬مليار معلمة) يتدرب لفترة أطول (‪ 1.4‬تريليون رمز تدريب)‪ ،‬متفوقًا‬
‫على ‪Gopher‬يف العديد من المهام‪ .‬لمواصلة خط القياس لنمذجة اللغة‪( PaLM ،‬نموذج لغة‬
‫المسار ‪ ،)2022 ،Chowdhery et al.( )Pathway Language Model‬مفكك شفرة‬
‫محول ‪ 540‬مليار متغير مع تصميمات معدلة تم اختبارها مسبقًا على ‪ 780‬مليار رمز‪ ،‬تفوقت‬
‫على متوسط األداء البشري على ‪ BIG-Bench‬المعيار (‪ .)2022 ،.Srivastava et al‬مزيد‬
‫من التدريب لـ ‪ PaLM‬على ‪ 38.5‬مليار رمز يحتوي على نتائج محتوى علمي ورياضييف ‬
‫‪ ،)2022,Lewkowycz et al.( ،Minerva‬وهو نموذج لغوي كبير يمكنه اإلجابة على ما‬
‫يقرب من ثلث مشاكل المستوى الجامعي التي تتطلب التفكير الكمي‪ ،‬مثل الفيزياء والكيمياء‬
‫وعلم األحياء واالقتصاد‪.‬‬

‫‪11.9.5‬‬
‫تم اختبار المحوالت مسبقًا على أنها مشفر فقط ‪( encoder-only‬على سبيل المثال‪،‬‬
‫‪ ،)BERT‬مشفر‪-‬مفكك شفرة ‪( encoder-decoder‬على سبيل المثال‪ ،)T5 ،‬ومفكك‬
‫شفرة فقط ‪( decoder-only‬على سبيل المثال‪ ،‬سلسلة ‪ .)GPT‬قد يتم تكييف النماذج سابقة‬
‫التدريب ألداء مهام مختلفة مع تحديث النموذج (على سبيل المثال‪ ،‬الضبط الدقيق ‪fine‬‬
‫‪ )tuning‬أو ال (على سبيل المثال‪ ،‬عدد قليل من اللقطات ‪ .)few shot‬تشير قابلية توسيع‬
‫المحوالت إلى أن األداء األفضل يستفيد من النماذج األكبر‪ ،‬والمزيد من بيانات التدريب‪،‬‬
‫والمزيد من حوسبة التدريب‪ .‬نظرًا ألن المحوالت تم تصميمها ألول مرة وفحصها مسبقًا للبيانات‬
‫النصية‪ ،‬فإن هذا القسم يميل قليالً نحو معالجة اللغة الطبيعية‪ .‬ومع ذلك‪ ،‬يمكن العثور على تلك‬
‫النماذج التي تمت مناقشتها أعالهيف نماذج أحدث عبر طرائق متعددة‪ .‬على سبيل المثال‪ ،‬تم‬
‫تمديد (‪ )2022,Hoffmann et al.( ،)1‬إلى ‪ ،)2022,Alayrac et al.( ،Flamingo‬وهو‬
‫نموذج لغة بصرية للتعلم قليل اللقطات؛ (‪ )2019,Radford et al.( ،GPT-2 )2‬ومحول‬
‫الرؤية يشفر النص والصوريف ‪( CLIP‬التدريب المسبق على اللغة المتباينة ‪Contrastive‬‬
‫‪ ،)2021 ،Radford et al.( )Language-Image Pre-training‬التي تم اعتماد صورتها‬
‫ونصها الحقًا‪.‬يف نظام تحويل النص إلى صورة ‪ .)2022 ،.Ramesh et al( DALL-E 2‬على‬
‫الرغم من عدم وجود دراسات منهجية حول قابلية التوسعيف المحوالتيف التدريب المسبق متعدد‬
‫الوسائط حتى اآلن‪ ،‬فإن نموذج تحويل النص إلى صورة حديث بالكامل‪Yu et ( ،Parti ،‬‬
‫‪355‬‬ ‫الفصل الحادي عشر‪ :‬آليات االنتباه والمحوالت‬

‫‪ ،)2022,al.‬يُظهر إمكانية التوسع عبر الطرائق‪ :‬يُظهر ‪ Parti‬أكبر أكثر قدرة على إنشاء صور عالية‬
‫الدقة وفهم نص غني بالمحتوى (الشكل ‪.)11.9.12‬‬

‫الشكل ‪ 11.9.12‬أمثلة للصور تم إنشاؤها من نفس النص بواسطة نموذج ‪ Parti‬بأحجام‬


‫متزايدة (‪( )20B ،3B ،750M ،350M‬أمثلة مأخوذة من ‪.))2022( Yu et al‬‬

‫‪11.9.6‬‬
‫‪ .1‬هل من الممكن ضبط ‪ T5‬باستخدام الدفعات الصغيرة يتكون من مهام مختلفة؟ لما‬
‫ولما ال؟ ماذا عن ‪GPT-2‬؟‬
‫‪ .2‬بالنظر إلى نموذج لغوي قوي‪ ،‬ما هي التطبيقات التي يمكنك التفكير فيها؟‬
‫‪ .3‬لنفترض أنه تمت مطالبتك بضبط نموذج لغة إلجراء تصنيف للنص عن طريق إضافة‬
‫طبقات إضافية‪ .‬أين ستضيفهم؟ لماذا ا؟‬
‫‪ .4‬ضعيف اعتبارك مشاكل التسلسل الى التسلسل (على سبيل المثال‪ ،‬الترجمة اآللية) حيث‬
‫يكون تسلسل اإلدخال متاحًا دائمًا خالل تنبؤ تسلسل الهدف‪ .‬ماذا يمكن أن تكون قيود‬
‫النمذجة باستخدام مفكك شفرة المحوالت فقط؟ لماذا؟‬
‫ئ‬

You might also like