Lecture 02 · NN Fundamentals

المحاضرة 02 · أساسيات الشبكات العصبية

Grouped and depthwise convolution

الالتفاف المجمّع (grouped) والعمقي (depthwise)

Slides 19–20الشرائح 19–20 P1 MUST

One knob, g, decides how many input channels each filter is allowed to see. Turn it up and weights and MACs fall by exactly g. Turn it all the way up and you get depthwise convolution, the engine of MobileNet.

مقبض واحد، هو g، يحدد كم قناة دخل يُسمح لكل filter أن يراها. ارفعه فتنخفض الأوزان وMACs بمقدار g بالضبط. ارفعه إلى أقصاه فتحصل على depthwise convolution، وهو المحرّك الذي يقوم عليه MobileNet.

High exam riskاحتمال عالٍ في الامتحان

Expect a counting question: given ci, co, k and g, give the weight shape, the number of weights and the number of MACs. Expect the slide 20 question in some form: "is this reduction in weights really good?"

توقّع سؤال عدّ: تُعطى ci وco وk وg، ويُطلب منك شكل الأوزان وعددها وعدد MACs. وتوقّع سؤال الشريحة 20 بصيغة ما: "هل هذا التخفيض في عدد الأوزان جيد فعلاً؟"

Start from the standard convolution

لنبدأ من الالتفاف العادي

A standard convolution has weights W of shape (co, ci, kh, kw). Every one of the co filters spans all ci input channels, so every output channel mixes every input channel.

في convolution العادي تكون الأوزان W بالشكل (co, ci, kh, kw). كل واحد من الـ co filters يمتد على كل قنوات الدخل ci، فكل قناة خرج تخلط كل قنوات الدخل.

#weights = co · ci · kh · kw     MACs = #weights · ho · wo

Each weight is used once per output pixel, which is why MACs are the weight count times ho wo (for batch n = 1). Bias b has shape (co) in every variant on this page.

كل وزن يُستخدم مرة واحدة لكل بكسل خرج، ولهذا فإن MACs تساوي عدد الأوزان مضروباً في ho wo (عندما n = 1). أما bias b فشكله (co) في كل الأنواع المذكورة في هذه الصفحة.

Grouped convolution: g narrower convolutions side by side

الالتفاف المجمّع: g من الالتفافات الأضيق جنباً إلى جنب

Slide 19 calls it "a group of narrower convolutions". Split the ci input channels into g groups and the co output channels into g groups. Output group j only looks at input group j. Each filter now spans ci/g channels instead of ci.

الشريحة 19 تسمّيه "مجموعة من convolutions أضيق". قسّم قنوات الدخل ci إلى g مجموعات، وقنوات الخرج co إلى g مجموعات. مجموعة الخرج رقم j لا ترى إلا مجموعة الدخل رقم j. وبهذا يمتد كل filter على ci/g قناة بدلاً من ci.

W : (g · co/g, ci/g, kh, kw) = (co, ci/g, kh, kw)

Read the slide's shape carefully: g groups times co/g filters per group is still co filters in total. Only the depth of each filter shrinks. So the layer has g times fewer weights and g times fewer MACs, and the output shape (n, co, ho, wo) does not change.

اقرأ الشكل في الشريحة بعناية: g مجموعات ضرب co/g filters في كل مجموعة يساوي co filters في المجموع. الذي يصغر هو عمق كل filter فقط. إذن الطبقة فيها أوزان أقل بـ g مرة وMACs أقل بـ g مرة، وشكل الخرج (n, co, ho, wo) لا يتغير.

Both channel counts are split into g equal groups, so g must divide ci and g must divide co. With ci = 64, g = 3 is illegal. PyTorch raises an error for it.

بما أن عددي القنوات كليهما يُقسَّمان إلى g مجموعات متساوية، يجب أن يقسم g كلاً من ci وco. فإذا كان ci = 64 فإن g = 3 غير مسموح، وPyTorch يرفع خطأ في هذه الحالة.

STANDARD g = 1 GROUPED g = 2 DEPTHWISE g = 8 ci co 8 x 8 = 64 links 2 x (4 x 4) = 32 links 8 x 1 = 8 links every output sees every input nothing crosses the group wall no cross-channel mixing at all
Each line is one kh x kw kernel slice. With 8 channels: g = 1 has 64 slices, g = 2 has 32, depthwise (g = 8) has 8. The count of slices is exactly co · ci/g.
كل خط هو شريحة نواة واحدة بحجم kh x kw. مع 8 قنوات: g = 1 فيه 64 شريحة، وg = 2 فيه 32، وdepthwise (g = 8) فيه 8. عدد الشرائح يساوي بالضبط co · ci/g.

