การรวมกันและการดำเนินการ Convolutional เลื่อน "หน้าต่าง" ข้ามเทนเซอร์อินพุต ใช้tf.nn.conv2d
เป็นตัวอย่าง: หากอินพุทเทนเซอร์มี 4 มิติ: คอน [batch, height, width, channels]
โวลูชั่นจะทำงานบนหน้าต่าง 2 มิติบนheight, width
มิติข้อมูล
strides
กำหนดว่าหน้าต่างจะเลื่อนไปเท่าใดในแต่ละมิติ การใช้งานโดยทั่วไปจะตั้งค่าการก้าวแรก (ชุด) และครั้งสุดท้าย (ความลึก) เป็น 1
ลองใช้ตัวอย่างที่เป็นรูปธรรม: การรันคอนโวลูชั่น 2 มิติบนอิมเมจอินพุตสีเทาขนาด 32x32 ฉันพูดว่า greyscale เพราะภาพที่ป้อนมีความลึก = 1 ซึ่งช่วยให้มันดูเรียบง่าย ให้ภาพมีลักษณะดังนี้:
00 01 02 03 04 ...
10 11 12 13 14 ...
20 21 22 23 24 ...
30 31 32 33 34 ...
...
ลองเรียกใช้หน้าต่าง Convolution 2x2 ในตัวอย่างเดียว (batch size = 1) เราจะให้คอนโวลูชั่นมีความลึกของช่องสัญญาณเอาต์พุตที่ 8
shape=[1, 32, 32, 1]
อินพุตบิดมี
หากคุณระบุstrides=[1,1,1,1]
ด้วยpadding=SAME
ผลลัพธ์ของตัวกรองจะเป็น [1, 32, 32, 8]
ตัวกรองจะสร้างผลลัพธ์สำหรับ:
F(00 01
10 11)
แล้วสำหรับ:
F(01 02
11 12)
และอื่น ๆ จากนั้นจะย้ายไปที่แถวที่สองโดยคำนวณ:
F(10, 11
20, 21)
แล้วก็
F(11, 12
21, 22)
หากคุณระบุการก้าวเป็น [1, 2, 2, 1] มันจะไม่ทำหน้าต่างที่ซ้อนกัน มันจะคำนวณ:
F(00, 01
10, 11)
แล้ว
F(02, 03
12, 13)
การก้าวย่างดำเนินไปในทำนองเดียวกันสำหรับตัวดำเนินการร่วมกัน
คำถามที่ 2: ทำไมต้องก้าว [1, x, y, 1] สำหรับ Convnets
ชุดแรกคือชุด: โดยปกติคุณไม่ต้องการข้ามตัวอย่างในชุดงานของคุณหรือคุณไม่ควรรวมไว้ในตอนแรก :)
1 สุดท้ายคือความลึกของการแปลง: โดยปกติคุณไม่ต้องการข้ามอินพุตด้วยเหตุผลเดียวกัน
ตัวดำเนินการ Conv2d มีความกว้างมากขึ้นดังนั้นคุณสามารถสร้าง Convolutions ที่เลื่อนหน้าต่างไปตามมิติข้อมูลอื่น ๆ ได้ แต่นั่นไม่ใช่การใช้งานทั่วไปใน Convnets การใช้งานทั่วไปคือการใช้เชิงพื้นที่
เหตุใดจึงเปลี่ยนรูปร่างเป็น -1 -1 จึงเป็นตัวยึดตำแหน่งที่ระบุว่า "ปรับตามความจำเป็นเพื่อให้ตรงกับขนาดที่จำเป็นสำหรับเทนเซอร์ทั้งหมด" เป็นวิธีการทำให้รหัสไม่ขึ้นอยู่กับขนาดแบตช์อินพุตเพื่อให้คุณสามารถเปลี่ยนไปป์ไลน์ของคุณและไม่ต้องปรับขนาดแบทช์ทุกที่ในโค้ด