โคตรการไล่ระดับสีแบบสุ่มสามารถประหยัดเวลาได้อย่างไรเมื่อเปรียบเทียบกับการไล่ระดับสีแบบมาตรฐาน


15

Standard Gradient Descent จะคำนวณการไล่ระดับสีสำหรับชุดข้อมูลการฝึกอบรมทั้งหมด

for i in range(nb_epochs):
  params_grad = evaluate_gradient(loss_function, data, params)
  params = params - learning_rate * params_grad

สำหรับจำนวน epoch ที่กำหนดไว้ล่วงหน้าเราจะคำนวณเวกเตอร์ไล่ระดับ weights_grad ของฟังก์ชันการสูญเสียสำหรับชุดข้อมูลทั้งหมด wrt พารามิเตอร์เวกเตอร์พารามิเตอร์ของเรา

ความแตกต่างของการไล่ระดับสีแบบสุ่มสุ่มทำการปรับปรุงพารามิเตอร์สำหรับแต่ละตัวอย่างการฝึกอบรม x (i) และเลเบล y (i)

for i in range(nb_epochs):
  np.random.shuffle(data)
  for example in data:
    params_grad = evaluate_gradient(loss_function, example, params)
    params = params - learning_rate * params_grad

SGD กล่าวกันว่าเร็วกว่ามาก อย่างไรก็ตามฉันไม่เข้าใจว่ามันจะเร็วขึ้นได้อย่างไรถ้าเรายังคงวนรอบจุดข้อมูลทั้งหมด การคำนวณการไล่ระดับสีใน GD นั้นช้ากว่าการคำนวณ GD สำหรับแต่ละจุดข้อมูลแยกกันหรือไม่?

รหัสสินค้ามาจากที่นี่


1
ในกรณีที่สองคุณจะต้องใช้แบทช์ขนาดเล็กเพื่อประมาณชุดข้อมูลทั้งหมด มันใช้งานได้ดีทีเดียว ดังนั้นส่วนที่สับสนอาจดูเหมือนว่าจำนวน epochs เหมือนกันในทั้งสองกรณี แต่คุณไม่ต้องการ epoch หลายตัวในกรณีที่ 2 "hyperparameters" จะแตกต่างกันสำหรับสองวิธี: GD nb_epochs! = SGD nb_epochs สมมติว่าเพื่อจุดประสงค์ของการโต้แย้ง: GD nb_epochs = SGD ตัวอย่าง * nb_epochs ดังนั้นจำนวนลูปทั้งหมดจะเท่ากัน แต่การคำนวณของการไล่ระดับสีนั้นทำได้เร็วกว่าใน SGD
Nima Mousavi

คำตอบสำหรับ CV นี้เป็นคำตอบที่ดีและเกี่ยวข้อง
Zhubarb

คำตอบ:


23

คำตอบสั้น ๆ :

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

คำตอบยาว:

สัญกรณ์ของฉันเป็นไปตามหลักสูตรการเรียนรู้ Coursera ของ Andrew NG หากคุณยังไม่คุ้นเคยกับมันคุณสามารถตรวจสอบการบรรยายชุดที่นี่

สมมติว่าถดถอยจากการสูญเสียกำลังสองฟังก์ชันต้นทุนคือ

J(θ)=12ม.Σผม=1ม.(ชั่วโมงθ(x(ผม))-Y(ผม))2

และการไล่ระดับสีคือ

dJ(θ)dθ=1ม.Σผม=1ม.(ชั่วโมงθ(x(ผม))-Y(ผม))x(ผม)

สำหรับการไล่ระดับสีที่เหมาะสม (GD) เราจะอัปเดตพารามิเตอร์ตาม

θnอีW=θโอล.d-α1ม.Σผม=1ม.(ชั่วโมงθ(x(ผม))-Y(ผม))x(ผม)

1/ม.x(ผม),Y(ผม)

θnอีW=θโอล.d-α(ชั่วโมงθ(x(ผม))-Y(ผม))x(ผม)

นี่คือเหตุผลที่เราประหยัดเวลา:

