ตัวเข้ารหัสอัตโนมัติใน TensorFlow พร้อมตัวอย่าง

⚡ สรุปอย่างชาญฉลาด

Autoencoders บีบอัดข้อมูลอินพุตให้เป็นรูปแบบการแสดงผลภายในที่เล็กลง จากนั้นจึงสร้างมันขึ้นมาใหม่ โดยเรียนรู้คุณลักษณะที่สำคัญที่สุดโดยไม่ต้องใช้ป้ายกำกับ ตัวอย่างนี้แสดงการเรียงซ้อนเลเยอร์ Dense สี่ชั้นใน TensorFlow และสร้างภาพม้า CIFAR-10 ขึ้นมาใหม่

  • 🔘 ตัวเข้ารหัสและตัวถอดรหัส: บล็อกสมมาตรสองบล็อกมาบรรจบกันที่ชั้นการเข้ารหัสแคบๆ ซึ่งบังคับให้เครือข่ายเก็บเฉพาะสัญญาณที่จำเป็นเท่านั้น
  • ☑️ การเตรียมชุดข้อมูล: ชุดภาพ CIFAR-10 จะถูกโหลด แปลงเป็นภาพขาวดำ ซ้อนภาพ และคัดกรองจนเหลือภาพม้า 5,000 ภาพ
  • ท่อส่งอาหาร: ตัวประมาณค่าชุดข้อมูลที่มี from_tensor_slices, repeat และ batch จะจัดหารูปภาพผ่านตัววนซ้ำที่สามารถเริ่มต้นได้
  • 🧪 รูปทรงเครือข่าย: ความกว้างของเลเยอร์มีค่า 1024, 300, 150, 300, 1024 โดยใช้ฟังก์ชันการกระตุ้น ELU, การเริ่มต้นค่าแบบ Xavier และการปรับค่าแบบ L2
  • 🛠️ การตั้งค่าการฝึกอบรม: ค่าความคลาดเคลื่อนกำลังสองเฉลี่ยระหว่างผลลัพธ์และอินพุต โดยใช้ตัวเพิ่มประสิทธิภาพ Adam ขนาดแบทช์ 150 และ 33 รอบต่อยุค
  • 📉 ผลการวัด: ตลอด 100 รอบการฝึกฝน ค่าความสูญเสียในการฝึกฝนลดลงจาก 2,934 เหลือประมาณ 1,454 ก่อนที่จะมีการสร้างกราฟแสดงผลลัพธ์ขึ้นใหม่

ออโตเอนโคเดอร์ในเทนเซอร์โฟล์ค

Autoencoder ใน Deep Learning คืออะไร?

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

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

โปรแกรมเข้ารหัสอัตโนมัติ TensorFlow ทำงานอย่างไร

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

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

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

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

กล่าวโดยสรุป ลองนึกภาพภาพที่มีขนาด 50×50 พิกเซล (เช่น 2,500 พิกเซล) และโครงข่ายประสาทเทียมที่มีเพียงชั้นซ่อนเร้นชั้นเดียวซึ่งประกอบด้วยเซลล์ประสาทหนึ่งร้อยเซลล์ การเรียนรู้เกิดขึ้นบนแผนที่คุณลักษณะซึ่งมีขนาดเล็กกว่าอินพุตถึงยี่สิบห้าเท่า นั่นหมายความว่าโครงข่ายจำเป็นต้องหาวิธีสร้างภาพ 2,500 พิกเซลขึ้นมาใหม่โดยใช้เวกเตอร์ของเซลล์ประสาทเพียง 100 เซลล์เท่านั้น

ตัวอย่างการเข้ารหัสอัตโนมัติแบบซ้อน

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

ปัจจุบัน Autoencoder ใน Deep Learning ส่วนใหญ่ใช้เพื่อลดสัญญาณรบกวนในภาพ ลองนึกภาพภาพที่มีรอยขีดข่วน มนุษย์ยังคงสามารถจดจำเนื้อหาได้ แนวคิดของการใช้ autoencoder ลดสัญญาณรบกวนคือการเพิ่มสัญญาณรบกวนให้กับภาพเพื่อบังคับให้เครือข่ายเรียนรู้รูปแบบที่อยู่เบื้องหลังข้อมูล

