2011-10-16 30 views
8

Tôi đang cố gắng viết ra một chút mã cho thuật toán gốc gradient giải thích trong bài giảng về Máy học Stanford (lecture 2 at around 25:00). Dưới đây là thực hiện tôi sử dụng lúc đầu, và tôi nghĩ rằng nó được sao chép đúng từ bài giảng, nhưng nó không hội tụ khi tôi thêm số lượng lớn (>8) vào tập huấn luyện.Thuật toán gốc dốc sẽ không hội tụ

Tôi đang nhập một số X, và point (X,X) được thêm vào tập huấn luyện, vì vậy vào lúc này, tôi chỉ cố gắng để làm cho nó hội tụ về y=ax+b nơi a=1=theta\[1\]b=0=theta\[0\]. Bộ đào tạo là mảng xy, trong đó (x[i],y[i]) là một điểm.

void train() 
{ 
    double delta; 
    for (int i = 0; i < x.size(); i++) 
    { 
     delta = y[i]-hypothesis(x[i]); 
     theta[1] += alpha*delta*x[i]; 
     theta[0] += alpha*delta*1; 
    } 
} 

void C_Approx::display() 
{ 
    std::cout<<theta[1]<<"x + "<<theta[0]<<" \t "<<"f(x)="<<hypothesis(1)<<std::endl; 
} 

một số kết quả tôi nhận được: tôi vào một con số, nó chạy train() một vài lần, sau đó display()

1 
0.33616x + 0.33616 f(x)=0.67232 
1 
0.482408x + 0.482408  f(x)=0.964816 
1 
0.499381x + 0.499381  f(x)=0.998762 
1 
0.499993x + 0.499993  f(x)=0.999986 
1 
0.5x + 0.5 f(x)=1 

Một ví dụ về nó phân kỳ sau khi nó trôi qua 8:

1 
0.33616x + 0.33616 f(x)=0.67232 
2 
0.705508x + 0.509914  f(x)=1.21542 
3 
0.850024x + 0.449928  f(x)=1.29995 
4 
0.936062x + 0.330346  f(x)=1.26641 
5 
0.951346x + 0.231295  f(x)=1.18264 
6 
0.992876x + 0.137739  f(x)=1.13062 
7 
0.932206x + 0.127372  f(x)=1.05958 
8 
1.00077x + 0.000493063 f(x)=1.00126 
9 
-0.689325x + -0.0714712  f(x)=-0.760797 
10 
4.10321e+08x + 4.365e+07  f(x)=4.53971e+08 
11 
1.79968e+22x + 1.61125e+21 f(x)=1.9608e+22 
12 
-3.9452e+41x + -3.26957e+40  f(x)=-4.27216e+41 

Tôi đã thử giải pháp được đề xuất here về chia tỷ lệ bước và kết thúc với kết quả tương tự. Tôi đang làm gì sai?

Trả lời

9

Triển khai của bạn tốt. Nói chung, gốc gốc ngẫu nhiên có thể phân kỳ khi α quá lớn. Những gì bạn sẽ làm với một tập dữ liệu lớn là lấy một mẫu ngẫu nhiên có kích thước hợp lý, tìm α cho bạn kết quả tốt nhất, và sau đó sử dụng nó cho phần còn lại.

+0

Bạn sẽ xác định α dựa trên mẫu ngẫu nhiên như thế nào? – howardh

+0

@ howardh, chỉ đơn giản bằng cách thử các giá trị khác nhau và chọn một giá trị hội tụ nhanh đến một J nhỏ (θ). –

+0

Vì vậy, tôi chỉ tạo một tập dữ liệu mới được chọn ngẫu nhiên từ tập huấn luyện ban đầu, gọi train() với tập hợp đó với một số α, và nếu lỗi không giảm theo từng bước, tôi giảm α và lặp lại? – howardh

0

Nếu tôi hiểu chính xác bạn, tập huấn luyện của bạn chỉ có độ dốc khác 0 ở mép của một dòng? Trừ khi bạn bắt đầu ở dòng (thực sự bắt đầu chính xác tại một trong những điểm đào tạo của bạn), bạn sẽ không tìm thấy dòng. Bạn luôn ở mức tối thiểu địa phương.

1

Khi chức năng chi phí của bạn tăng hoặc tăng lên, bạn thường có giá trị quá lớn cho alpha. Bạn đang sử dụng những gì alpha?

Bắt đầu với một số alpha = 0.001 và xem liệu điều đó có hội tụ không? Nếu không thử khác nhau alphas(0.003, 0.01, 0.03, 0.1, 0.3, 1) và tìm thấy một hội tụ nhanh.

Chia tỷ lệ dữ liệu (chuẩn hóa) sẽ không giúp bạn chỉ với 1 tính năng (theta[1]) như bình thường chỉ áp dụng cho 2+ tính năng (hồi quy tuyến tính đa biến).

Cũng lưu ý rằng đối với một số lượng nhỏ các tính năng bạn có thể sử dụng phương trình bình thường để có được câu trả lời đúng.

3

Tôi đã gặp phải cùng một vấn đề (mặc dù trong Java) vì tỷ lệ học tập của tôi quá lớn.
Tóm lại, tôi đã sử dụng α = 0.001 và tôi phải đẩy nó đến 0.000001 để xem sự hội tụ thực tế.

Tất nhiên, các giá trị này được liên kết với tập dữ liệu của bạn.

0

sử dụng tìm kiếm đường theo dõi ngược để bảo đảm hội tụ. Nó rất đơn giản để thực hiện. Xem Stephen Boyd, Tối ưu hóa lồi để tham khảo. Bạn có thể chọn một số giá trị alpha, beta chuẩn cho tìm kiếm dòng ngược, ví dụ: 0,3 và 0,8.

Các vấn đề liên quan