Convnets, การบีบ, Xception พร้อม Keras และ TPU

1. ภาพรวม

ในแล็บนี้ คุณจะได้เรียนรู้เกี่ยวกับสถาปัตยกรรม Convolutional สมัยใหม่ และใช้ความรู้ของคุณเพื่อใช้ ConvNet ที่เรียบง่ายแต่มีประสิทธิภาพที่เรียกว่า "SqueezeNet"

แล็บนี้มีคำอธิบายเชิงทฤษฎีที่จำเป็นเกี่ยวกับเครือข่ายประสาทแบบคอนโวลูชัน และเป็นจุดเริ่มต้นที่ดีสำหรับนักพัฒนาซอฟต์แวร์ที่กำลังเรียนรู้เกี่ยวกับดีปเลิร์นนิง

แล็บนี้เป็นส่วนที่ 4 ของชุด "Keras บน TPU" คุณจะทำตามลำดับต่อไปนี้หรือจะทำแยกกันก็ได้

ca8cc21f6838eccc.png

สิ่งที่คุณจะได้เรียนรู้

  • หากต้องการเชี่ยวชาญสไตล์ฟังก์ชันของ Keras
  • วิธีสร้างโมเดลโดยใช้สถาปัตยกรรม SqueezeNet
  • หากต้องการใช้ TPU เพื่อฝึกโมเดลอย่างรวดเร็วและทำซ้ำในสถาปัตยกรรม
  • วิธีใช้การเพิ่มข้อมูลด้วย tf.data.dataset
  • วิธีปรับแต่งโมเดลขนาดใหญ่ที่ฝึกไว้ล่วงหน้า (Xception) บน TPU

ความคิดเห็น

หากพบสิ่งผิดปกติในโค้ดแล็บนี้ โปรดแจ้งให้เราทราบ คุณแสดงความคิดเห็นได้ผ่านปัญหาใน GitHub [feedback link]

2. คู่มือเริ่มต้นฉบับย่อของ Google Colaboratory

โดยแล็บนี้ใช้ Google Collaboratory และคุณไม่จำเป็นต้องตั้งค่าใดๆ Colaboratory เป็นแพลตฟอร์มสมุดบันทึกออนไลน์เพื่อการศึกษา โดยมีหลักสูตรการฝึกอบรม CPU, GPU และ TPU ฟรี

688858c21e3beff2.png

คุณสามารถเปิด Notebook ตัวอย่างนี้และเรียกใช้ 2-3 เซลล์เพื่อทำความคุ้นเคยกับ Colaboratory

c3df49e90e5a654f.png Welcome to Colab.ipynb

เลือกแบ็กเอนด์ TPU

8832c6208c99687d.png

ในเมนู Colab ให้เลือกรันไทม์ > เปลี่ยนประเภทรันไทม์ แล้วเลือก TPU ในโค้ดแล็บนี้ คุณจะได้ใช้ TPU (Tensor Processing Unit) ที่มีประสิทธิภาพซึ่งได้รับการสนับสนุนสำหรับการฝึกที่เร่งด้วยฮาร์ดแวร์ การเชื่อมต่อกับรันไทม์จะเกิดขึ้นโดยอัตโนมัติเมื่อมีการดำเนินการครั้งแรก หรือคุณจะใช้ปุ่ม "เชื่อมต่อ" ที่มุมขวาบนก็ได้

การดำเนินการ Notebook

76d05caa8b4db6da.png

เรียกใช้เซลล์ทีละเซลล์โดยคลิกเซลล์และใช้ Shift-ENTER นอกจากนี้ คุณยังเรียกใช้ทั้งสมุดบันทึกได้ด้วยรันไทม์ > เรียกใช้ทั้งหมด

สารบัญ

429f106990037ec4.png

Notebook ทุกรายการมีสารบัญ คุณเปิดได้โดยใช้ลูกศรสีดำทางด้านซ้าย

เซลล์ที่ซ่อนอยู่

edc3dba45d26f12a.png

บางเซลล์จะแสดงเฉพาะชื่อ ฟีเจอร์นี้เป็นฟีเจอร์สมุดบันทึกเฉพาะของ Colab คุณดับเบิลคลิกที่ไฟล์เพื่อดูโค้ดภายในได้ แต่โดยปกติแล้วโค้ดจะไม่น่าสนใจนัก โดยปกติจะเป็นฟังก์ชันการสนับสนุนหรือการแสดงภาพ คุณยังคงต้องเรียกใช้เซลล์เหล่านี้เพื่อให้ฟังก์ชันภายในได้รับการกำหนด

การตรวจสอบสิทธิ์

cdd4b41413100543.png

Colab สามารถเข้าถึง Bucket ของ Google Cloud Storage ส่วนตัวได้หากคุณตรวจสอบสิทธิ์ด้วยบัญชีที่ได้รับอนุญาต ข้อมูลโค้ดด้านบนจะทริกเกอร์กระบวนการตรวจสอบสิทธิ์

3. [INFO] Tensor Processing Unit (TPU) คืออะไร

โดยสรุป

f88cf6facfc70166.png

โค้ดสำหรับการฝึกโมเดลใน TPU ใน Keras (และใช้ GPU หรือ CPU แทนหากไม่มี TPU)

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

วันนี้เราจะใช้ TPU เพื่อสร้างและเพิ่มประสิทธิภาพเครื่องมือแยกประเภทดอกไม้ด้วยความเร็วแบบอินเทอร์แอกทีฟ (นาทีต่อการเรียกใช้การฝึก)

688858c21e3beff2.png

ทำไมต้อง TPU

GPU สมัยใหม่ได้รับการจัดระเบียบโดยมี "แกน" ที่ตั้งโปรแกรมได้ ซึ่งเป็นสถาปัตยกรรมที่ยืดหยุ่นมากที่ช่วยให้ GPU สามารถจัดการงานต่างๆ ได้ เช่น การแสดงผล 3 มิติ ดีปเลิร์นนิง การจำลองทางกายภาพ ฯลฯ ในทางกลับกัน TPU จะจับคู่โปรเซสเซอร์เวกเตอร์แบบคลาสสิกกับหน่วยคูณเมทริกซ์เฉพาะ และทำงานได้ดีในทุกงานที่การคูณเมทริกซ์ขนาดใหญ่มีบทบาทสำคัญ เช่น โครงข่ายประสาทเทียม

8eb3e718b8e2ed08.png

ภาพประกอบ: เลเยอร์โครงข่ายประสาทแบบหนาแน่นเป็นการคูณเมทริกซ์ โดยมีการประมวลผลรูปภาพ 8 รูปพร้อมกันผ่านโครงข่ายประสาท โปรดทำการคูณ 1 แถว x คอลัมน์เพื่อยืนยันว่าฟีเจอร์นี้จะหาผลรวมแบบถ่วงน้ำหนักของค่าพิกเซลทั้งหมดของรูปภาพ เลเยอร์ Convolutional สามารถแสดงเป็นการคูณเมทริกซ์ได้เช่นกัน แม้ว่าจะซับซ้อนกว่าเล็กน้อย ( คำอธิบายที่นี่ในส่วนที่ 1)

ฮาร์ดแวร์

MXU และ VPU

แกน TPU v2 ประกอบด้วยหน่วยคูณเมทริกซ์ (MXU) ซึ่งทำการคูณเมทริกซ์ และหน่วยประมวลผลเวกเตอร์ (VPU) สำหรับงานอื่นๆ ทั้งหมด เช่น การเปิดใช้งาน, Softmax เป็นต้น โดย VPU จะจัดการการคำนวณ float32 และ int32 ในทางกลับกัน MXU จะทำงานในรูปแบบจุดลอยตัวแบบผสมความแม่นยำ 16-32 บิต

7d68944718f76b18.png

จุดลอยแบบความแม่นยำผสมและ bfloat16

MXU จะคำนวณการคูณเมทริกซ์โดยใช้อินพุต bfloat16 และเอาต์พุต float32 การสะสมระดับกลางจะดำเนินการด้วยความแม่นยำของ float32

19c5fc432840c714.png