ตระกูล Autoencoder ที่มีประโยชน์อีกตระกูลหนึ่งคือ การเรียนรู้ลึก ๆ Variational Autoencoder (VAOC) คือโครงข่ายประสาทเทียมแบบออโตเอนโคเดอร์ (Autoencoder) ประเภทนี้สามารถสร้างภาพใหม่ได้ ลองนึกภาพว่าคุณฝึกโครงข่ายด้วยภาพของผู้ชาย โครงข่ายดังกล่าวสามารถสร้างใบหน้าใหม่ได้

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

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

วิธีสร้างตัวเข้ารหัสอัตโนมัติด้วย TensorFlow

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

คุณจะใช้ชุดข้อมูล CIFAR-10 ซึ่งประกอบด้วยภาพสีขนาด 32x32 จำนวน 60000 ภาพ ชุดข้อมูล Autoencoder ได้ถูกแบ่งออกเป็น 50000 ภาพสำหรับฝึกฝนและ 10000 ภาพสำหรับทดสอบแล้ว โดยมีคลาสสูงสุดสิบคลาส:

  • เครื่องบิน
  • Automobile
  • นก
  • แคท
  • กวาง
  • สุนัข
  • กบ
  • ม้า
  • เรือ
  • รถบรรทุก

คุณต้องดาวน์โหลดรูปภาพจาก หน้าชุดข้อมูล CIFAR-10 และแตกไฟล์ซิป โฟลเดอร์ cifar-10-batches-py จะประกอบด้วยข้อมูลห้าชุด ชุดละ 10000 ภาพ เรียงลำดับแบบสุ่ม

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

  1. นำเข้าข้อมูล
  2. แปลงข้อมูลเป็นรูปแบบขาวดำ
  3. ผนวกแบทช์ทั้งหมด
  4. สร้างชุดข้อมูลการฝึกอบรม
  5. สร้างโปรแกรมสร้างภาพ

หมายเหตุเกี่ยวกับเวอร์ชัน: โค้ดในบทช่วยสอนนี้ใช้กับ TensorFlow 1.x ใน TensorFlow 2 โมดูล tf.contrib ไม่มีอยู่อีกต่อไปแล้ว และ placeholder, session และ initializable iterator จะอยู่ใน tf.compat.v1 การเรียกใช้ tf.compat.v1.disable_v2_behavior() หลังจากนำเข้าโมดูลเป็นวิธีที่เร็วที่สุดในการรันโค้ดโดยไม่เปลี่ยนแปลง

การประมวลผลภาพล่วงหน้า

ขั้นตอนที่ 1) นำเข้าข้อมูล

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

import numpy as np
import tensorflow as tf
import pickle
def unpickle(file):
    import pickle
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='latin1')
    return dict

ขั้นตอนที่ 2) แปลงข้อมูลเป็นรูปแบบขาวดำ

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

def grayscale(im):
    return im.reshape(im.shape[0], 3, 32, 32).mean(1).reshape(im.shape[0], -1)

ขั้นตอนที่ 3) ผนวกชุดงานทั้งหมด

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

เมื่อทำขั้นตอนนี้เสร็จแล้ว คุณจะแปลงข้อมูลสีเป็นรูปแบบขาวดำ ดังที่คุณเห็น รูปทรงของข้อมูลคือ 50000 และ 1024 พิกเซล ขนาด 32*32 ถูกรวมเข้าเป็น 1024 แล้ว

# Load the data into memory
data, labels = [], []
## Loop over the b
for i in range(1, 6):
    filename = './cifar-10-batches-py/data_batch_' + str(i)
    open_data = unpickle(filename)
    if len(data) > 0:
        data = np.vstack((data, open_data['data']))
        labels = np.hstack((labels, open_data['labels']))
    else:
        data = open_data['data']
        labels = open_data['labels']