Depthwise: push g to the limit

Depthwise: دفع g إلى أقصاه

Slide 20: "independent filter for each channel: g = ci = co in grouped convolution". Each group now holds one input channel and one output channel, so each output channel is one kh x kw filter slid over exactly one input channel.

الشريحة 20: "filter مستقل لكل قناة: g = ci = co في grouped convolution". كل مجموعة الآن فيها قناة دخل واحدة وقناة خرج واحدة، فكل قناة خرج هي filter واحد بحجم kh x kw ينزلق على قناة دخل واحدة فقط.

W : (c, kh, kw)     #weights = c · kh · kw     MACs = c · kh · kw · ho · wo

Plug g = ci into the grouped formula and the ci cancels: co · (ci/ci) · kh kw = co kh kw. There is no ci factor left in a depthwise weight count.

عوّض g = ci في معادلة grouped فيُلغى ci: co · (ci/ci) · kh kw = co kh kw. أي أنه لا يبقى أي عامل ci في عدد أوزان depthwise.

Why depthwise is never used alone

لماذا لا يُستخدم depthwise وحده أبداً

A depthwise layer filters each channel spatially but never combines channels. Stack only depthwise layers and channel 5 can never learn anything from channel 6. The fix is a 1 x 1 pointwise convolution right after it: a standard conv with k = 1, weights (co, ci, 1, 1), that does nothing spatially and all the channel mixing. Depthwise followed by pointwise is the depthwise separable block (MobileNet).

طبقة depthwise تُرشّح كل قناة مكانياً لكنها لا تجمع القنوات أبداً. فلو كدّست طبقات depthwise فقط، لن تتعلم القناة 5 أي شيء من القناة 6. والحل هو 1 x 1 pointwise convolution بعدها مباشرة: conv عادي بـ k = 1 وأوزان (co, ci, 1, 1)، لا يفعل شيئاً مكانياً ويتولى كل خلط القنوات. وتتابع depthwise ثم pointwise هو كتلة depthwise separable (MobileNet).

separable / standard = cik2 + cicococik2 = 1co + 1k2

For k = 3 and large co the ratio is close to 1/9, so roughly 8 to 9 times cheaper. The same ratio holds for MACs, because every term gets multiplied by the same ho wo.

عندما k = 3 وco كبير تقترب النسبة من 1/9، أي أرخص بنحو 8 إلى 9 مرات. والنسبة نفسها تنطبق على MACs، لأن كل حد يُضرب في نفس ho wo.

Worked: one layer, five ways

مثال محلول: طبقة واحدة بخمس طرق

ci = co = 64, k = 3, output 56 x 56, so ho wo = 3,136 output positions. Weights only (bias is 64 in each single-conv row and 128 for the two-conv separable block).

ci = co = 64، وk = 3، والخرج 56 x 56، إذن ho wo = 3,136 موضع خرج. الأوزان فقط (bias يساوي 64 في كل صف فيه conv واحد، و128 لكتلة separable ذات الطبقتين).

Workedمثال محلول
positions = 56 x 56 = 3,136

standard  (g = 1)  W (64, 64, 3, 3)
  weights = 64 x 64 x 9          = 36,864
  MACs    = 36,864 x 3,136       = 115,605,504   (about 115.6 M)

grouped   (g = 2)  W (64, 32, 3, 3)
  weights = 64 x 32 x 9          = 18,432        (2x fewer)
  MACs    = 18,432 x 3,136       =  57,802,752

grouped   (g = 4)  W (64, 16, 3, 3)
  weights = 64 x 16 x 9          =  9,216        (4x fewer)
  MACs    =  9,216 x 3,136       =  28,901,376

depthwise (g = 64) W (64, 3, 3)
  weights = 64 x 9               =    576        (64x fewer)
  MACs    =    576 x 3,136       =   1,806,336

depthwise + 1x1 pointwise W (64, 64, 1, 1)
  weights = 576 + 64 x 64        =  4,672
  MACs    =  4,672 x 3,136       =  14,651,392

ratio  115,605,504 / 14,651,392  = 7.89
check  1/64 + 1/9 = 0.0156 + 0.1111 = 0.1267,  1/0.1267 = 7.89