โดยปกติแล้วการฝึกโครงข่ายประสาทเทียมจะทนทานต่อสัญญาณรบกวนที่เกิดจากความแม่นยำของจำนวนทศนิยมที่ลดลง ในบางกรณี สัญญาณรบกวนอาจช่วยให้เครื่องมือเพิ่มประสิทธิภาพบรรลุเป้าหมายได้ โดยปกติแล้ว ความแม่นยำแบบจุดลอยตัว 16 บิตจะใช้เพื่อเร่งการคำนวณ แต่รูปแบบ float16 และ float32 มีช่วงที่แตกต่างกันมาก การลดความแม่นยำจาก float32 เป็น float16 มักทำให้เกิดการล้นและอันเดอร์โฟลว์ แม้จะมีโซลูชันอยู่ แต่โดยปกติแล้วจะต้องมีการดำเนินการเพิ่มเติมเพื่อให้ float16 ทำงานได้

ด้วยเหตุนี้ Google จึงเปิดตัวรูปแบบ bfloat16 ใน TPU ซึ่งเป็น float32 ที่ตัดทอนแล้วโดยมีบิตเลขชี้กำลังและช่วงเหมือนกับ float32 ทุกประการ การที่ TPU คำนวณการคูณเมทริกซ์ในความแม่นยำแบบผสมโดยมีอินพุตเป็น bfloat16 แต่อินพุตเป็น float32 หมายความว่าโดยปกติแล้วไม่จำเป็นต้องเปลี่ยนแปลงโค้ดเพื่อให้ได้รับประโยชน์จากประสิทธิภาพที่เพิ่มขึ้นของความแม่นยำที่ลดลง

อาร์เรย์ซิสโตลิก

MXU จะใช้การคูณเมทริกซ์ในฮาร์ดแวร์โดยใช้สถาปัตยกรรมที่เรียกว่า "อาร์เรย์ซิสโตลิก" ซึ่งองค์ประกอบข้อมูลจะไหลผ่านอาร์เรย์ของหน่วยการคำนวณฮาร์ดแวร์ (ในทางการแพทย์ "ซิสโทลิก" หมายถึงการบีบตัวของหัวใจและการไหลเวียนของเลือด ซึ่งในที่นี้หมายถึงการไหลเวียนของข้อมูล)

องค์ประกอบพื้นฐานของการคูณเมทริกซ์คือผลคูณจุดระหว่างแถวจากเมทริกซ์หนึ่งกับคอลัมน์จากเมทริกซ์อีกเมทริกซ์หนึ่ง (ดูภาพที่ด้านบนของส่วนนี้) สำหรับการคูณเมทริกซ์ Y=X*W องค์ประกอบหนึ่งของผลลัพธ์จะเป็นดังนี้

Y[2,0] = X[2,0]*W[0,0] + X[2,1]*W[1,0] + X[2,2]*W[2,0] + ... + X[2,n]*W[n,0]

ใน GPU เราจะเขียนโปรแกรมผลคูณจุดนี้ลงใน "แกน" ของ GPU แล้วรันใน "แกน" ให้ได้มากที่สุดแบบขนานเพื่อพยายามคำนวณค่าทุกค่าของเมทริกซ์ผลลัพธ์พร้อมกัน หากเมทริกซ์ที่ได้มีขนาด 128x128 จะต้องมี "แกน" 128x128=16K ซึ่งโดยปกติแล้วจะเป็นไปไม่ได้ GPU ที่ใหญ่ที่สุดมีประมาณ 4,000 คอร์ ในทางกลับกัน TPU จะใช้ฮาร์ดแวร์ขั้นต่ำสำหรับหน่วยประมวลผลใน MXU ซึ่งมีเพียงbfloat16 x bfloat16 => float32ตัวคูณสะสมเท่านั้น ซึ่งมีขนาดเล็กมากจน TPU สามารถติดตั้งใช้งานได้ถึง 16,000 รายการใน MXU ขนาด 128x128 และประมวลผลการคูณเมทริกซ์นี้ได้ในครั้งเดียว

f1b283fc45966717.gif

ภาพ: อาร์เรย์ซิสโตลิก MXU องค์ประกอบการคำนวณคือตัวคูณสะสม ระบบจะโหลดค่าของเมทริกซ์หนึ่งลงในอาร์เรย์ (จุดสีแดง) ค่าของเมทริกซ์อื่นๆ จะไหลผ่านอาร์เรย์ (จุดสีเทา) เส้นแนวตั้งจะส่งต่อค่าขึ้นไป เส้นแนวนอนจะส่งต่อผลรวมบางส่วน ผู้ใช้ต้องตรวจสอบว่าเมื่อข้อมูลไหลผ่านอาร์เรย์ คุณจะได้รับผลลัพธ์ของการคูณเมทริกซ์ที่ออกมาจากด้านขวา

นอกจากนี้ ขณะที่ MXU กำลังคำนวณผลคูณแบบดอท ผลรวมขั้นกลางจะไหลเวียนระหว่างหน่วยประมวลผลที่อยู่ติดกัน ไม่จำเป็นต้องจัดเก็บและดึงข้อมูลจากหน่วยความจำหรือแม้แต่ไฟล์รีจิสเตอร์ ผลลัพธ์ที่ได้คือสถาปัตยกรรมอาร์เรย์ซิสโตลิกของ TPU มีข้อได้เปรียบด้านความหนาแน่นและกำลังอย่างมาก รวมถึงข้อได้เปรียบด้านความเร็วที่สำคัญเมื่อเทียบกับ GPU เมื่อทำการคูณเมทริกซ์

Cloud TPU

เมื่อขอ "Cloud TPU v2" ใน Google Cloud Platform คุณจะได้รับเครื่องเสมือน (VM) ที่มีบอร์ด TPU ที่เชื่อมต่อกับ PCI บอร์ด TPU มีชิป TPU แบบดูอัลคอร์ 4 ตัว แต่ละคอร์ TPU มี VPU (หน่วยประมวลผลเวกเตอร์) และ MXU (หน่วยคูณเมทริกซ์) ขนาด 128x128 จากนั้นโดยปกติแล้ว "Cloud TPU" นี้จะเชื่อมต่อผ่านเครือข่ายกับ VM ที่ขอ ดังนั้นภาพรวมทั้งหมดจึงมีลักษณะดังนี้

dfce5522ed644ece.png

ภาพประกอบ: VM ของคุณที่มีตัวเร่ง "Cloud TPU" ที่เชื่อมต่อกับเครือข่าย "Cloud TPU" เองประกอบด้วย VM ที่มีบอร์ด TPU ที่เชื่อมต่อ PCI ซึ่งมีชิป TPU แบบดูอัลคอร์ 4 ตัว

พ็อด TPU

ในศูนย์ข้อมูลของ Google นั้น TPU จะเชื่อมต่อกับอินเทอร์คอนเน็กต์การประมวลผลประสิทธิภาพสูง (HPC) ซึ่งทำให้ TPU ปรากฏเป็นตัวเร่งขนาดใหญ่มากตัวเดียว Google เรียกพ็อดเหล่านี้ว่าพ็อด และพ็อดสามารถมีแกน TPU v2 ได้สูงสุด 512 แกน หรือแกน TPU v3 ได้สูงสุด 2048 แกน

2ec1e0d341e7fc34.jpeg

ภาพ: พ็อด TPU v3 บอร์ดและแร็ค TPU ที่เชื่อมต่อผ่านการเชื่อมต่อถึงกันของ HPC

ในระหว่างการฝึก อัลกอริทึม All-Reduce จะใช้เพื่อแลกเปลี่ยนการไล่ระดับระหว่างคอร์ TPU ( คำอธิบายที่ดีเกี่ยวกับ All-Reduce อยู่ที่นี่) โมเดลที่กำลังฝึกสามารถใช้ประโยชน์จากฮาร์ดแวร์ได้โดยการฝึกในขนาดกลุ่มใหญ่

d97b9cc5d40fdb1d.gif

ภาพ: การซิงโครไนซ์การไล่ระดับสีระหว่างการฝึกโดยใช้อัลกอริทึม All-Reduce ในเครือข่าย HPC แบบเมชโทโรดัล 2 มิติของ TPU ของ Google