data = grayscale(data)
x = np.matrix(data)
y = np.array(labels)
print(x.shape)
(50000, 1024)

หมายเหตุ เปลี่ยน './cifar-10-batches-py/data_batch_' เป็นตำแหน่งที่ตั้งจริงของไฟล์ของคุณ ตัวอย่างเช่น สำหรับไฟล์ Windows เครื่อง เส้นทางอาจเป็น filename = 'E:\cifar-10-batches-py\data_batch_' + str(i)

ขั้นตอนที่ 4) สร้างชุดข้อมูลการฝึกอบรม

เพื่อให้การฝึกฝนรวดเร็วและง่ายขึ้น คุณจะฝึกฝนโมเดลโดยใช้เฉพาะภาพม้าเท่านั้น ม้ามีป้ายกำกับหมายเลข 7 ในข้อมูลป้ายกำกับ ดังที่ระบุไว้ในเอกสารประกอบของชุดข้อมูล CIFAR-10 แต่ละคลาสประกอบด้วยภาพ 5000 ภาพ คุณสามารถพิมพ์โครงสร้างของข้อมูลเพื่อยืนยันว่ามีภาพ 5,000 ภาพและ 1024 คอลัมน์ ดังแสดงในขั้นตอนตัวอย่าง TensorFlow Autoencoder ด้านล่าง

horse_i = np.where(y == 7)[0]
horse_x = x[horse_i]
print(np.shape(horse_x)) 
(5000, 1024)

ขั้นตอนที่ 5) สร้างโปรแกรมสร้างภาพ

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

วิธีง่ายๆ ในการแสดงภาพคือการใช้ฟังก์ชัน imshow() จากไลบรารี Matplotlib โปรดทราบว่า คุณต้องแปลงขนาดของข้อมูลจาก 1024 เป็น 32*32 (เช่น รูปแบบของภาพ)

# To plot pretty figures
%matplotlib inline
import matplotlib
import matplotlib.pyplot as plt
def plot_image(image, shape=[32, 32], cmap = "Greys_r"):
    plt.imshow(image.reshape(shape), cmap=cmap,interpolation="nearest")
    plt.axis("off")   

ฟังก์ชันรับ 3 อาร์กิวเมนต์:

  • รูปภาพ: ข้อมูลนำเข้า
  • รูปร่าง: รายการแสดงขนาดของภาพ
  • Cmap: เลือกแผนที่สี โดยค่าเริ่มต้นจะเป็นสีเทา

คุณสามารถลองพล็อตรูปภาพแรกในชุดข้อมูลได้ คุณควรเห็นชายคนหนึ่งขี่ม้า

plot_image(horse_x[1], shape=[32, 32], cmap = "Greys_r")

คำสั่งนี้แสดงภาพขนาดย่อขาวดำดังที่แสดงด้านล่าง และยืนยันว่าการปรับรูปร่างจากค่า 1024 กลับไปเป็นภาพขนาด 32×32 นั้นถูกต้อง

ภาพขาวดำขนาด 32x32 พิกเซล รูปแบบ CIFAR-10 แสดงภาพคนขี่ม้าที่วาดด้วยฟังก์ชัน plot_image()

ตั้งค่าตัวประมาณการชุดข้อมูล

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

คุณจะสร้างชุดข้อมูลด้วยตัวประมาณค่า TensorFlow เพื่อฟื้นฟูจิตใจของคุณ คุณต้องใช้:

  • จาก_tensor_slices
  • ทำซ้ำ
  • ชุด

รหัสเต็มในการสร้างชุดข้อมูลคือ:

dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)

โปรดทราบว่า x เป็นตัวแปรแทนที่มีรูปร่าง [None,n_inputs] มิติแรกถูกตั้งค่าเป็น None เนื่องจากจำนวนภาพที่ป้อนเข้าสู่เครือข่ายเท่ากับขนาดแบทช์ ซึ่งจะถูกกำหนดในระหว่างการทำงานเท่านั้น สำหรับรายละเอียดเพิ่มเติม โปรดดูบทช่วยสอนเกี่ยวกับ การถดถอยเชิงเส้นด้วย TensorFlow.