สมมติว่าเรามีจุดข้อมูล 1 พันล้านจุด

  • ใน GD เพื่ออัปเดตพารามิเตอร์หนึ่งครั้งเราต้องมีการไล่ระดับสี (แน่นอน) ต้องมีการรวมจุดข้อมูล 1 พันล้านจุดเหล่านี้เพื่อดำเนินการอัปเดต 1 รายการ

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

เคล็ดลับคือใน SGD คุณไม่จำเป็นต้องมีการทำซ้ำ / อัปเดต 1 พันล้าน แต่น้อยลงซ้ำ ๆ / อัปเดตพูด 1 ล้านและคุณจะมีรูปแบบ "ดีพอ" ที่จะใช้


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

set.seed(0);n_data=1e3;n_feature=2;
A=matrix(runif(n_data*n_feature),ncol=n_feature)
b=runif(n_data)
res1=solve(t(A) %*% A, t(A) %*% b)

sq_loss<-function(A,b,x){
  e=A %*% x -b
  v=crossprod(e)
  return(v[1])
}

sq_loss_gr_approx<-function(A,b,x){
  # note, in GD, we need to sum over all data
  # here i is just one random index sample
  i=sample(1:n_data, 1)
  gr=2*(crossprod(A[i,],x)-b[i])*A[i,]
  return(gr)
}

x=runif(n_feature)
alpha=0.01
N_iter=300
loss=rep(0,N_iter)

for (i in 1:N_iter){
  x=x-alpha*sq_loss_gr_approx(A,b,x)
  loss[i]=sq_loss(A,b,x)
}

ผลลัพธ์ที่ได้:

as.vector(res1)
[1] 0.4368427 0.3991028
x
[1] 0.3580121 0.4782659

124.1343123.0355

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

ป้อนคำอธิบายรูปภาพที่นี่

ป้อนคำอธิบายรูปภาพที่นี่

1000sq_loss_gr_approx3001000


ฉันคิดว่าการโต้เถียงเกี่ยวกับ "ความเร็ว" นั้นเกี่ยวกับจำนวนการดำเนินการ / การวนซ้ำที่จำเป็นในการรวมเข้าด้วยกันเป็นค่าที่เหมาะสมที่สุดในท้องถิ่น (และเชื้อสายการไล่ระดับสีแบบสุ่มนั้นมีแนวโน้มที่จะลู่เข้าสู่
optima ที่

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

@ GeoMatt22 ในลิงก์ที่ฉันให้ไว้จะมีข้อความระบุว่า: "ในทางกลับกันสิ่งนี้จะทำให้การบรรจบกันมีความซับซ้อนมากที่สุดในท้ายที่สุดเนื่องจาก SGD จะยังคงต้องแก้ไขต่อไป" ความหมายมันไม่ได้มาบรรจบกับ optima ที่ดีกว่า หรือฉันเข้าใจผิด
อลีนา

@Tonja ฉันไม่มีความเชี่ยวชาญ แต่อย่างเช่นบทความที่มีอิทธิพลอย่างสูงในการเรียนรู้อย่างลึกทำให้อาร์กิวเมนต์ "การฝึกอบรมที่เชื่อถือได้รวดเร็วยิ่งขึ้น" สำหรับการไล่ระดับสีแบบสุ่ม โปรดทราบว่ามันไม่ได้ใช้เวอร์ชัน "ดิบ" แต่ใช้การประมาณความโค้งต่าง ๆ เพื่อตั้งค่าอัตราการเรียนรู้ (ขึ้นอยู่กับพิกัด)
GeoMatt22

1
@Tonja ใช่ การประมาณ "อ่อนแอ" ใด ๆ ของการไล่ระดับสีจะทำงาน คุณสามารถตรวจสอบ "การไล่ระดับสีเร่ง" ซึ่งเป็นความคิดที่คล้ายกัน ในทางกลับกันฉันเขียนโค้ดเพื่อสาธิตแนวคิด ฉันจะโพสต์มันเมื่อมันพร้อม
Haitao Du
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.