ซอฟต์แวร์

การฝึกที่มีขนาดกลุ่มใหญ่

ขนาดกลุ่มที่เหมาะสมสำหรับ TPU คือ 128 รายการข้อมูลต่อแกน TPU แต่ฮาร์ดแวร์สามารถแสดงการใช้งานที่ดีได้ตั้งแต่ 8 รายการข้อมูลต่อแกน TPU โปรดทราบว่า Cloud TPU 1 เครื่องมี 8 คอร์

ในโค้ดแล็บนี้ เราจะใช้ Keras API ใน Keras แบตช์ที่คุณระบุคือขนาดแบตช์ส่วนกลางสำหรับ TPU ทั้งหมด ระบบจะแยกกลุ่มของคุณออกเป็น 8 กลุ่มโดยอัตโนมัติและเรียกใช้ใน 8 คอร์ของ TPU

da534407825f01e3.png

ดูเคล็ดลับเพิ่มเติมเกี่ยวกับประสิทธิภาพได้ที่คู่มือประสิทธิภาพ TPU สำหรับขนาดกลุ่มที่ใหญ่มาก โมเดลบางรุ่นอาจต้องมีการดูแลเป็นพิเศษ โปรดดูรายละเอียดเพิ่มเติมที่ LARSOptimizer

กลไกภายใน: XLA

โปรแกรม TensorFlow จะกำหนดกราฟการคำนวณ TPU ไม่ได้รันโค้ด Python โดยตรง แต่จะรันกราฟการคำนวณที่กำหนดโดยโปรแกรม TensorFlow เบื้องหลังคอมไพเลอร์ที่ชื่อว่า XLA (คอมไพเลอร์พีชคณิตเชิงเส้นแบบเร่งความเร็ว) จะแปลงกราฟการคำนวณของ TensorFlow ที่มีโหนดการคำนวณให้เป็นโค้ดเครื่องของ TPU นอกจากนี้ คอมไพเลอร์นี้ยังทำการเพิ่มประสิทธิภาพขั้นสูงหลายอย่างในโค้ดและเลย์เอาต์หน่วยความจำ การคอมไพล์จะเกิดขึ้นโดยอัตโนมัติเมื่อส่งงานไปยัง TPU คุณไม่จำเป็นต้องรวม XLA ไว้ในห่วงโซ่การสร้างอย่างชัดเจน

edce61112cd57972.png

ภาพประกอบ: หากต้องการเรียกใช้ใน TPU กราฟการคำนวณที่กำหนดโดยโปรแกรม TensorFlow จะได้รับการแปลเป็นตัวแทน XLA (คอมไพเลอร์พีชคณิตเชิงเส้นแบบเร่ง) ก่อน จากนั้น XLA จะคอมไพล์เป็นโค้ดเครื่อง TPU

การใช้ TPU ใน Keras

TPU รองรับผ่าน Keras API ตั้งแต่ TensorFlow 2.1 เป็นต้นไป การรองรับ Keras ใช้ได้กับ TPU และ TPU Pod ต่อไปนี้คือตัวอย่างที่ใช้ได้กับ TPU, GPU และ CPU

try: # detect TPUs
    tpu = tf.distribute.cluster_resolver.TPUClusterResolver.connect()
    strategy = tf.distribute.TPUStrategy(tpu)
except ValueError: # detect GPUs
    strategy = tf.distribute.MirroredStrategy() # for CPU/GPU or multi-GPU machines

# use TPUStrategy scope to define model
with strategy.scope():
  model = tf.keras.Sequential( ... )
  model.compile( ... )

# train model normally on a tf.data.Dataset
model.fit(training_dataset, epochs=EPOCHS, steps_per_epoch=...)

ในข้อมูลโค้ดนี้

  • TPUClusterResolver().connect() ค้นหา TPU ในเครือข่าย โดยจะทำงานได้โดยไม่ต้องใช้พารามิเตอร์ในระบบ Google Cloud ส่วนใหญ่ (งาน AI Platform, Colaboratory, Kubeflow, VM สำหรับ Deep Learning ที่สร้างผ่านยูทิลิตี "ctpu up") ระบบเหล่านี้ทราบว่า TPU อยู่ที่ใดเนื่องจากตัวแปรสภาพแวดล้อม TPU_NAME หากสร้าง TPU ด้วยตนเอง ให้ตั้งค่าตัวแปรสภาพแวดล้อม TPU_NAME ใน VM ที่คุณใช้ หรือเรียกใช้ TPUClusterResolver โดยมีพารามิเตอร์ที่ชัดเจน: TPUClusterResolver(tp_uname, zone, project)
  • TPUStrategy เป็นส่วนที่ใช้การกระจายและอัลกอริทึมการซิงค์การไล่ระดับสี "all-reduce"
  • กลยุทธ์นี้ใช้ผ่านขอบเขต ต้องกำหนดโมเดลภายในขอบเขตกลยุทธ์()
  • ฟังก์ชัน tpu_model.fit ต้องการออบเจ็กต์ tf.data.Dataset เป็นอินพุตสำหรับการฝึก TPU

งานทั่วไปในการพอร์ต TPU

  • แม้ว่าจะมีหลายวิธีในการโหลดข้อมูลในโมเดล TensorFlow แต่สำหรับ TPU คุณต้องใช้ tf.data.Dataset API
  • TPU ทำงานได้รวดเร็วมาก และการนำเข้าข้อมูลมักกลายเป็นคอขวดเมื่อเรียกใช้บน TPU คุณใช้เครื่องมือเพื่อตรวจหาจุดคอขวดของข้อมูลและเคล็ดลับอื่นๆ เกี่ยวกับประสิทธิภาพได้ในคู่มือประสิทธิภาพของ TPU
  • ระบบจะถือว่าตัวเลข int8 หรือ int16 เป็น int32 TPU ไม่มีฮาร์ดแวร์จำนวนเต็มที่ทำงานน้อยกว่า 32 บิต
  • ไม่รองรับการดำเนินการบางอย่างของ TensorFlow ดูรายการได้ที่นี่ ข่าวดีคือข้อจำกัดนี้มีผลกับโค้ดการฝึกเท่านั้น ซึ่งหมายถึงการส่งต่อและส่งย้อนกลับผ่านโมเดล คุณยังคงใช้การดำเนินการ Tensorflow ทั้งหมดในไปป์ไลน์อินพุตข้อมูลได้เนื่องจากระบบจะดำเนินการบน CPU
  • TPU ไม่รองรับ tf.py_func

4. [ข้อมูล] ตัวแยกประเภทโครงข่ายประสาทเทียม 101

โดยสรุป

หากคุณทราบคำศัพท์ทั้งหมดที่ตัวหนาในย่อหน้าถัดไปแล้ว ให้ไปที่แบบฝึกหัดถัดไป หากคุณเพิ่งเริ่มต้นเรียนรู้เชิงลึก เราขอต้อนรับและโปรดอ่านต่อ

สำหรับโมเดลที่สร้างเป็นลำดับของเลเยอร์ Keras มี Sequential API ตัวอย่างเช่น คุณเขียนตัวแยกประเภทรูปภาพที่ใช้เลเยอร์แบบหนาแน่น 3 เลเยอร์ใน Keras ได้ดังนี้

model = tf.keras.Sequential([
    tf.keras.layers.Flatten(input_shape=[192, 192, 3]),
    tf.keras.layers.Dense(500, activation="relu"),
    tf.keras.layers.Dense(50, activation="relu"),
    tf.keras.layers.Dense(5, activation='softmax') # classifying into 5 classes
])

# this configures the training of the model. Keras calls it "compiling" the model.
model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy']) # % of correct answers

# train the model
model.fit(dataset, ... )

688858c21e3beff2.png

โครงข่ายประสาทเทียมแบบหนาแน่น

