Câu trả lời ngắn:
- Trong nhiều cài đặt dữ liệu lớn (giả sử vài triệu điểm dữ liệu), việc tính toán chi phí hoặc độ dốc mất rất nhiều thời gian, bởi vì chúng ta cần tổng hợp trên tất cả các điểm dữ liệu.
- Chúng ta KHÔNG cần phải có độ dốc chính xác để giảm chi phí trong một lần lặp nhất định. Một số xấp xỉ của gradient sẽ hoạt động tốt.
- Độ dốc màu ngẫu nhiên (SGD) xấp xỉ độ dốc chỉ sử dụng một điểm dữ liệu. Vì vậy, việc đánh giá độ dốc giúp tiết kiệm rất nhiều thời gian so với tổng hợp trên tất cả dữ liệu.
- Với số lần lặp "hợp lý" (con số này có thể là vài nghìn và ít hơn nhiều so với số điểm dữ liệu có thể là hàng triệu), độ dốc ngẫu nhiên có thể có được một giải pháp tốt hợp lý.
Câu trả lời dài:
Ký hiệu của tôi theo khóa học Coursera của Andrew NG. Nếu bạn không quen thuộc với nó, bạn có thể xem lại chuỗi bài giảng ở đây .
Giả sử hồi quy về tổn thất bình phương, hàm chi phí là
J( θ ) = 12 mΣi = 1m( hθ( x( tôi )) - y( tôi ))2
và độ dốc là
dJ( θ )dθ= 1mΣi = 1m( hθ( x( tôi )) - y( tôi )) x( tôi )
đối với độ dốc tốt (GD), chúng tôi cập nhật tham số bằng
θn e w= θo l d- α 1mΣi = 1m( hθ( x( tôi )) - y( tôi )) x( tôi )
1 / mx( tôi ), y( tôi )
θn e w= θo l d- α ⋅ ( hθ( x( tôi )) - y( tôi )) x( tôi )
Đây là lý do tại sao chúng tôi đang tiết kiệm thời gian:
Giả sử chúng ta có 1 tỷ điểm dữ liệu.
Trong GD, để cập nhật các tham số một lần, chúng ta cần phải có độ dốc (chính xác). Điều này đòi hỏi phải tổng hợp 1 tỷ điểm dữ liệu này để thực hiện 1 cập nhật.
Trong SGD, chúng ta có thể nghĩ về nó như cố gắng để có được một gradient xấp xỉ thay vì gradient chính xác . Phép tính gần đúng đến từ một điểm dữ liệu (hoặc một số điểm dữ liệu được gọi là lô nhỏ). Do đó, trong SGD, chúng tôi có thể cập nhật các thông số rất nhanh. Ngoài ra, nếu chúng tôi "lặp lại" tất cả dữ liệu (được gọi là một epoch), chúng tôi thực sự có 1 tỷ cập nhật.
Mẹo nhỏ là, trong SGD, bạn không cần phải có 1 tỷ lần lặp / cập nhật, nhưng số lần lặp / cập nhật ít hơn nhiều, giả sử là 1 triệu và bạn sẽ có mô hình "đủ tốt" để sử dụng.
Tôi đang viết một mã để demo ý tưởng. Đầu tiên chúng ta giải hệ phương trình tuyến tính bằng phương trình bình thường, sau đó giải nó bằng SGD. Sau đó, chúng tôi so sánh các kết quả về các giá trị tham số và giá trị hàm mục tiêu cuối cùng. Để hình dung nó sau, chúng ta sẽ có 2 tham số để điều chỉnh.
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)
}
Kết quả:
as.vector(res1)
[1] 0.4368427 0.3991028
x
[1] 0.3580121 0.4782659
124.143123.0355
Dưới đây là các giá trị hàm chi phí qua các lần lặp, chúng ta có thể thấy nó có thể giảm tổn thất một cách hiệu quả, điều này minh họa ý tưởng: chúng ta có thể sử dụng một tập hợp con dữ liệu để xấp xỉ độ dốc và nhận được kết quả "đủ tốt".
1000sq_loss_gr_approx
3001000