The honest comparison is standard vs separable (7.9x), not standard vs depthwise alone (64x), because depthwise alone cannot mix channels and is not a replacement.

المقارنة الصادقة هي بين standard وseparable (7.9x)، لا بين standard وdepthwise وحده (64x)، لأن depthwise وحده لا يخلط القنوات فلا يصلح بديلاً.

LayerالطبقةW shapeشكل WWeightsالأوزانMACsvs standardمقارنة بالعادي
Standard, g = 1عادي، g = 1(64, 64, 3, 3)36,864115.6 M1x
Grouped, g = 2مجمّع، g = 2(64, 32, 3, 3)18,43257.8 M2x
Grouped, g = 4مجمّع، g = 4(64, 16, 3, 3)9,21628.9 M4x
Depthwise, g = 64Depthwise، g = 64(64, 3, 3)5761.8 M64x
Depthwise + 1 x 1Depthwise + 1 x 1(64, 3, 3) + (64, 64, 1, 1)4,67214.7 M7.9x

يلخّص الجدول الحالات الخمس على نفس الطبقة. لاحظ أن عمودي الأوزان وMACs يتناقصان بنفس النسبة دائماً، لأن MACs هي الأوزان مضروبة في 3,136.

Notice where the separable block's cost lives: 4,096 of its 4,672 weights (87.7 percent) are in the 1 x 1 pointwise layer, not the depthwise one.

لاحظ أين تكمن كلفة الكتلة separable: 4,096 من أصل 4,672 وزناً (87.7%) موجودة في طبقة 1 x 1 pointwise، وليس في طبقة depthwise.

"Is this reduction in weights really good?"

«هل هذا التخفيض في الأوزان جيد فعلاً؟»

The red question on slide 20 has a two-part answer.

سؤال الشريحة 20 المكتوب بالأحمر جوابه من جزأين.

What you lose in modelling

ما تخسره في قدرة النمذجة

Inside a group, no information crosses the group wall. Depthwise mixes zero channels. Capacity drops, so networks pair grouped layers with 1 x 1 convs (or a channel shuffle, as in ShuffleNet) to let information flow again.

داخل المجموعة لا تعبر أي معلومة جدار المجموعة، وdepthwise لا يخلط أي قناة. فتنخفض قدرة النموذج، ولذلك تُقرن الشبكات طبقات grouped بـ 1 x 1 convs (أو channel shuffle كما في ShuffleNet) لتعود المعلومات إلى التدفق.

What you lose on hardware

ما تخسره على العتاد

Fewer MACs does not mean proportionally lower latency. Standard 3 x 3 conv here does 576 MACs per output value; depthwise does 9, while still reading and writing the same 56 x 56 x 64 activation maps. Arithmetic intensity falls by 64x, so depthwise layers are typically memory-bound and underuse the compute units.

قلة MACs لا تعني انخفاضاً مماثلاً في latency. هنا ينفّذ 3 x 3 conv العادي 576 MACs لكل قيمة خرج، بينما ينفّذ depthwise 9 فقط، مع أنه يقرأ ويكتب نفس خرائط التنشيط 56 x 56 x 64. فتنخفض arithmetic intensity بمقدار 64x، ولذلك تكون طبقات depthwise عادةً memory-bound ولا تستغل وحدات الحساب جيداً.

This is a preview of Lecture 03: latency is roughly max(compute time, memory time), and depthwise cuts only the first term. A 7.9x MAC saving might buy far less than 7.9x in wall-clock time.

وهذا تمهيد للمحاضرة 03: latency تساوي تقريباً max(compute time, memory time)، وdepthwise يقلّص الحد الأول فقط. فتوفير 7.9x في MACs قد يعطيك أقل بكثير من 7.9x في الزمن الفعلي.

Trapفخ

Divide by g once, not twice. The slide writes (g · co/g, ci/g, kh, kw). The g · co/g is just co. Writing co/g · ci/g · k2 gives a g2 reduction, which is wrong: 64 x 64 x 9 at g = 4 is 9,216, not 2,304.

اقسم على g مرة واحدة، لا مرتين. الشريحة تكتب (g · co/g, ci/g, kh, kw)، وg · co/g ما هو إلا co. أما كتابة co/g · ci/g · k2 فتعطي تخفيضاً بمقدار g2، وهذا خطأ: 64 x 64 x 9 عند g = 4 يساوي 9,216 لا 2,304.