ซึ่งเป็นโครงข่ายประสาทเทียมที่ง่ายที่สุดสำหรับการจัดหมวดหมู่รูปภาพ ซึ่งประกอบด้วย "นิวรอน" ที่จัดเรียงเป็นชั้นๆ เลเยอร์แรกจะประมวลผลข้อมูลอินพุตและส่งเอาต์พุตไปยังเลเยอร์อื่นๆ เลเยอร์นี้เรียกว่า "หนาแน่น" เนื่องจากแต่ละนิวรอนเชื่อมต่อกับนิวรอนทั้งหมดในเลเยอร์ก่อนหน้า

c21bae6dade487bc.png

คุณสามารถป้อนรูปภาพลงในเครือข่ายดังกล่าวได้โดยการแปลงค่า RGB ของพิกเซลทั้งหมดให้เป็นเวกเตอร์ยาวและใช้เป็นอินพุต แม้จะไม่ใช่เทคนิคที่ดีที่สุดสำหรับการจดจำรูปภาพ แต่เราจะปรับปรุงเทคนิคนี้ในภายหลัง

เซลล์ประสาท การเปิดใช้งาน RELU

"นิวรอน" จะคำนวณผลรวมแบบถ่วงน้ำหนักของอินพุตทั้งหมด เพิ่มค่าที่เรียกว่า "อคติ" และป้อนผลลัพธ์ผ่านสิ่งที่เรียกว่า "ฟังก์ชันกระตุ้น" โดยตอนแรกเราจะไม่ทราบค่าถ่วงน้ำหนักและค่าอคติ โดยจะเริ่มต้นแบบสุ่มและ "เรียนรู้" ด้วยการฝึกโครงข่ายประสาทเทียมกับข้อมูลที่ทราบจำนวนมาก

644f4213a4ee70e5.png

ฟังก์ชันการเปิดใช้งานที่ได้รับความนิยมมากที่สุดเรียกว่า RELU สำหรับ Rectified Linear Unit ฟังก์ชันนี้ใช้งานง่ายมาก ดังที่เห็นในกราฟด้านบน

ฟังก์ชันกระตุ้น Softmax

เครือข่ายด้านบนลงท้ายด้วยเลเยอร์ 5 นิวรอนเนื่องจากเราจัดประเภทดอกไม้เป็น 5 หมวดหมู่ (กุหลาบ ทิวลิป แดนดิไลออน เดซี่ และทานตะวัน) ระบบจะเปิดใช้งานนิวรอนในเลเยอร์กลางโดยใช้ฟังก์ชันการเปิดใช้งาน RELU แบบคลาสสิก แต่ในเลเยอร์สุดท้าย เราต้องการคำนวณตัวเลขระหว่าง 0 ถึง 1 ซึ่งแสดงถึงความน่าจะเป็นที่ดอกไม้นี้จะเป็นดอกกุหลาบ ดอกทิวลิป และอื่นๆ สำหรับกรณีนี้ เราจะใช้ฟังก์ชันการเปิดใช้งานที่เรียกว่า "softmax"

การใช้ Softmax กับเวกเตอร์ทำได้โดยการหาเลขชี้กำลังของแต่ละองค์ประกอบ แล้วทำให้เวกเตอร์เป็นปกติ โดยปกติจะใช้ L1 Norm (ผลรวมของค่าสัมบูรณ์) เพื่อให้ค่ารวมกันเป็น 1 และสามารถตีความเป็นความน่าจะเป็นได้

ef0d98c0952c262d.png d51252f75894479e.gif

การสูญเสียแบบ Cross-Entropy

เมื่อเครือข่ายประสาทสร้างการคาดการณ์จากรูปภาพอินพุตแล้ว เราต้องวัดว่าการคาดการณ์นั้นดีเพียงใด กล่าวคือ ระยะห่างระหว่างสิ่งที่เครือข่ายบอกเรากับคำตอบที่ถูกต้อง ซึ่งมักเรียกว่า "ป้ายกำกับ" โปรดทราบว่าเรามีป้ายกำกับที่ถูกต้องสำหรับรูปภาพทั้งหมดในชุดข้อมูล

ระยะทางใดก็ได้ แต่สำหรับปัญหาการจัดประเภท "ระยะทางครอสเอนโทรปี" ที่เรียกว่ามีประสิทธิภาพมากที่สุด เราจะเรียกฟังก์ชันนี้ว่าฟังก์ชันข้อผิดพลาดหรือ "การสูญเสีย"

7bdf8753d20617fb.png

การไล่ระดับสี

"การฝึก" โครงข่ายประสาทเทียมหมายถึงการใช้รูปภาพและป้ายกำกับการฝึกเพื่อปรับน้ำหนักและอคติเพื่อลดฟังก์ชันการสูญเสียเอนโทรปีแบบครอสให้เหลือน้อยที่สุด วิธีการทำงานมีดังนี้

Cross-entropy เป็นฟังก์ชันของน้ำหนัก อคติ พิกเซลของรูปภาพการฝึก และคลาสที่ทราบ

หากเราคำนวณอนุพันธ์ย่อยของครอสเอนโทรปีเทียบกับน้ำหนักทั้งหมดและอคติทั้งหมด เราจะได้ "การไล่ระดับ" ซึ่งคำนวณสำหรับรูปภาพ ป้ายกำกับ และค่าปัจจุบันของน้ำหนักและอคติที่กำหนด โปรดทราบว่าเรามีค่าถ่วงน้ำหนักและไบแอสได้หลายล้านรายการ ดังนั้นการคำนวณการไล่ระดับจึงดูเหมือนเป็นงานที่ต้องทำมาก โชคดีที่ TensorFlow จัดการเรื่องนี้ให้เรา คุณสมบัติทางคณิตศาสตร์ของเกรเดียนต์คือจะชี้ "ขึ้น" เนื่องจากเราต้องการไปในทิศทางที่ครอสเอนโทรปีต่ำ เราจึงไปในทิศทางตรงกันข้าม เราอัปเดตน้ำหนักและอคติด้วยเศษส่วนของค่าการไล่ระดับ จากนั้นเราจะทำซ้ำไปเรื่อยๆ โดยใช้รูปภาพและป้ายกำกับการฝึกชุดถัดไปในลูปการฝึก หวังว่าสิ่งนี้จะมาบรรจบกันในจุดที่ Cross-Entropy น้อยที่สุด แม้ว่าจะไม่มีอะไรรับประกันว่าค่าต่ำสุดนี้จะไม่ซ้ำกัน

gradient descent2.png

การประมวลผลแบบมินิแบตช์และโมเมนตัม

คุณสามารถคำนวณการไล่ระดับสีในรูปภาพตัวอย่างเพียงรูปเดียวและอัปเดตน้ำหนักและอคติได้ทันที แต่การทำเช่นนั้นในกลุ่มรูปภาพ เช่น 128 รูป จะทำให้ได้การไล่ระดับสีที่แสดงถึงข้อจำกัดที่กำหนดโดยรูปภาพตัวอย่างต่างๆ ได้ดีกว่า และจึงมีแนวโน้มที่จะบรรลุโซลูชันได้เร็วขึ้น ขนาดของมินิแบตช์เป็นพารามิเตอร์ที่ปรับได้

เทคนิคนี้ซึ่งบางครั้งเรียกว่า "การไล่ระดับความชันแบบสุ่ม" มีประโยชน์อีกอย่างที่ใช้งานได้จริงมากกว่า นั่นคือการทำงานกับกลุ่มยังหมายถึงการทำงานกับเมทริกซ์ขนาดใหญ่ขึ้น และโดยปกติแล้วการเพิ่มประสิทธิภาพเมทริกซ์เหล่านี้ใน GPU และ TPU จะทำได้ง่ายกว่า

อย่างไรก็ตาม การบรรจบกันอาจยังคงวุ่นวายเล็กน้อยและอาจหยุดลงได้หากเวกเตอร์การไล่ระดับเป็น 0 ทั้งหมด ซึ่งหมายความว่าเราพบค่าต่ำสุดแล้วใช่ไหม ไม่เสมอไป คอมโพเนนต์การไล่ระดับสีอาจเป็น 0 ในค่าต่ำสุดหรือค่าสูงสุด เวกเตอร์การไล่ระดับที่มีองค์ประกอบหลายล้านรายการ หากองค์ประกอบทั้งหมดเป็น 0 ความน่าจะเป็นที่ 0 ทุกตัวจะสอดคล้องกับจุดต่ำสุดและไม่มีตัวใดสอดคล้องกับจุดสูงสุดจะค่อนข้างน้อย ในพื้นที่ที่มีหลายมิติ จุดอานมักจะพบได้ทั่วไป และเราไม่ต้องการหยุดที่จุดเหล่านั้น