หลังจากนั้นคุณจะต้องสร้างตัววนซ้ำ หากไม่มีโค้ดบรรทัดนี้ จะไม่มีข้อมูลใดผ่านไปป์ไลน์

iter = dataset.make_initializable_iterator() # create the iteratorfeatures = iter.get_next()

ตอนนี้ไปป์ไลน์พร้อมแล้ว คุณสามารถตรวจสอบได้ว่าภาพแรกเหมือนเดิมหรือไม่ (เช่น คนขี่ม้า)

คุณตั้งค่าขนาดแบทช์เป็น 1 เพราะคุณต้องการป้อนภาพเพียงภาพเดียวลงในชุดข้อมูล คุณสามารถดูขนาดของข้อมูลได้ด้วยคำสั่ง print(sess.run(features).shape) ซึ่งจะมีค่าเท่ากับ (1, 1024) เลข 1 หมายความว่าภาพเดียวที่มีค่า 1024 จะถูกป้อนเข้าไปในแต่ละครั้ง หากตั้งค่าขนาดแบทช์เป็น 2 ภาพสองภาพจะถูกส่งผ่านไปป์ไลน์ อย่าเปลี่ยนขนาดแบทช์ มิฉะนั้นจะเกิดข้อผิดพลาด เพราะมีเพียงภาพเดียวเท่านั้นที่สามารถส่งไปยังฟังก์ชัน plot_image() ได้ในแต่ละครั้ง

## Parameters
n_inputs = 32 * 32
BATCH_SIZE = 1
batch_size = tf.placeholder(tf.int64)

# using a placeholder
x = tf.placeholder(tf.float32, shape=[None,n_inputs])
## Dataset
dataset = tf.data.Dataset.from_tensor_slices(x).repeat().batch(batch_size)
iter = dataset.make_initializable_iterator() # create the iterator
features = iter.get_next()

## Print the image
with tf.Session() as sess:
    # feed the placeholder with data
    sess.run(iter.initializer, feed_dict={x: horse_x,
                                         batch_size: BATCH_SIZE}) 
    print(sess.run(features).shape) 
    plot_image(sess.run(features), shape=[32, 32], cmap = "Greys_r")
(1, 1024)

ไปป์ไลน์ส่งคืนค่า rider เดียวกันกับที่พล็อตโดยตรงจากเมทริกซ์ NumPy ซึ่งพิสูจน์ได้ว่า placeholder, iterator และ batch size เชื่อมต่อกันอย่างถูกต้อง

ภาพย่อของม้าตัวเดียวกันถูกพิมพ์หลังจากที่ภาพผ่านตัววนซ้ำของชุดข้อมูล TensorFlow

สร้างเครือข่าย

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

เครือข่ายของคุณจะมีเลเยอร์อินพุตหนึ่งเลเยอร์ที่มี 1024 จุด หรือก็คือขนาด 32×32 ซึ่งเป็นรูปร่างของภาพ

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

สถาปัตยกรรมออโตเอนโคเดอร์แบบสมมาตรที่มีอินพุต 1024 ตัว เลเยอร์เอนโคเดอร์ 300 และ 150 ยูนิต และดีโคเดอร์แบบมิเรอร์

การสร้างเครือข่ายสำหรับ Autoencoder

การสร้างโปรแกรมเข้ารหัสอัตโนมัตินั้นคล้ายคลึงกับโมเดลการเรียนรู้เชิงลึกอื่นๆ มาก

คุณจะสร้างแบบจำลองโดยทำตามขั้นตอนเหล่านี้:

  1. กำหนดพารามิเตอร์
  2. กำหนดเลเยอร์
  3. กำหนดสถาปัตยกรรม
  4. กำหนดการเพิ่มประสิทธิภาพ
  5. เรียกใช้โมเดล
  6. ประเมินแบบจำลอง

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