Depthwise has no ci in its count. It is c · kh · kw. Writing co · ci · k2 is a standard conv.

عدد أوزان depthwise لا يحتوي ci. هو c · kh · kw. أما co · ci · k2 فهو conv عادي.

g must divide both ci and co, and grouping never changes the output shape.

يجب أن يقسم g كلاً من ci وco، والتجميع لا يغيّر شكل الخرج أبداً.

Memory hookمفتاح للحفظ

g shrinks the depth of each filter, not the number of filters. Depthwise filters space, pointwise mixes channels, and together they cost about 1/k2 of a standard conv.

g يقلّص عمق كل filter، لا عدد الـ filters. depthwise يُرشّح المكان، وpointwise يخلط القنوات، ومعاً يكلّفان نحو 1/k2 من conv العادي.

Check yourself

اختبر نفسك

A conv layer has ci = 128, co = 256, k = 3, g = 8. How many weights (excluding bias)?

طبقة conv فيها ci = 128، وco = 256، وk = 3، وg = 8. كم عدد الأوزان (بدون bias)؟

W is (256, 128/8, 3, 3) = (256, 16, 3, 3), so 256 x 16 x 9 = 36,864, exactly 1/8 of the standard 294,912 (option A). Option C divides by g twice (256/8 x 16 x 9). Option D is a depthwise-style count that ignores co.

W شكله (256, 128/8, 3, 3) = (256, 16, 3, 3)، إذن 256 x 16 x 9 = 36,864، أي 1/8 بالضبط من 294,912 العادي (الخيار A). الخيار C يقسم على g مرتين (256/8 x 16 x 9). والخيار D عدّ بأسلوب depthwise يتجاهل co.

A depthwise 5 x 5 convolution on 32 channels produces a 28 x 28 output. How many weights and MACs?

depthwise convolution بحجم 5 x 5 على 32 قناة يُنتج خرجاً 28 x 28. كم عدد الأوزان وMACs؟

Depthwise weights are c · k2 = 32 x 25 = 800 (no ci factor). Each is used at every output position: 800 x 784 = 627,200 MACs. Option A is the standard conv count 32 x 32 x 25. Option B forgets that MACs scale with ho wo.

أوزان depthwise هي c · k2 = 32 x 25 = 800 (بدون عامل ci). وكل وزن يُستخدم في كل موضع خرج: 800 x 784 = 627,200 MACs. الخيار A هو عدّ conv العادي 32 x 32 x 25. والخيار B ينسى أن MACs تتناسب مع ho wo.

Which grouped convolution configuration is invalid?

أي إعداد من إعدادات grouped convolution غير صالح؟

g must divide both channel counts. 3 divides 48 but not 64, so A cannot split the outputs into equal groups. B is legal (each input channel feeds 2 output channels, a depthwise multiplier of 2). C is plain depthwise. D gives W = (64, 8, k, k).

يجب أن يقسم g عددي القنوات كليهما. الرقم 3 يقسم 48 لكنه لا يقسم 64، فالخيار A لا يمكنه تقسيم قنوات الخرج إلى مجموعات متساوية. الخيار B صالح (كل قناة دخل تغذّي قناتي خرج، أي depthwise multiplier يساوي 2). الخيار C هو depthwise عادي. والخيار D يعطي W = (64, 8, k, k).

Replacing a 3 x 3 standard conv (ci = co = 256) by depthwise + 1 x 1 pointwise cuts MACs by about 8.7x, but measured latency on a mobile GPU drops only 3x. The best explanation:

استبدال 3 x 3 conv عادي (ci = co = 256) بـ depthwise ثم 1 x 1 pointwise يقلّص MACs بنحو 8.7x، لكن latency المقاسة على GPU لهاتف تنخفض 3x فقط. ما أفضل تفسير؟

Ratio check: 1/256 + 1/9 = 0.115, so 8.7x fewer MACs is right. But depthwise does only 9 MACs per output value while moving the same activation maps, so data movement, not compute, sets its runtime. Latency is about max(compute, memory), and only the compute term shrank.

تحقق من النسبة: 1/256 + 1/9 = 0.115، إذن 8.7x أقل في MACs صحيح. لكن depthwise ينفّذ 9 MACs فقط لكل قيمة خرج بينما ينقل نفس خرائط التنشيط، فحركة البيانات وليس الحساب هي التي تحدد زمنه. وlatency تساوي تقريباً max(compute, memory)، والذي تقلّص هو حد الحساب فقط.