52e824fe4716c4a0.png

ภาพ: จุดอานม้า การไล่ระดับเป็น 0 แต่ไม่ใช่ค่าต่ำสุดในทุกทิศทาง (การระบุแหล่งที่มาของรูปภาพ Wikimedia: By Nicoguaro - Own work, CC BY 3.0)

วิธีแก้คือการเพิ่มโมเมนตัมให้กับอัลกอริทึมการเพิ่มประสิทธิภาพเพื่อให้ผ่านจุดอานม้าไปได้โดยไม่ต้องหยุด

อภิธานศัพท์

กลุ่มหรือกลุ่มย่อย: การฝึกจะดำเนินการกับกลุ่มข้อมูลการฝึกและป้ายกำกับเสมอ การทำเช่นนี้จะช่วยให้อัลกอริทึมบรรจบกัน มิติข้อมูล "กลุ่ม" มักจะเป็นมิติข้อมูลแรกของเทนเซอร์ข้อมูล เช่น เทนเซอร์ที่มีรูปร่าง [100, 192, 192, 3] มีรูปภาพ 100 รูปขนาด 192x192 พิกเซล โดยมีค่า 3 ค่าต่อพิกเซล (RGB)

การสูญเสียแบบครอสเอนโทรปี: ฟังก์ชันการสูญเสียพิเศษที่มักใช้ในตัวแยกประเภท

เลเยอร์หนาแน่น: เลเยอร์ของนิวรอนที่นิวรอนแต่ละตัวเชื่อมต่อกับนิวรอนทั้งหมดในเลเยอร์ก่อนหน้า

ฟีเจอร์: บางครั้งอินพุตของโครงข่ายประสาทเทียมเรียกว่า "ฟีเจอร์" ศิลปะในการพิจารณาว่าควรป้อนส่วนใดของชุดข้อมูล (หรือการรวมกันของส่วนต่างๆ) ลงในโครงข่ายประสาทเทียมเพื่อให้ได้การคาดการณ์ที่ดีเรียกว่า "การออกแบบฟีเจอร์"

ป้ายกำกับ: ชื่ออื่นของ "คลาส" หรือคำตอบที่ถูกต้องในปัญหาการแยกประเภทภายใต้การดูแล

อัตราการเรียนรู้: เศษส่วนของค่าการไล่ระดับที่ใช้ในการอัปเดตน้ำหนักและอคติในแต่ละการทำซ้ำของลูปการฝึก

ลอจิท: เอาต์พุตของเลเยอร์ของนิวรอนก่อนที่จะใช้ฟังก์ชันการเปิดใช้งานเรียกว่า "ลอจิท" คำนี้มาจาก "ฟังก์ชันโลจิสติก" หรือที่เรียกว่า "ฟังก์ชันซิกมอยด์" ซึ่งเคยเป็นฟังก์ชันกระตุ้นที่ได้รับความนิยมมากที่สุด "เอาต์พุตของนิวรอนก่อนฟังก์ชันลอจิสติก" เปลี่ยนชื่อเป็น "ลอจิท"

loss: ฟังก์ชันข้อผิดพลาดที่เปรียบเทียบเอาต์พุตของโครงข่ายประสาทกับคำตอบที่ถูกต้อง

นิวรอน: คำนวณผลรวมแบบถ่วงน้ำหนักของอินพุต เพิ่มอคติ และป้อนผลลัพธ์ผ่านฟังก์ชันการเปิดใช้งาน

การเข้ารหัสแบบ One-hot: ระบบจะเข้ารหัสคลาส 3 จาก 5 เป็นเวกเตอร์ที่มีองค์ประกอบ 5 รายการ ซึ่งเป็น 0 ทั้งหมด ยกเว้นรายการที่ 3 ซึ่งเป็น 1

relu: หน่วยเชิงเส้นที่แก้ไขแล้ว ฟังก์ชันการเปิดใช้งานยอดนิยมสำหรับนิวรอน

sigmoid: ฟังก์ชันกระตุ้นอีกฟังก์ชันหนึ่งที่เคยได้รับความนิยมและยังคงมีประโยชน์ในกรณีพิเศษ

softmax: ฟังก์ชันการกระตุ้นพิเศษที่ทำงานกับเวกเตอร์ เพิ่มความแตกต่างระหว่างคอมโพเนนต์ที่ใหญ่ที่สุดกับคอมโพเนนต์อื่นๆ ทั้งหมด และยังปรับเวกเตอร์ให้มีผลรวมเป็น 1 เพื่อให้ตีความได้เป็นเวกเตอร์ของความน่าจะเป็น ใช้เป็นขั้นตอนสุดท้ายในตัวแยกประเภท

เทนเซอร์: "เทนเซอร์" คล้ายกับเมทริกซ์ แต่มีจำนวนมิติข้อมูลเท่าใดก็ได้ เทนเซอร์ 1 มิติคือเวกเตอร์ เทนเซอร์ 2 มิติคือเมทริกซ์ จากนั้นคุณก็จะมีเทนเซอร์ที่มี 3, 4, 5 หรือมากกว่านั้น

5. [INFO] โครงข่ายประสาทแบบคอนโวลูชัน

โดยสรุป

หากคุณทราบคำศัพท์ทั้งหมดที่ตัวหนาในย่อหน้าถัดไปแล้ว ให้ไปที่แบบฝึกหัดถัดไป หากคุณเพิ่งเริ่มต้นใช้งาน Convolutional Neural Network โปรดอ่านต่อ

convolutional.gif

ภาพประกอบ: การกรองรูปภาพด้วยฟิลเตอร์ 2 รายการที่ต่อเนื่องกันซึ่งสร้างจากน้ำหนักที่เรียนรู้ได้ขนาด 4x4x3=48

เครือข่ายประสาทแบบคอนโวลูชันอย่างง่ายใน Keras มีลักษณะดังนี้

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=3, filters=24, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=12, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=6, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

688858c21e3beff2.png

โครงข่ายประสาทเทียมแบบคอนโวลูชัน 101

ในเลเยอร์ของเครือข่าย Convolutional "นิวรอน" จะทำการหาผลรวมแบบถ่วงน้ำหนักของพิกเซลที่อยู่เหนือขึ้นไปในบริเวณเล็กๆ ของรูปภาพเท่านั้น โดยจะเพิ่มอคติและป้อนผลรวมผ่านฟังก์ชันการเปิดใช้งาน เช่นเดียวกับที่นิวรอนในเลเยอร์ Dense ปกติจะทำ จากนั้นจะดำเนินการนี้ซ้ำทั่วทั้งรูปภาพโดยใช้น้ำหนักเดียวกัน โปรดทราบว่าในเลเยอร์แบบหนาแน่น นิวรอนแต่ละตัวจะมีน้ำหนักของตัวเอง ในที่นี้ "แพตช์" เดียวของน้ำหนักจะเลื่อนไปทั่วรูปภาพในทั้ง 2 ทิศทาง ("การสังวัตนาการ") เอาต์พุตมีค่ามากเท่ากับจำนวนพิกเซลในรูปภาพ (แม้ว่าอาจต้องมีการเว้นขอบบ้าง) ซึ่งเป็นการดำเนินการกรองโดยใช้น้ำหนัก 4x4x3=48

อย่างไรก็ตาม น้ำหนัก 48 รายการจะไม่เพียงพอ หากต้องการเพิ่มระดับอิสระ เราจะทำซ้ำการดำเนินการเดียวกันกับชุดน้ำหนักใหม่ ซึ่งจะสร้างเอาต์พุตตัวกรองชุดใหม่ เราจะเรียกเอาต์พุตนี้ว่า "แชแนล" โดยเปรียบเทียบกับแชแนล R,G,B ในรูปภาพอินพุต