ขั้นตอนที่ 1) กำหนดพารามิเตอร์

ขั้นตอนแรกหมายถึงการกำหนดจำนวนเซลล์ประสาทในแต่ละชั้น อัตราการเรียนรู้ และไฮเปอร์พารามิเตอร์ของเรกูลาร์ไลเซอร์

ก่อนหน้านั้น คุณต้องนำเข้าฟังก์ชันบางส่วนก่อน นี่เป็นวิธีการที่ดีกว่าในการกำหนดพารามิเตอร์ของเลเยอร์หนาแน่น โค้ดด้านล่างกำหนดค่าของสถาปัตยกรรมออโตเอนโคเดอร์ ดังที่ได้กล่าวไว้ก่อนหน้านี้ เอนโคเดอร์มีสองชั้น โดยมี 300 นิวรอนในชั้นแรกและ 150 นิวรอนในชั้นที่สอง ค่าของพวกมันถูกเก็บไว้ใน n_hidden_1 และ n_hidden_2

คุณต้องกำหนดอัตราการเรียนรู้และพารามิเตอร์ L2 โดยค่าต่างๆ จะถูกเก็บไว้ในตัวแปร learning_rate และ l2_reg

from functools import partial

## Encoder
n_hidden_1 = 300
n_hidden_2 = 150  # codings

## Decoder
n_hidden_3 = n_hidden_1
n_outputs = n_inputs

learning_rate = 0.01
l2_reg = 0.0001

เทคนิคการเริ่มต้นแบบ Xavier จะถูกเรียกใช้ด้วยอ็อบเจ็กต์ xavier_initializer จาก contrib ของตัวประมาณค่า ในตัวประมาณค่าเดียวกันนี้ คุณสามารถเพิ่ม regularizer ด้วย l2_regularizer ได้

## Define the Xavier initialization
xav_init =  tf.contrib.layers.xavier_initializer()
## Define the L2 regularizer
l2_regularizer = tf.contrib.layers.l2_regularizer(l2_reg)

หมายเหตุเกี่ยวกับเวอร์ชัน: tf.contrib ถูกลบออกใน TensorFlow 2 แล้ว ฟังก์ชันทดแทนโดยตรงคือ tf.keras.initializers.GlorotUniform() สำหรับ xavier_initializer() และ tf.keras.regularizers.l2() สำหรับ l2_regularizer()

ขั้นตอนที่ 2) กำหนดเลเยอร์

พารามิเตอร์ทั้งหมดของเลเยอร์หนาแน่นได้รับการตั้งค่าแล้ว คุณสามารถบรรจุทุกอย่างลงในตัวแปร dense_layer โดยใช้ object partial จากนั้น dense_layer จะใช้การเปิดใช้งาน ELU การเริ่มต้น Xavier และการปรับค่า L2 ในทุกการเรียกใช้

## Create the dense layer
dense_layer = partial(tf.layers.dense,
                         activation=tf.nn.elu,
                         kernel_initializer=xav_init,
                         kernel_regularizer=l2_regularizer)

ขั้นตอนที่ 3) กำหนดโครงสร้างสถาปัตยกรรม

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

## Make the mat mul
hidden_1 = dense_layer(features, n_hidden_1)
hidden_2 = dense_layer(hidden_1, n_hidden_2)
hidden_3 = dense_layer(hidden_2, n_hidden_3)
outputs = dense_layer(hidden_3, n_outputs, activation=None)

ขั้นตอนที่ 4) กำหนดการเพิ่มประสิทธิภาพ

