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

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

688858c21e3beff2.png

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

c3df49e90e5a654f.png Welcome to Colab.ipynb

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

8832c6208c99687d.png

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

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

76d05caa8b4db6da.png

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

สารบัญ

429f106990037ec4.png

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

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

edc3dba45d26f12a.png

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

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

cdd4b41413100543.png

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

3. [ข้อมูล] 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 1 คอลัมน์เพื่อยืนยันว่าฟังก์ชันนี้จะหาผลรวมแบบถ่วงน้ำหนักของค่าพิกเซลทั้งหมดของรูปภาพ เลเยอร์ 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 จะใช้การคูณเมทริกซ์ในฮาร์ดแวร์โดยใช้สถาปัตยกรรมที่เรียกว่า "systolic array" ซึ่งองค์ประกอบข้อมูลจะไหลผ่านอาร์เรย์ของหน่วยการคำนวณฮาร์ดแวร์ (ในทางการแพทย์ "ซิสโทลิก" หมายถึงการบีบตัวของหัวใจและการไหลเวียนของเลือด แต่ในที่นี้หมายถึงการไหลเวียนของข้อมูล)

องค์ประกอบพื้นฐานของการคูณเมทริกซ์คือผลคูณจุดระหว่างแถวจากเมทริกซ์หนึ่งกับคอลัมน์จากเมทริกซ์อีกเมทริกซ์หนึ่ง (ดูภาพที่ด้านบนของส่วนนี้) สำหรับการคูณเมทริกซ์ 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 แบบ 2 คอร์ 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 มิติของ Google TPU

ซอฟต์แวร์

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

ขนาดกลุ่มที่เหมาะสมสำหรับ 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 (Accelerated Linear Algebra Compiler) ก่อน จากนั้น 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 สำหรับการเรียนรู้เชิงลึกที่สร้างผ่านยูทิลิตี "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. [INFO] ตัวแยกประเภทโครงข่ายระบบประสาทเทียมเบื้องต้น

ข้อมูลโดยสรุป

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

สำหรับโมเดลที่สร้างเป็นลำดับของเลเยอร์ 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 สำหรับหน่วยเชิงเส้นที่แก้ไขแล้ว ฟังก์ชันนี้ใช้งานง่ายมาก ดังที่เห็นในกราฟด้านบน

ฟังก์ชัน Softmax

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

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

ef0d98c0952c262d.png d51252f75894479e.gif

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

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

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

7bdf8753d20617fb.png

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

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

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

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

gradient descent2.png

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

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

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

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

52e824fe4716c4a0.png

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

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

อภิธานศัพท์

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

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

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

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

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

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

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

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

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

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

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

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

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

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

5. [INFO] โครงข่ายประสาทแบบ Convolution

ข้อมูลโดยสรุป

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

convolutional.gif

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

โครงข่ายระบบประสาทเทียมแบบ Convolution อย่างง่ายใน 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 ชุด (หรือมากกว่า) เป็น Tensor เดียวได้โดยการเพิ่มมิติข้อมูลใหม่ ซึ่งจะทำให้เราได้รูปร่างทั่วไปของเทนเซอร์น้ำหนักสำหรับเลเยอร์ Convolutional เนื่องจากจำนวนช่องอินพุตและเอาต์พุตเป็นพารามิเตอร์ เราจึงเริ่มซ้อนและเชื่อมโยงเลเยอร์ Convolutional ได้

d1b557707bcd1cb9.png

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

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

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

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

2b2d4263bb8470b.gif

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

ตัวแยกประเภทแบบ Convolutions

สุดท้าย เราจะแนบส่วนหัวของการจัดประเภทโดยการทำให้คิวบ์ข้อมูลสุดท้ายแบนราบและป้อนผ่านเลเยอร์ที่หนาแน่นซึ่งเปิดใช้งาน 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.pngad795b70334e0d6b.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 ปกติ และพบว่ามีประสิทธิภาพเท่ากันในทางปฏิบัติ ต่อไปนี้คือจำนวนน้ำหนักสำหรับตัวอย่างที่แสดงด้านบน

เลเยอร์ Convolution: 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