Screen Shot 2016-07-29 at 16.02.37.png

คุณสามารถรวมชุดน้ำหนัก 2 ชุด (หรือมากกว่า) เป็นเทนเซอร์เดียวได้โดยการเพิ่มมิติข้อมูลใหม่ ซึ่งจะทำให้เราได้รูปร่างทั่วไปของเทนเซอร์น้ำหนักสำหรับเลเยอร์ Convolutional เนื่องจากจำนวนช่องอินพุตและเอาต์พุตเป็นพารามิเตอร์ เราจึงเริ่มซ้อนและเชื่อมต่อเลเยอร์ Convolutional ได้

d1b557707bcd1cb9.png

ภาพ: เครือข่ายประสาทแบบคอนโวลูชันจะเปลี่ยน "ก้อน" ข้อมูลให้เป็น "ก้อน" ข้อมูลอื่นๆ

การสังวัตน์แบบก้าวกระโดด การรวมสูงสุด

การดำเนินการ Convolution ด้วย Stride 2 หรือ 3 จะช่วยให้เราลดขนาด Data Cube ที่ได้ในมิติแนวนอนได้ด้วย ซึ่งมีวิธีทั่วไป 2 วิธีดังนี้

  • การสังวัตน์แบบมีระยะก้าวกระโดด: ตัวกรองแบบเลื่อนตามที่อธิบายไว้ข้างต้น แต่มีระยะก้าวกระโดด > 1
  • Max Pooling: หน้าต่างเลื่อนที่ใช้การดำเนินการ MAX (โดยปกติจะใช้กับแพตช์ 2x2 ซึ่งทำซ้ำทุกๆ 2 พิกเซล)

2b2d4263bb8470b.gif

ภาพประกอบ: การเลื่อนหน้าต่างการคำนวณ 3 พิกเซลจะทำให้ค่าเอาต์พุตน้อยลง การสังวัตน์แบบก้าวย่างหรือการรวมสูงสุด (ค่าสูงสุดในหน้าต่าง 2x2 ที่เลื่อนตามก้าวย่าง 2) เป็นวิธีลดขนาดก้อนข้อมูลในมิติข้อมูลแนวนอน

เครื่องมือแยกประเภทแบบ Convolutional

สุดท้าย เราจะแนบส่วนหัวของการจัดประเภทโดยการทำให้คิวบ์ข้อมูลสุดท้ายแบนราบและป้อนผ่านเลเยอร์ที่หนาแน่นซึ่งเปิดใช้งาน Softmax โดยทั่วไปแล้ว ตัวแยกประเภทแบบ Convolutional จะมีลักษณะดังนี้

4a61aaffb6cba3d1.png

ภาพประกอบ: ตัวแยกประเภทรูปภาพที่ใช้เลเยอร์ Convolutional และ Softmax โดยใช้ฟิลเตอร์ 3x3 และ 1x1 เลเยอร์ MaxPool จะใช้ค่าสูงสุดของกลุ่มจุดข้อมูล 2x2 ส่วนหัวการแยกประเภทจะใช้เลเยอร์แบบหนาแน่นที่มีการเปิดใช้งาน Softmax

ใน Keras

สแต็ก Convolutional ที่แสดงด้านบนสามารถเขียนใน Keras ได้ดังนี้

model = tf.keras.Sequential([
  # input: images of size 192x192x3 pixels (the three stands for RGB channels)    
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu', input_shape=[192, 192, 3]),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=32, padding='same', activation='relu'),
  tf.keras.layers.MaxPooling2D(pool_size=2),
  tf.keras.layers.Conv2D(kernel_size=3, filters=16, padding='same', activation='relu'),
  tf.keras.layers.Conv2D(kernel_size=1, filters=8, padding='same', activation='relu'),
  tf.keras.layers.Flatten(),
  # classifying into 5 categories
  tf.keras.layers.Dense(5, activation='softmax')
])

model.compile(
  optimizer='adam',
  loss= 'categorical_crossentropy',
  metrics=['accuracy'])

6. [ข้อมูลใหม่] สถาปัตยกรรม Convolutional สมัยใหม่

โดยสรุป

7968830b57b708c0.png

ภาพ: "โมดูล" แบบ Convolutional ตอนนี้ควรทำอย่างไร เลเยอร์ Max-Pool ตามด้วยเลเยอร์ Convolutional 1x1 หรือการผสมเลเยอร์แบบอื่น ลองใช้ทั้งหมดนี้ ต่อผลลัพธ์เข้าด้วยกัน แล้วปล่อยให้เครือข่ายตัดสิน ทางด้านขวา: สถาปัตยกรรมแบบ Convolutional " Inception" ที่ใช้โมดูลดังกล่าว

ใน Keras หากต้องการสร้างโมเดลที่โฟลว์ของข้อมูลสามารถแยกสาขาเข้าและออกได้ คุณต้องใช้รูปแบบโมเดล "ฟังก์ชัน" มีตัวอย่างดังต่อไปนี้

l = tf.keras.layers # syntax shortcut

y = l.Conv2D(filters=32, kernel_size=3, padding='same',
             activation='relu', input_shape=[192, 192, 3])(x) # x=input image

# module start: branch out
y1 = l.Conv2D(filters=32, kernel_size=1, padding='same', activation='relu')(y)
y3 = l.Conv2D(filters=32, kernel_size=3, padding='same', activation='relu')(y)
y = l.concatenate([y1, y3]) # output now has 64 channels
# module end: concatenation

# many more layers ...

# Create the model by specifying the input and output tensors.
# Keras layers track their connections automatically so that's all that's needed.
z = l.Dense(5, activation='softmax')(y)
model = tf.keras.Model(x, z)

688858c21e3beff2.png

เคล็ดลับอื่นๆ

ฟิลเตอร์ขนาดเล็ก 3x3

40a7b15fb7dbe75c.png

ในภาพนี้ คุณจะเห็นผลลัพธ์ของฟิลเตอร์ 3x3 2 รายการติดต่อกัน ลองย้อนรอยว่าจุดข้อมูลใดที่ทำให้เกิดผลลัพธ์นี้ โดยตัวกรอง 3x3 2 ตัวที่ต่อเนื่องกันจะคำนวณการรวมกันของภูมิภาค 5x5 แม้จะไม่ใช่การรวมกันแบบเดียวกับที่ฟิลเตอร์ 5x5 จะคำนวณ แต่ก็ควรลองใช้เนื่องจากฟิลเตอร์ 3x3 2 ตัวที่ต่อเนื่องกันมีราคาถูกกว่าฟิลเตอร์ 5x5 ตัวเดียว

การสังวัตนาการ 1x1 ?

fd7cac16f8ecb423.png

ในทางคณิตศาสตร์ การสังวัตนา "1x1" คือการคูณด้วยค่าคงที่ ซึ่งไม่ใช่แนวคิดที่มีประโยชน์มากนัก อย่างไรก็ตาม ในเครือข่ายประสาทแบบคอนโวลูชัน โปรดทราบว่าตัวกรองจะใช้กับคิวบ์ข้อมูล ไม่ใช่แค่รูปภาพ 2 มิติ ดังนั้น ฟิลเตอร์ "1x1" จะคำนวณผลรวมแบบถ่วงน้ำหนักของคอลัมน์ข้อมูล 1x1 (ดูภาพประกอบ) และเมื่อเลื่อนฟิลเตอร์ไปตามข้อมูล คุณจะได้รับการรวมเชิงเส้นของแชแนลของอินพุต ซึ่งมีประโยชน์จริงๆ หากคุณคิดว่าช่องเป็นผลลัพธ์ของการดำเนินการกรองแต่ละรายการ เช่น ตัวกรองสำหรับ "หูแหลม" ตัวกรองอีกรายการสำหรับ "หนวด" และตัวกรองที่ 3 สำหรับ "ตาเรียว" เลเยอร์ Convolutional "1x1" จะคำนวณการรวมเชิงเส้นที่เป็นไปได้หลายรายการของฟีเจอร์เหล่านี้ ซึ่งอาจมีประโยชน์เมื่อมองหา "แมว" นอกจากนี้ เลเยอร์ 1x1 ยังใช้น้ำหนักน้อยกว่าด้วย