ขั้นตอนสุดท้ายคือการสร้างตัวปรับแต่ง (optimizer) คุณใช้ค่าความคลาดเคลื่อนกำลังสองเฉลี่ย (Mean Square Error หรือ MSE) เป็นฟังก์ชันความสูญเสีย หากคุณจำบทเรียนเกี่ยวกับการถดถอยเชิงเส้นได้ คุณจะรู้ว่า MSE คำนวณจากความแตกต่างระหว่างผลลัพธ์ที่คาดการณ์ไว้กับป้ายกำกับจริง ในที่นี้ ป้ายกำกับคือคุณลักษณะ (feature) เพราะแบบจำลองพยายามสร้างอินพุตขึ้นมาใหม่ ดังนั้น คุณต้องการค่าเฉลี่ยของผลรวมของความแตกต่างกำลังสองระหว่างผลลัพธ์ที่คาดการณ์ไว้กับอินพุต ด้วย TensorFlow คุณสามารถเขียนโค้ดฟังก์ชันความสูญเสียได้ดังนี้:

loss = tf.reduce_mean(tf.square(outputs - features))

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

## Optimize
loss = tf.reduce_mean(tf.square(outputs - features))
optimizer = tf.train.AdamOptimizer(learning_rate)
train  = optimizer.minimize(loss)

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

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

BATCH_SIZE = 150
### Number of batches :  length dataset / batch size
n_batches = horse_x.shape[0] // BATCH_SIZE
print(n_batches)
33

ขั้นตอนที่ 5) รันโมเดล

สุดท้ายนี้ ให้ฝึกโมเดล คุณจะฝึกโมเดลด้วยจำนวน 100 รอบ นั่นหมายความว่าโมเดลจะเห็นภาพ 100 ครั้งในขณะที่ปรับค่าถ่วงน้ำหนักให้เหมาะสม

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

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

## Set params
n_epochs = 100

## Call Saver to save the model and re-use it later during evaluation
saver = tf.train.Saver()

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    # initialise iterator with train data
    sess.run(iter.initializer, feed_dict={x: horse_x,
                                          batch_size: BATCH_SIZE})
    print('Training...')
    print(sess.run(features).shape) 
    for epoch in range(n_epochs):       
        for iteration in range(n_batches):
            sess.run(train)
        if epoch % 10 == 0:
            loss_train = loss.eval()   # not shown
            print("\r{}".format(epoch), "Train MSE:", loss_train) 
        #saver.save(sess, "./my_model_all_layers.ckpt") 
    save_path = saver.save(sess, "./model.ckpt")    
    print("Model saved in path: %s" % save_path)  
Training...
(150, 1024)
0 Train MSE: 2934.455
10 Train MSE: 1672.676
20 Train MSE: 1514.709
30 Train MSE: 1404.3118
40 Train MSE: 1425.058
50 Train MSE: 1479.0631
60 Train MSE: 1609.5259
70 Train MSE: 1482.3223
80 Train MSE: 1445.7035
90 Train MSE: 1453.8597
Model saved in path: ./model.ckpt

ขั้นตอนที่ 6) ประเมินแบบจำลอง

เมื่อคุณฝึกฝนโมเดลเสร็จแล้ว ก็ถึงเวลาประเมินผล คุณต้องนำเข้าชุดข้อมูลทดสอบจากไฟล์ /cifar-10-batches-py/

test_data = unpickle('./cifar-10-batches-py/test_batch')
test_x = grayscale(test_data['data'])
#test_labels = np.array(test_data['labels'])

หมายเหตุ สำหรับ Windows เครื่อง รหัสจะกลายเป็น test_data = unpickle(r”E:\cifar-10-batches-py\test_batch”)

คุณสามารถลองพิมพ์ภาพที่ 13 ซึ่งเป็นภาพม้าได้

plot_image(test_x[13], shape=[32, 32], cmap = "Greys_r")

กราฟยืนยันว่าชุดข้อมูลทดสอบโหลดได้อย่างถูกต้อง และภาพที่ 13 อยู่ในกลุ่มเดียวกับที่ใช้ฝึกโมเดล

ภาพทดสอบหมายเลข 13 จากชุดทดสอบ CIFAR-10 แสดงภาพม้าในโทนสีเทา

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

