ใครช่วยอธิบายให้ชัดเจนถึงความแตกต่างระหว่าง 1D, 2D และ 3D Convolutions ใน Convolutional Neural Network (ในการเรียนรู้เชิงลึก) ด้วยการใช้ตัวอย่าง
ใครช่วยอธิบายให้ชัดเจนถึงความแตกต่างระหว่าง 1D, 2D และ 3D Convolutions ใน Convolutional Neural Network (ในการเรียนรู้เชิงลึก) ด้วยการใช้ตัวอย่าง
คำตอบ:
ฉันต้องการที่จะอธิบายกับภาพจากC3D
สรุปทิศทางการแปลงและรูปร่างเอาต์พุตเป็นสิ่งสำคัญ!
↑↑↑↑↑ 1D Convolutions - พื้นฐาน ↑↑↑↑↑
import tensorflow as tf
import numpy as np
sess = tf.Session()
ones_1d = np.ones(5)
weight_1d = np.ones(3)
strides_1d = 1
in_1d = tf.constant(ones_1d, dtype=tf.float32)
filter_1d = tf.constant(weight_1d, dtype=tf.float32)
in_width = int(in_1d.shape[0])
filter_width = int(filter_1d.shape[0])
input_1d = tf.reshape(in_1d, [1, in_width, 1])
kernel_1d = tf.reshape(filter_1d, [filter_width, 1, 1])
output_1d = tf.squeeze(tf.nn.conv1d(input_1d, kernel_1d, strides_1d, padding='SAME'))
print sess.run(output_1d)
↑↑↑↑↑การแปลง 2D - พื้นฐาน ↑↑↑↑↑
ones_2d = np.ones((5,5))
weight_2d = np.ones((3,3))
strides_2d = [1, 1, 1, 1]
in_2d = tf.constant(ones_2d, dtype=tf.float32)
filter_2d = tf.constant(weight_2d, dtype=tf.float32)
in_width = int(in_2d.shape[0])
in_height = int(in_2d.shape[1])
filter_width = int(filter_2d.shape[0])
filter_height = int(filter_2d.shape[1])
input_2d = tf.reshape(in_2d, [1, in_height, in_width, 1])
kernel_2d = tf.reshape(filter_2d, [filter_height, filter_width, 1, 1])
output_2d = tf.squeeze(tf.nn.conv2d(input_2d, kernel_2d, strides=strides_2d, padding='SAME'))
print sess.run(output_2d)
↑↑↑↑↑การแปลง3D - พื้นฐาน ↑↑↑↑↑
ones_3d = np.ones((5,5,5))
weight_3d = np.ones((3,3,3))
strides_3d = [1, 1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_3d = tf.constant(weight_3d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
in_depth = int(in_3d.shape[2])
filter_width = int(filter_3d.shape[0])
filter_height = int(filter_3d.shape[1])
filter_depth = int(filter_3d.shape[2])
input_3d = tf.reshape(in_3d, [1, in_depth, in_height, in_width, 1])
kernel_3d = tf.reshape(filter_3d, [filter_depth, filter_height, filter_width, 1, 1])
output_3d = tf.squeeze(tf.nn.conv3d(input_3d, kernel_3d, strides=strides_3d, padding='SAME'))
print sess.run(output_3d)
↑↑↑↑↑การแปลง 2D พร้อมอินพุต 3D - LeNet, VGG, ... , ↑↑↑↑↑
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
ones_3d = np.ones((5,5,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae with in_channels
weight_3d = np.ones((3,3,in_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_3d = tf.constant(weight_3d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_3d.shape[0])
filter_height = int(filter_3d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_3d = tf.reshape(filter_3d, [filter_height, filter_width, in_channels, 1])
output_2d = tf.squeeze(tf.nn.conv2d(input_3d, kernel_3d, strides=strides_2d, padding='SAME'))
print sess.run(output_2d)
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
out_channels = 64 # 128, 256, ...
ones_3d = np.ones((5,5,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae x number of filters = 4D
weight_4d = np.ones((3,3,in_channels, out_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_4d = tf.constant(weight_4d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_4d.shape[0])
filter_height = int(filter_4d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_4d = tf.reshape(filter_4d, [filter_height, filter_width, in_channels, out_channels])
#output stacked shape is 3D = 2D x N matrix
output_3d = tf.nn.conv2d(input_3d, kernel_4d, strides=strides_2d, padding='SAME')
print sess.run(output_3d)
↑↑↑↑↑ โบนัส 1x1 Conv. ใน CNN - GoogLeNet, ... , ↑↑↑↑↑
in_channels = 32 # 3 for RGB, 32, 64, 128, ...
out_channels = 64 # 128, 256, ...
ones_3d = np.ones((1,1,in_channels)) # input is 3d, in_channels = 32
# filter must have 3d-shpae x number of filters = 4D
weight_4d = np.ones((3,3,in_channels, out_channels))
strides_2d = [1, 1, 1, 1]
in_3d = tf.constant(ones_3d, dtype=tf.float32)
filter_4d = tf.constant(weight_4d, dtype=tf.float32)
in_width = int(in_3d.shape[0])
in_height = int(in_3d.shape[1])
filter_width = int(filter_4d.shape[0])
filter_height = int(filter_4d.shape[1])
input_3d = tf.reshape(in_3d, [1, in_height, in_width, in_channels])
kernel_4d = tf.reshape(filter_4d, [filter_height, filter_width, in_channels, out_channels])
#output stacked shape is 3D = 2D x N matrix
output_3d = tf.nn.conv2d(input_3d, kernel_4d, strides=strides_2d, padding='SAME')
print sess.run(output_3d)
- ลิงค์ต้นฉบับ: ลิงค์
- ผู้แต่ง: Martin Görner
- Twitter: @martin_gorner
- Google +: plus.google.com/+MartinGorne
↑↑↑↑↑ 1D Convolutions พร้อมอินพุต 1D ↑↑↑↑↑
↑↑↑↑↑ 1D Convolutions พร้อมอินพุต 2D ↑↑↑↑↑
in_channels = 32 # 3, 32, 64, 128, ...
out_channels = 64 # 3, 32, 64, 128, ...
ones_4d = np.ones((5,5,5,in_channels))
weight_5d = np.ones((3,3,3,in_channels,out_channels))
strides_3d = [1, 1, 1, 1, 1]
in_4d = tf.constant(ones_4d, dtype=tf.float32)
filter_5d = tf.constant(weight_5d, dtype=tf.float32)
in_width = int(in_4d.shape[0])
in_height = int(in_4d.shape[1])
in_depth = int(in_4d.shape[2])
filter_width = int(filter_5d.shape[0])
filter_height = int(filter_5d.shape[1])
filter_depth = int(filter_5d.shape[2])
input_4d = tf.reshape(in_4d, [1, in_depth, in_height, in_width, in_channels])
kernel_5d = tf.reshape(filter_5d, [filter_depth, filter_height, filter_width, in_channels, out_channels])
output_4d = tf.nn.conv3d(input_4d, kernel_5d, strides=strides_3d, padding='SAME')
print sess.run(output_4d)
sess.close()
1
แล้ว→1+stride
สำหรับแถว Convolution เองก็เปลี่ยนไม่แปรผันแล้วทำไมทิศทางของ Convolution จึงมีความสำคัญ?
ตามคำตอบจาก @runhani ฉันกำลังเพิ่มรายละเอียดอีกเล็กน้อยเพื่อให้คำอธิบายชัดเจนขึ้นและจะพยายามอธิบายสิ่งนี้ให้มากขึ้น (และแน่นอนว่ามี exmaples จาก TF1 และ TF2)
หนึ่งในบิตเพิ่มเติมหลักที่ฉันรวมไว้คือ
tf.Variable
นี่คือวิธีที่คุณสามารถทำ Convolution 1D โดยใช้ TF 1 และ TF 2
และเพื่อให้เฉพาะเจาะจงข้อมูลของฉันมีรูปร่างดังต่อไปนี้
[batch size, width, in channels]
(เช่น1, 5, 1
)[width, in channels, out channels]
(เช่น5, 1, 4
)[batch size, width, out_channels]
(เช่น1, 5, 4
)import tensorflow as tf
import numpy as np
inp = tf.placeholder(shape=[None, 5, 1], dtype=tf.float32)
kernel = tf.Variable(tf.initializers.glorot_uniform()([5, 1, 4]), dtype=tf.float32)
out = tf.nn.conv1d(inp, kernel, stride=1, padding='SAME')
with tf.Session() as sess:
tf.global_variables_initializer().run()
print(sess.run(out, feed_dict={inp: np.array([[[0],[1],[2],[3],[4]],[[5],[4],[3],[2],[1]]])}))
import tensorflow as tf
import numpy as np
inp = np.array([[[0],[1],[2],[3],[4]],[[5],[4],[3],[2],[1]]]).astype(np.float32)
kernel = tf.Variable(tf.initializers.glorot_uniform()([5, 1, 4]), dtype=tf.float32)
out = tf.nn.conv1d(inp, kernel, stride=1, padding='SAME')
print(out)
มันทำงานน้อยลงกับ TF2 เนื่องจาก TF2 ไม่ต้องการSession
และvariable_initializer
ตัวอย่างเช่น
ลองมาทำความเข้าใจว่าสิ่งนี้กำลังทำอะไรโดยใช้ตัวอย่างการปรับสัญญาณให้เรียบ ทางด้านซ้ายคุณจะได้รับต้นฉบับและทางด้านขวาคุณจะได้รับเอาต์พุตของ Convolution 1D ซึ่งมีช่องสัญญาณออก 3 ช่อง
ช่องสัญญาณหลายช่องเป็นการนำเสนอคุณลักษณะหลายอย่างของอินพุต ในตัวอย่างนี้คุณมีตัวแทนสามแบบที่ได้รับจากตัวกรองที่แตกต่างกันสามตัว ช่องแรกคือฟิลเตอร์ปรับผิวเรียบที่มีน้ำหนักเท่ากัน อย่างที่สองคือตัวกรองที่ให้น้ำหนักตรงกลางของตัวกรองมากกว่าขอบเขต ตัวกรองสุดท้ายจะตรงกันข้ามกับตัวกรองที่สอง คุณจึงสามารถดูได้ว่าฟิลเตอร์ต่างๆเหล่านี้ให้เอฟเฟกต์ที่แตกต่างกันอย่างไร
ใช้ Convolution 1D สำหรับงานจำแนกประโยคได้สำเร็จ
ปิดการแปลงเป็น 2D หากคุณเป็นคนที่มีการเรียนรู้เชิงลึกโอกาสที่คุณจะไม่เจอ 2D Convolution ก็คือ…เป็นศูนย์ ใช้ใน CNN สำหรับการจำแนกภาพการตรวจจับวัตถุ ฯลฯ รวมทั้งในปัญหา NLP ที่เกี่ยวข้องกับภาพ (เช่นการสร้างคำบรรยายภาพ)
ลองดูตัวอย่างฉันได้รับเคอร์เนล Convolution พร้อมตัวกรองต่อไปนี้ที่นี่
และเพื่อให้เฉพาะเจาะจงข้อมูลของฉันมีรูปร่างดังต่อไปนี้
[batch_size, height, width, 1]
(เช่น1, 340, 371, 1
)[height, width, in channels, out channels]
(เช่น3, 3, 1, 3
)[batch_size, height, width, out_channels]
(เช่น1, 340, 371, 3
)import tensorflow as tf
import numpy as np
from PIL import Image
im = np.array(Image.open(<some image>).convert('L'))#/255.0
kernel_init = np.array(
[
[[[-1, 1.0/9, 0]],[[-1, 1.0/9, -1]],[[-1, 1.0/9, 0]]],
[[[-1, 1.0/9, -1]],[[8, 1.0/9,5]],[[-1, 1.0/9,-1]]],
[[[-1, 1.0/9,0]],[[-1, 1.0/9,-1]],[[-1, 1.0/9, 0]]]
])
inp = tf.placeholder(shape=[None, image_height, image_width, 1], dtype=tf.float32)
kernel = tf.Variable(kernel_init, dtype=tf.float32)
out = tf.nn.conv2d(inp, kernel, strides=[1,1,1,1], padding='SAME')
with tf.Session() as sess:
tf.global_variables_initializer().run()
res = sess.run(out, feed_dict={inp: np.expand_dims(np.expand_dims(im,0),-1)})
import tensorflow as tf
import numpy as np
from PIL import Image
im = np.array(Image.open(<some image>).convert('L'))#/255.0
x = np.expand_dims(np.expand_dims(im,0),-1)
kernel_init = np.array(
[
[[[-1, 1.0/9, 0]],[[-1, 1.0/9, -1]],[[-1, 1.0/9, 0]]],
[[[-1, 1.0/9, -1]],[[8, 1.0/9,5]],[[-1, 1.0/9,-1]]],
[[[-1, 1.0/9,0]],[[-1, 1.0/9,-1]],[[-1, 1.0/9, 0]]]
])
kernel = tf.Variable(kernel_init, dtype=tf.float32)
out = tf.nn.conv2d(x, kernel, strides=[1,1,1,1], padding='SAME')
ที่นี่คุณสามารถดูผลลัพธ์ที่ผลิตโดยโค้ดด้านบน ภาพแรกเป็นภาพต้นฉบับและเป็นไปตามเข็มนาฬิกาคุณมีเอาต์พุตของตัวกรองที่ 1 ตัวกรองที่ 2 และตัวกรอง 3 ตัว
ในบริบทถ้าการแปลงแบบ 2 มิติจะง่ายกว่ามากที่จะเข้าใจว่าช่องต่างๆเหล่านี้หมายถึงอะไร สมมติว่าคุณกำลังจดจำใบหน้า คุณสามารถนึกถึง (นี่คือการทำให้เข้าใจง่ายอย่างไม่สมจริง แต่ได้ประเด็นไป) ฟิลเตอร์แต่ละตัวแสดงถึงตาปากจมูก ฯลฯ ดังนั้นแผนที่คุณลักษณะแต่ละรายการจะเป็นตัวแทนแบบไบนารีว่ามีคุณลักษณะนั้นอยู่ในภาพที่คุณระบุหรือไม่ . ฉันไม่คิดว่าฉันจำเป็นต้องเน้นว่ารูปแบบการจดจำใบหน้าเหล่านี้เป็นคุณสมบัติที่มีค่ามาก ข้อมูลเพิ่มเติมในเรื่องนี้บทความ
นี่คือภาพประกอบของสิ่งที่ฉันพยายามจะพูดให้ชัดเจน
2D Convolution เป็นที่แพร่หลายมากในขอบเขตของการเรียนรู้เชิงลึก
CNN (Convolution Neural Networks) ใช้การดำเนินการ Convolution แบบ 2 มิติสำหรับงานการมองเห็นของคอมพิวเตอร์เกือบทั้งหมด (เช่นการจำแนกภาพการตรวจจับวัตถุการจัดประเภทวิดีโอ)
ตอนนี้การอธิบายสิ่งที่เกิดขึ้นเป็นเรื่องยากขึ้นเรื่อย ๆ เมื่อจำนวนมิติเพิ่มขึ้น แต่ด้วยความเข้าใจเป็นอย่างดีเกี่ยวกับวิธีการทำงานของคอนโวลูชั่น 1D และ 2D จึงเป็นการตรงไปตรงมามากที่จะสรุปความเข้าใจนั้นกับการแปลงภาพ 3 มิติ นี่ไปเลย
และเพื่อให้เฉพาะเจาะจงข้อมูลของฉันมีรูปร่างดังต่อไปนี้
[batch size, height, width, depth, in channels]
(เช่น1, 200, 200, 200, 1
)[height, width, depth, in channels, out channels]
(เช่น5, 5, 5, 1, 3
)[batch size, width, height, width, depth, out_channels]
(เช่น1, 200, 200, 2000, 3
)import tensorflow as tf
import numpy as np
tf.reset_default_graph()
inp = tf.placeholder(shape=[None, 200, 200, 200, 1], dtype=tf.float32)
kernel = tf.Variable(tf.initializers.glorot_uniform()([5,5,5,1,3]), dtype=tf.float32)
out = tf.nn.conv3d(inp, kernel, strides=[1,1,1,1,1], padding='SAME')
with tf.Session() as sess:
tf.global_variables_initializer().run()
res = sess.run(out, feed_dict={inp: np.random.normal(size=(1,200,200,200,1))})
import tensorflow as tf
import numpy as np
x = np.random.normal(size=(1,200,200,200,1))
kernel = tf.Variable(tf.initializers.glorot_uniform()([5,5,5,1,3]), dtype=tf.float32)
out = tf.nn.conv3d(x, kernel, strides=[1,1,1,1,1], padding='SAME')
3D Convolution ถูกนำมาใช้ในการพัฒนาแอปพลิเคชันการเรียนรู้ของเครื่องที่เกี่ยวข้องกับข้อมูล LIDAR (Light Detection and Ranging) ซึ่งมีลักษณะเป็น 3 มิติ
ได้เลยคุณใกล้จะถึงแล้ว ดังนั้นถือไว้ มาดูกันว่าการก้าวย่างและช่องว่างภายในคืออะไร พวกเขาค่อนข้างเข้าใจง่ายถ้าคุณคิดถึงพวกเขา
หากคุณก้าวข้ามทางเดินคุณจะไปถึงที่นั่นได้เร็วขึ้นในจำนวนก้าวที่น้อยลง แต่ก็หมายความว่าคุณสังเกตรอบข้างน้อยกว่าตอนที่คุณเดินข้ามห้อง มาเสริมความเข้าใจด้วยภาพสวย ๆ กันเถอะ! มาทำความเข้าใจกับสิ่งเหล่านี้ผ่าน 2D Convolution
tf.nn.conv2d
ตัวอย่างเช่นเมื่อคุณใช้คุณต้องตั้งค่าเป็นเวกเตอร์ของ 4 องค์ประกอบ ไม่มีเหตุผลที่จะต้องกลัวเรื่องนี้ มันมีขั้นตอนตามลำดับต่อไปนี้
การแปลง 2D - [batch stride, height stride, width stride, channel stride]
. ที่นี่การก้าวเดินแบบเป็นกลุ่มและการก้าวข้ามช่องที่คุณตั้งไว้เป็นหนึ่ง (ฉันใช้โมเดลการเรียนรู้เชิงลึกมา 5 ปีแล้วและไม่ต้องตั้งค่าเป็นอะไรเลยนอกจากแบบเดียว) ซึ่งจะทำให้คุณมีก้าวย่างเพียง 2 ก้าวเท่านั้น
การแปลง 3D - [batch stride, height stride, width stride, depth stride, channel stride]
. ที่นี่คุณกังวลเกี่ยวกับความสูง / ความกว้าง / ความลึกเท่านั้น
ตอนนี้คุณสังเกตเห็นว่าไม่ว่าการก้าวของคุณจะเล็กแค่ไหน (กล่าวคือ 1) จะมีการลดขนาดที่หลีกเลี่ยงไม่ได้เกิดขึ้นระหว่างการชัก (เช่นความกว้างคือ 3 หลังจากที่ทำให้ภาพกว้าง 4 หน่วย) นี่เป็นสิ่งที่ไม่พึงปรารถนาโดยเฉพาะอย่างยิ่งเมื่อสร้างโครงข่ายประสาทเทียมแบบลึก นี่คือจุดที่มีช่องว่างในการช่วยเหลือ ช่องว่างภายในที่ใช้บ่อยที่สุดมีสองประเภท
SAME
และ VALID
ด้านล่างคุณสามารถเห็นความแตกต่าง
คำพูดสุดท้าย : ถ้าคุณอยากรู้มากคุณอาจสงสัย เราเพิ่งทิ้งระเบิดในการลดขนาดอัตโนมัติทั้งหมดและตอนนี้กำลังพูดถึงการมีความก้าวหน้าที่แตกต่างกัน แต่สิ่งที่ดีที่สุดในการก้าวย่างคือคุณควบคุมได้ว่าจะลดขนาดเมื่อใดและอย่างไร
CNN 1D, 2D หรือ 3D หมายถึงทิศทาง Convolution แทนที่จะเป็นมิติข้อมูลอินพุตหรือตัวกรอง
สำหรับอินพุต 1 ช่อง CNN2D เท่ากับ CNN1D คือความยาวเคอร์เนล = ความยาวอินพุต (ทิศทาง 1 Conv.)
โดยสรุปใน 1D CNN เคอร์เนลจะเคลื่อนที่ไปใน 1 ทิศทาง ข้อมูลอินพุตและเอาต์พุตของ 1D CNN เป็น 2 มิติ ส่วนใหญ่ใช้กับข้อมูลอนุกรมเวลา
ใน 2D CNN เคอร์เนลจะเคลื่อนที่ใน 2 ทิศทาง ข้อมูลอินพุตและเอาต์พุตของ 2D CNN เป็น 3 มิติ ส่วนใหญ่ใช้กับข้อมูลรูปภาพ
ใน 3D CNN เคอร์เนลจะเคลื่อนที่ใน 3 ทิศทาง ข้อมูลอินพุตและเอาต์พุตของ 3D CNN เป็น 4 มิติ ส่วนใหญ่ใช้กับข้อมูลภาพ 3 มิติ (MRI, CT Scans)
สามารถดูรายละเอียดเพิ่มเติมได้ที่นี่: https://medium.com/@xzz201920/conv1d-conv2d-and-conv3d-8a59182c4d6