7. Squeezenet

เอกสาร"Squeezenet" ได้แสดงวิธีง่ายๆ ในการรวมแนวคิดเหล่านี้เข้าด้วยกัน ผู้เขียนแนะนำการออกแบบโมดูล Convolutional ที่เรียบง่าย โดยใช้เฉพาะเลเยอร์ Convolutional ขนาด 1x1 และ 3x3

1730ac375379269b.png

ภาพ: สถาปัตยกรรม SqueezeNet ที่อิงตาม "โมดูล Fire" โดยจะสลับเลเยอร์ 1x1 ที่ "บีบ" ข้อมูลขาเข้าในมิติแนวตั้ง ตามด้วยเลเยอร์ Convolutional แบบ 1x1 และ 3x3 แบบขนาน 2 เลเยอร์ที่ "ขยาย" ความลึกของข้อมูลอีกครั้ง

ลงมือปฏิบัติ

ทำต่อใน Notebook ก่อนหน้าและสร้าง Convolutional Neural Network ที่ได้แรงบันดาลใจจาก SqueezeNet คุณจะต้องเปลี่ยนโค้ดโมเดลเป็น "รูปแบบฟังก์ชัน" ของ Keras

c3df49e90e5a654f.png Keras_Flowers_TPU (playground).ipynb

ข้อมูลเพิ่มเติม

การกำหนดฟังก์ชันตัวช่วยสำหรับโมดูล SqueezeNet จะมีประโยชน์สำหรับการฝึกนี้