ฟังก์ชันรับสองอาร์กิวเมนต์:

  • df: นำเข้าข้อมูลทดสอบ
  • image_number: ระบุหมายเลขรูปภาพที่จะนำเข้า

ฟังก์ชั่นแบ่งออกเป็นสามส่วน:

  1. ปรับรูปร่างรูปภาพให้เป็นมิติที่ถูกต้อง เช่น 1, 1024
  2. ป้อนโมเดลด้วยภาพที่มองไม่เห็น เข้ารหัส/ถอดรหัสรูปภาพ
  3. พิมพ์ภาพจริงและสร้างใหม่
def reconstruct_image(df, image_number = 1):
    ## Part 1: Reshape the image to the correct dimension i.e 1, 1024
    x_test = df[image_number]
    x_test_1 = x_test.reshape((1, 32*32))
    
    ## Part 2: Feed the model with the unseen image, encode/decode the image
    with tf.Session() as sess:     
        sess.run(tf.global_variables_initializer()) 
        sess.run(iter.initializer, feed_dict={x: x_test_1,
                                      batch_size: 1})
    ## Part 3:  Print the real and reconstructed image
      # Restore variables from disk.
        saver.restore(sess, "./model.ckpt")  
        print("Model restored.")
      # Reconstruct image
        outputs_val = outputs.eval()
        print(outputs_val.shape)
        fig = plt.figure()
      # Plot real
        ax1 = fig.add_subplot(121)
        plot_image(x_test_1, shape=[32, 32], cmap = "Greys_r")
      # Plot estimated
        ax2 = fig.add_subplot(122)
        plot_image(outputs_val, shape=[32, 32], cmap = "Greys_r")
        plt.tight_layout()
        fig = plt.gcf()

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

reconstruct_image(df =test_x, image_number = 13)
INFO:tensorflow:Restoring parameters from ./model.ckpt
Model restored.
(1, 1024)

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

การเปรียบเทียบภาพม้าต้นฉบับกับภาพที่สร้างขึ้นใหม่ด้วยออโตเอนโคเดอร์ซึ่งมีความเบลอมากกว่า

คำถามที่พบบ่อย

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

ไม่ได้เหมือนเดิม โมดูล tf.contrib ถูกลบออก และตัวยึดตำแหน่งและเซสชันถูกย้ายไปยัง tf.compat.v1 การเพิ่ม disable_v2_behavior() ช่วยให้การแสดงรายการทำได้อย่างรวดเร็ว ในขณะที่ฟังก์ชันเนทีฟ TensorFlow 2. การเขียนใหม่ใช้ tf.keras.layers.Dense ร่วมกับการเริ่มต้นใช้งาน GlorotUniform

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

ใช่. นักบิน GitHub ร่างโครงสร้างสมมาตรของตัวเข้ารหัสและตัวถอดรหัส ลูปการฝึกฝน และตัวช่วยในการสร้างกราฟจากข้อความแสดงความคิดเห็นสั้นๆ โดยตัดส่วนที่ไม่จำเป็นออกไปส่วนใหญ่ ตรวจสอบรูปร่างของเทนเซอร์และคำจำกัดความของฟังก์ชันความสูญเสียด้วยตนเอง เนื่องจากโค้ดที่สร้างขึ้นมักผสมผสานไวยากรณ์ของ TensorFlow 1 และ 2 เข้าด้วยกัน

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

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

จำนวนการพิมพ์ลดลงจาก 2,934 เหลือประมาณ 1,404 เมื่อถึงรอบที่ 30 จากนั้นจะแกว่งไปมาระหว่าง 1,425 ถึง 1,609 อัตราการเรียนรู้คงที่ที่ 0.01 นั้นสูงเกินไปกว่าค่าต่ำสุด ณ จุดนั้น การลดอัตราการเรียนรู้หรือการเพิ่มตารางการลดอัตราการเรียนรู้มักจะช่วยให้ได้ผลลัพธ์ที่ดีขึ้น

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

สรุปโพสต์นี้ด้วย: