โคตรลาดไล่สีแบบสุ่มตามการดำเนินการของเวกเตอร์


10

สมมติว่าฉันต้องการฝึกอัลกอริธึมการถดถอยแบบไล่ระดับสีแบบสุ่มโดยใช้ชุดข้อมูลที่มีตัวอย่าง N ตัว เนื่องจากขนาดของชุดข้อมูลได้รับการแก้ไขฉันจะใช้ข้อมูล T ครั้ง ในการทำซ้ำแต่ละครั้งหรือ "ยุค" ฉันใช้ตัวอย่างการฝึกอบรมแต่ละครั้งทันทีหลังจากจัดลำดับการฝึกทั้งหมดใหม่แบบสุ่ม

การติดตั้งของฉันนั้นใช้ Python และ Numpy ดังนั้นการใช้การดำเนินการเวกเตอร์สามารถลดเวลาในการคำนวณได้อย่างน่าทึ่ง การหาเวกเตอร์ของการไล่สีแบบแบทช์นั้นค่อนข้างตรงไปตรงมา อย่างไรก็ตามในกรณีของการไล่ระดับสีแบบสุ่มสุ่มฉันไม่สามารถหาวิธีที่จะหลีกเลี่ยงการวนรอบนอกที่วนซ้ำผ่านตัวอย่างทั้งหมดในแต่ละยุค

ไม่มีใครรู้ว่าการใช้เวกเตอร์ของการไล่ระดับสีแบบสุ่มสุ่ม?

แก้ไข : ฉันถูกถามว่าทำไมฉันถึงต้องการใช้การไล่ระดับสีแบบออนไลน์ถ้าขนาดของชุดข้อมูลของฉันได้รับการแก้ไข

จาก [1] เราจะเห็นได้ว่าการไล่ระดับสีแบบออนไลน์นั้นช้ากว่าการไล่ระดับสีแบบแบทช์เป็นค่าต่ำสุดของต้นทุนเชิงประจักษ์ อย่างไรก็ตามมันมาบรรจบกันได้เร็วขึ้นจนถึงค่าต่ำสุดที่คาดไว้ซึ่งวัดประสิทธิภาพทั่วไป ฉันต้องการทดสอบผลกระทบของผลลัพธ์ทางทฤษฎีเหล่านี้ในปัญหาเฉพาะของฉันโดยใช้การตรวจสอบข้าม หากไม่มีการใช้งาน vectorized แล้วโค้ดโคตรลาดของฉันออนไลน์จะช้ากว่าโคตรเกรเดียนต์ของแบทช์ ที่เพิ่มขึ้นอย่างน่าทึ่งเวลาที่ใช้ในกระบวนการตรวจสอบข้ามที่จะแล้วเสร็จ

แก้ไข : ฉันรวมที่นี่ pseudocode ของการดำเนินการสืบเชื้อสายการไล่ระดับสีแบบออนไลน์ของฉันตามที่เพื่อนร้องขอ ฉันกำลังแก้ปัญหาการถดถอย

Method: on-line gradient descent (regression)
Input: X (nxp matrix; each line contains a training sample, represented as a length-p vector), Y (length-n vector; output of the training samples)
Output: A (length-p+1 vector of coefficients)

Initialize coefficients (assign value 0 to all coefficients)
Calculate outputs F
prev_error = inf
error = sum((F-Y)^2)/n
it = 0
while abs(error - prev_error)>ERROR_THRESHOLD and it<=MAX_ITERATIONS:
    Randomly shuffle training samples
    for each training sample i:
        Compute error for training sample i
        Update coefficients based on the error above
    prev_error = error
    Calculate outputs F
    error = sum((F-Y)^2)/n
    it = it + 1

[1] "การเรียนรู้ออนไลน์ขนาดใหญ่", L. Bottou, Y. Le Cunn, NIPS 2003


2
แยกชุดข้อมูลออกเป็นชุดเล็กและพอดีกับแต่ละชุดย่อยตามลำดับ
แฟน

ขอบคุณ @ffriend อย่างไรก็ตามนั่นไม่ได้เป็นการใช้งานออนไลน์อย่างแท้จริง
Pablo Suau

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

ขอโทษสำหรับการตอบกลับช้าของฉัน โปรดตรวจสอบข้อความที่ฉันเพิ่มไปยังคำถามเดิม
Pablo Suau

1
คุณสามารถแสดงการใช้งานของคุณได้หรือไม่? ฉันเห็นความเข้าใจผิด แต่หากไม่มีตัวอย่างโค้ดจะเป็นการยากที่จะอธิบาย
แฟน

คำตอบ:


10

ก่อนอื่นคำว่า "ตัวอย่าง" เป็นคำที่ใช้เพื่ออธิบายกลุ่มย่อยของประชากรดังนั้นฉันจะอ้างถึงสิ่งเดียวกันกับ "ตัวอย่าง"

การใช้งาน SGD ของคุณช้าเนื่องจากบรรทัดนี้:

for each training example i:

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

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

batches = split dataset into mini-batches
for batch in batches: 

และคำนวณข้อผิดพลาดจากแบทช์ไม่ใช่จากตัวอย่างเดียว

แม้ว่าจะค่อนข้างชัดเจน แต่ผมก็ควรพูดถึง vectorization ในระดับต่อตัวอย่าง นั่นคือแทนที่จะเป็นอย่างนี้:

theta = np.array([...])  # parameter vector
x = np.array([...])      # example
y = 0                    # predicted response
for i in range(len(example)):
    y += x[i] * theta[i]
error = (true_y - y) ** 2  # true_y - true value of response

คุณควรทำสิ่งนี้อย่างแน่นอน:

error = (true_y - sum(np.dot(x, theta))) ** 2

ซึ่งอีกครั้งง่ายต่อการทั่วไปสำหรับชุดมินิ:

true_y = np.array([...])     # vector of response values
X = np.array([[...], [...]]) # mini-batch
errors = true_y - sum(np.dot(X, theta), 1)
error = sum(e ** 2 for e in errors)

1
ฉันคิดว่านี่เป็นวิธีที่จะไป มินิแบทช์ที่มีขนาดที่ดีเลือกจริงสามารถมาบรรจบกันได้เร็วขึ้นกว่าทั้งชุดหรือรุ่นออนไลน์ (อดีตปรับปรุงเฉพาะน้ำหนักครั้งเดียวต่อทั้งชุดและไม่หลังสามารถ vectorised บวกมีขั้นตอนการปรับปรุงน้ำหนักที่เพิ่มขึ้นบ่อยขึ้น)
นีลตำหนิ

ขอบคุณทั้งคู่ ขออภัยในการปฏิเสธมินิแบทช์ก่อนหน้านี้ แต่ฉันไม่แน่ใจเกี่ยวกับนัยของวิธีการนี้ในอัตราการบรรจบกัน นีลการยืนยันของคุณมาจากประสบการณ์ของคุณเองหรือมีผลการตีพิมพ์เชิงทฤษฎี / เชิงประจักษ์หรือไม่?
Pablo Suau

1
@PabloSuau คุณสามารถตรวจสอบคลาสการเรียนรู้ของ Machine Ng ของ Andrew Ng ได้ที่ Coursera ในสัปดาห์ที่ 10 เขาอธิบายว่าทำไมการรวมกันจึงเร็วกว่าทั้ง SGD และ batch GD เพื่อความแม่นยำมากขึ้น: ควรรวดเร็วเท่า SGD แต่บางครั้งควรฝึกฝนให้เร็วขึ้น
gaborous

1

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

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.