def fire(x, squeeze, expand):
  y = l.Conv2D(filters=squeeze, kernel_size=1, padding='same', activation='relu')(x)
  y1 = l.Conv2D(filters=expand//2, kernel_size=1, padding='same', activation='relu')(y)
  y3 = l.Conv2D(filters=expand//2, kernel_size=3, padding='same', activation='relu')(y)
  return tf.keras.layers.concatenate([y1, y3])

# this is to make it behave similarly to other Keras layers
def fire_module(squeeze, expand):
  return lambda x: fire(x, squeeze, expand)

# usage:
x = l.Input(shape=[192, 192, 3])
y = fire_module(squeeze=24, expand=48)(x) # typically, squeeze is less than expand
y = fire_module(squeeze=32, expand=64)(y)
...
model = tf.keras.Model(x, y)

โดยวัตถุประสงค์ในครั้งนี้คือการบรรลุความแม่นยำ 80%

สิ่งที่ควรลอง

เริ่มด้วยเลเยอร์ Convolutional เดียว แล้วตามด้วย "fire_modules" สลับกับเลเยอร์ MaxPooling2D(pool_size=2) คุณสามารถทดลองใช้เลเยอร์การจัดกลุ่มสูงสุด 2-4 เลเยอร์ในเครือข่าย รวมถึงใช้โมดูล Fire ต่อเนื่อง 1, 2 หรือ 3 โมดูลระหว่างเลเยอร์การจัดกลุ่มสูงสุด

ในโมดูลไฟ พารามิเตอร์ "บีบ" ควรมีขนาดเล็กกว่าพารามิเตอร์ "ขยาย" พารามิเตอร์เหล่านี้เป็นจำนวนตัวกรอง โดยปกติแล้วจะมีค่าตั้งแต่ 8 ถึง 196 คุณสามารถทดลองใช้สถาปัตยกรรมที่จำนวนฟิลเตอร์จะเพิ่มขึ้นเรื่อยๆ ผ่านเครือข่าย หรือสถาปัตยกรรมที่ตรงไปตรงมาซึ่งโมดูล Fire ทั้งหมดมีจำนวนฟิลเตอร์เท่ากัน

มีตัวอย่างดังต่อไปนี้

x = tf.keras.layers.Input(shape=[*IMAGE_SIZE, 3]) # input is 192x192 pixels RGB

y = tf.keras.layers.Conv2D(kernel_size=3, filters=32, padding='same', activation='relu')(x)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.MaxPooling2D(pool_size=2)(y)
y = fire_module(24, 48)(y)
y = tf.keras.layers.GlobalAveragePooling2D()(y)
y = tf.keras.layers.Dense(5, activation='softmax')(y)

model = tf.keras.Model(x, y)

ในตอนนี้ คุณอาจสังเกตเห็นว่าการทดสอบไม่เป็นไปตามที่คาดหวัง และเป้าหมายความแม่นยำ 80% ดูเหมือนจะอยู่ไกลเกินเอื้อม ได้เวลาสำหรับเคล็ดลับราคาถูกอีก 2-3 อย่าง

การทำให้เป็นมาตรฐานแบบกลุ่ม

Batch Norm จะช่วยแก้ปัญหาการบรรจบกันที่คุณพบ เราจะอธิบายรายละเอียดเกี่ยวกับเทคนิคนี้ในเวิร์กช็อปครั้งถัดไป สำหรับตอนนี้ โปรดใช้เป็นตัวช่วย "มหัศจรรย์" ที่ไม่จำเป็นต้องรู้รายละเอียดภายในโดยการเพิ่มบรรทัดนี้หลังเลเยอร์ Convolutional ทุกเลเยอร์ในเครือข่าย รวมถึงเลเยอร์ภายในฟังก์ชัน fire_module

y = tf.keras.layers.BatchNormalization(momentum=0.9)(y)
# please adapt the input and output "y"s to whatever is appropriate in your context

เราต้องลดพารามิเตอร์โมเมนตัมจากค่าเริ่มต้นที่ 0.99 เป็น 0.9 เนื่องจากชุดข้อมูลมีขนาดเล็ก ไม่ต้องสนใจรายละเอียดนี้ในตอนนี้

การเพิ่มข้อมูล

คุณจะได้รับเปอร์เซ็นต์เพิ่มขึ้นอีก 2-3 เปอร์เซ็นต์โดยการเพิ่มข้อมูลด้วยการเปลี่ยนรูปแบบง่ายๆ เช่น การพลิกซ้ายขวาของการเปลี่ยนแปลงความอิ่มตัว

4ed2958e09b487ca.png

ad795b70334e0d6b.png

ซึ่งทำได้ง่ายมากใน TensorFlow ด้วย tf.data.Dataset API กำหนดฟังก์ชันการเปลี่ยนรูปแบบใหม่สำหรับข้อมูลของคุณ

def data_augment(image, label):
    image = tf.image.random_flip_left_right(image)
    image = tf.image.random_saturation(image, lower=0, upper=2)
    return image, label

จากนั้นใช้ในการเปลี่ยนรูปแบบข้อมูลขั้นสุดท้าย (เซลล์ "ชุดข้อมูลการฝึกและชุดข้อมูลการตรวจสอบ" ฟังก์ชัน "get_batched_dataset")

dataset = dataset.repeat() # existing line
# insert this
if augment_data:
  dataset = dataset.map(data_augment, num_parallel_calls=AUTO)
dataset = dataset.shuffle(2048) # existing line

อย่าลืมทําให้การเพิ่มข้อมูลเป็นแบบไม่บังคับ และเพิ่มโค้ดที่จําเป็นเพื่อให้แน่ใจว่าเฉพาะชุดข้อมูลการฝึกเท่านั้นที่จะได้รับการเพิ่ม การเพิ่มชุดข้อมูลการตรวจสอบจึงไม่มีประโยชน์

ตอนนี้คุณควรมีความแม่นยำ 80% ใน 35 ยุค

Solution

สมุดบันทึกโซลูชัน คุณสามารถใช้ฟีเจอร์นี้ได้หากติดขัด

c3df49e90e5a654f.png Keras_Flowers_TPU_squeezenet.ipynb

สิ่งที่เราได้พูดถึง

  • 🤔 โมเดล "รูปแบบฟังก์ชัน" ของ Keras
  • 🤓 สถาปัตยกรรม Squeezenet
  • 🤓 การเพิ่มข้อมูลด้วย tf.data.datset

โปรดสละเวลาสักครู่เพื่อพิจารณารายการตรวจสอบนี้ในใจ

8. Xception ที่ปรับแต่งแล้ว

การสังวัตน์แบบแยกได้

เมื่อเร็วๆ นี้ วิธีการใช้เลเยอร์ Convolutional แบบอื่นได้รับความนิยมมากขึ้น นั่นคือ Convolution แบบแยกความลึก เราทราบว่าชื่อนี้ค่อนข้างยาว แต่แนวคิดนั้นเรียบง่ายมาก โดยจะใช้งานใน TensorFlow และ Keras เป็น tf.keras.layers.SeparableConv2D

การ Convolution แบบแยกกันได้จะเรียกใช้ตัวกรองในรูปภาพเช่นกัน แต่จะใช้ชุดน้ำหนักที่แตกต่างกันสำหรับแต่ละแชแนลของรูปภาพอินพุต จากนั้นจะตามด้วย "การสังวัตน์แบบ 1x1" ซึ่งเป็นชุดของผลคูณแบบดอทที่ให้ผลรวมแบบถ่วงน้ำหนักของช่องที่กรองแล้ว โดยจะใช้ค่าถ่วงน้ำหนักใหม่ทุกครั้ง และจะคำนวณการรวมช่องที่ถ่วงน้ำหนักมากที่สุดเท่าที่จำเป็น

615720b803bf8dda.gif

ภาพ: การคูณแบบแยกกัน เฟสที่ 1: การบิดเบือนที่มีตัวกรองแยกต่างหากสำหรับแต่ละช่อง ระยะที่ 2: การรวมช่องเชิงเส้น ทำซ้ำโดยใช้ชุดน้ำหนักใหม่จนกว่าจะได้จำนวนช่องเอาต์พุตที่ต้องการ คุณทำเฟส 1 ซ้ำได้เช่นกัน โดยใช้ค่าถ่วงน้ำหนักใหม่ในแต่ละครั้ง แต่ในทางปฏิบัติแล้วมักไม่ค่อยเกิดขึ้น

การแยก Convolution ออกจากกันใช้ในสถาปัตยกรรมเครือข่าย Convolutional ล่าสุดส่วนใหญ่ ได้แก่ MobileNetV2, Xception และ EfficientNet อย่างไรก็ตาม MobileNetV2 คือสิ่งที่คุณใช้สำหรับการเรียนรู้แบบถ่ายโอนก่อนหน้านี้

โดยมีราคาถูกกว่าการ Convolution ปกติ และพบว่ามีประสิทธิภาพเท่ากันในทางปฏิบัติ น้ำหนักของตัวอย่างที่แสดงด้านบนมีดังนี้

เลเยอร์ Convolutional: 4 x 4 x 3 x 5 = 240

เลเยอร์ Convolution ที่แยกได้: 4 x 4 x 3 + 3 x 5 = 48 + 15 = 63

ผู้อ่านสามารถลองคำนวณจำนวนการคูณที่จำเป็นในการใช้เลเยอร์ Convolutional แต่ละสไตล์ในลักษณะที่คล้ายกัน การคูณแบบแยกส่วนมีขนาดเล็กกว่าและมีประสิทธิภาพในการคำนวณมากกว่า

ลงมือปฏิบัติ

เริ่มใหม่จาก Notebook ของ Playground "การเรียนรู้แบบถ่ายโอน" แต่คราวนี้ให้เลือก Xception เป็นโมเดลที่ฝึกไว้ล่วงหน้า Xception ใช้เฉพาะการผสานรวมที่แยกออกได้ ปล่อยให้น้ำหนักทั้งหมดฝึกได้ เราจะปรับแต่งน้ำหนักที่ฝึกไว้ล่วงหน้าในข้อมูลของเราแทนที่จะใช้เลเยอร์ที่ฝึกไว้ล่วงหน้าตามนั้น

c3df49e90e5a654f.png Keras Flowers transfer learning (playground).ipynb

เป้าหมาย: ความแม่นยำ > 95% (ใช่ คุณทำได้จริงๆ)

เนื่องจากเป็นแบบฝึกหัดสุดท้าย จึงต้องใช้โค้ดและงานด้านวิทยาศาสตร์ข้อมูลเพิ่มเติมเล็กน้อย

ข้อมูลเพิ่มเติมเกี่ยวกับการปรับแต่ง

Xception พร้อมใช้งานในโมเดลที่ฝึกไว้ล่วงหน้ามาตรฐานใน tf.keras.application.* อย่าลืมปล่อยให้น้ำหนักทั้งหมดฝึกได้ในครั้งนี้

pretrained_model = tf.keras.applications.Xception(input_shape=[*IMAGE_SIZE, 3],
                                                  include_top=False)
pretrained_model.trainable = True

หากต้องการให้ได้ผลลัพธ์ที่ดีเมื่อปรับแต่งโมเดล คุณจะต้องให้ความสำคัญกับอัตราการเรียนรู้และใช้กำหนดการอัตราการเรียนรู้ที่มีระยะเวลาการเพิ่มขึ้น ดังนี้

9b1af213b2b36d47.png

การเริ่มต้นด้วยอัตราการเรียนรู้มาตรฐานจะรบกวนน้ำหนักที่ฝึกไว้ล่วงหน้าของโมเดล การเริ่มต้นอย่างค่อยเป็นค่อยไปจะช่วยรักษาข้อมูลดังกล่าวไว้จนกว่าโมเดลจะเชื่อมต่อกับข้อมูลของคุณและแก้ไขข้อมูลเหล่านั้นได้อย่างสมเหตุสมผล หลังจากเพิ่มขึ้นแล้ว คุณจะใช้ Learning Rate แบบคงที่หรือแบบลดลงแบบเอ็กซ์โปเนนเชียลต่อไปก็ได้

ใน Keras คุณจะระบุอัตราการเรียนรู้ผ่านการเรียกกลับซึ่งคุณสามารถคำนวณอัตราการเรียนรู้ที่เหมาะสมสำหรับแต่ละ Epoch ได้ Keras จะส่งอัตราการเรียนรู้ที่ถูกต้องไปยังตัวเพิ่มประสิทธิภาพสำหรับแต่ละ Epoch

def lr_fn(epoch):
  lr = ...
  return lr

lr_callback = tf.keras.callbacks.LearningRateScheduler(lr_fn, verbose=True)

model.fit(..., callbacks=[lr_callback])

Solution

สมุดบันทึกโซลูชัน คุณสามารถใช้ฟีเจอร์นี้ได้หากติดขัด

c3df49e90e5a654f.png 07_Keras_Flowers_TPU_xception_fine_tuned_best.ipynb

สิ่งที่เราได้พูดถึง

  • 🤔 การผสานรวมที่แยกความลึก
  • 🤓 กำหนดการอัตราการเรียนรู้
  • 😈 การปรับแต่งโมเดลที่ฝึกไว้ล่วงหน้า

โปรดสละเวลาสักครู่เพื่อพิจารณารายการตรวจสอบนี้ในใจ

9. ยินดีด้วย

คุณได้สร้างโครงข่ายระบบประสาทเทียมแบบ Convolution ที่ทันสมัยเป็นครั้งแรกและฝึกให้มีความแม่นยำมากกว่า 90% โดยทำการฝึกซ้ำๆ กันในเวลาเพียงไม่กี่นาทีด้วย TPU สรุป "Codelab Keras บน TPU" ทั้ง 4 รายการ

TPU ในทางปฏิบัติ

TPU และ GPU พร้อมให้บริการใน Cloud AI Platform

สุดท้ายนี้ เรายินดีรับฟังความคิดเห็น โปรดแจ้งให้เราทราบหากพบสิ่งผิดปกติในห้องทดลองนี้หรือหากคุณคิดว่าควรมีการปรับปรุง คุณแสดงความคิดเห็นได้ผ่านปัญหาใน GitHub [feedback link]

HR.png

Martin Görner ID small.jpg
ผู้เขียน: Martin Görner
Twitter: @martin_gorner

tensorflow logo.jpg
www.tensorflow.org