Bạn đang hơi có chút nhầm lẫn thì phải. Hàm subscribe()được gọi đến từ main thread nên observable gốc sẽ chạy trên main thread. Còn đoạn code nằm trong subscribe() (chú ý là nằm trong) thì sẽ chạy trên thread của operator đứng trc nó nhé bạn.
mình dùng đoạn ''' String folderSaveFile = context.getFilesDir().getAbsolutePath() ''' này thì mọi thứ đã ẩn như mình mong muốn. getFilesDir().getAbsolutePath() là code mình muốn hỏi để ẩn hình, giờ mình đã tìm ra rồi
(y), đúng rồi, ngày trước mình code cũng không biết, cứ tưởng cái nào .equal cũng được.
Về sau, mới biết là cái nào khác null thì nên để ra trước (y).
Còn chuyện trong bài viết, thì đoạn code đó cũng là đoạn ko đẹp, và ko có được approve ,
Mình thấy một vấn đề khá quen thuộc khi training một NN đó là Vanishing Gradients - gradient error sẽ nhỏ dần trong quá trình backpropagation. Đến một thời điểm nào đó connection weights của các layer thấp hơn sẽ không thay đổi (khi sử dụng Gradient Descent chẳng hạn), quá trình trainning sẽ không tìm được một kết quả tốt. Ngược lại nếu gradient lớn dần trong quá trình backpropagation thì sẽ dẫn đến hiện tượng Exploding Gradients - cũng không tốt một chút nào.
Có hai nguyên nhân chính dẫn đến hiện tượng trên:
Sử dụng saturating activation function (ví dụ như signmoid function)
Kĩ thuật khởi tạo các connection weights (weight initialization)
Ví dụ trong trường hợp sigmoid function, khi input lớn thì function sẽ trở nên bão hòa (saturating) tại 0 và 1, đạo hàm rất gần với 0, gradients trong quá trình backpropagation sẽ nhỏ dần khi đến các layer thấp hơn.
ReLU và các biến thể của nó thường được sử dụng thay cho sigmoid function, do nó không có hiện tượng bão hòa và khá nhanh khi tính toán.
ReLU(z)=max(0,z)
Tuy nhiên khi sử dụng ReLU chúng ta gặp phải một hiện tượng đó là Dying ReLUs, khi một số neuron sẽ chỉ cho ra giá trị là 0 trong quá trình trainning (khi connection weights của neuron được update và weighted sum của các inputs nhỏ hơn 0 -> output = 0 -> gradient = 0). Để giải quyết vấn đề này thì chúng ta sẽ dùng một số biến thể của ReLU.
Ở đây alpha có tác dụng điều chỉnh độ dốc của hàm khi z < 0. Thay vì bằng 0 như trong ReLU output sẽ có giá trị thay đổi, tránh được hiện tượng dying ReLUs.
RReLU - Randomized Leaky ReLU
Tương tự như Leaky ReLU nhưng alpha sẽ được chọn ngẫu nhiên trong một khoảng nào đó khi training và được giữ nguyên trong quá trình testing -> tránh được hiện tượng overfitting.
PReLU - Parametric Leaky ReLU
Ở biến thể này thì alpha sẽ được "learn" trong quá trình trainning thay vì là một hyperparameter. Nó hoạt động khá tốt khi dataset lớn nhưng có thể dẫn đến overfitting nếu dataset quá nhỏ.
Một loại activation function khá mới (2017) và có performance rất tốt so với các loại activation function khác.
Kết luận
Thông thường: ELU > Leaky ReLU (và các biến thể của nó) > ReLU > tanh > logistic (signmoid)
Nếu quan tâm đến thời gian training: Leaky ReLUs > ELUs
Thông thường giá trị của alpha sẽ là 0.01 cho leaky ReLU và 1 cho ELU
Sử dụng RReLU nếu model overfitting tập training, PReLU nếu tập training lớn
getANumberObservable() //this will run on main thread
.observeOn(Schedulers.io())
.map(new Func1<Integer, String>() { // this will run on a thread intended for I/O bound
@Override
public String call(Integer integer) {
Log.i("Operator thread", Thread.currentThread().getName());
return String.valueOf(integer);
}
})
.subscribe(new Action1<String>() { // this will run on a thread intended for I/O bound
@Override
public void call(String s) {
Log.i("Subscriber thread", Thread.currentThread().getName());
}
});
Chào bạn.
Cho mình hỏi sample của bạn gọi hàm .observeOn(Schedulers.io()) thì subscribe() sẽ chạy trên RXIOThread, vậy tại sao observable lại chạy trên main vậy,
vì lúc đầu có nói nếu ko để subribeOn() thì mặc định Oservable sẽ chạy trên thread của nào chạy hàm subscribe, mà lúc này nó là RXIOThread
THẢO LUẬN
@bs90 (thankyou) bài viết không có ứng dụng vẹo gì, mình thích thì mình viết thôi =))
@kiendinang Đã vote up! bài viết rất hay. Cho mình hỏi bài toán này có ứng dụng gì trong thực tế không (?)
Viết nốt đi bạn ơi, đang hay lại đứt dây
"Nếu QuickSort là nhanh nhất thì tại sao lại còn phải đẻ ra ti tỉ các loại thuật toán sắp xếp khác làm cái lề gì nhỉ?" :bride_with_veil_tone1:
Bạn đang hơi có chút nhầm lẫn thì phải. Hàm
subscribe()
được gọi đến từ main thread nên observable gốc sẽ chạy trên main thread. Còn đoạn code nằm trongsubscribe()
(chú ý là nằm trong) thì sẽ chạy trên thread của operator đứng trc nó nhé bạn.mình dùng đoạn ''' String folderSaveFile = context.getFilesDir().getAbsolutePath() ''' này thì mọi thứ đã ẩn như mình mong muốn. getFilesDir().getAbsolutePath() là code mình muốn hỏi để ẩn hình, giờ mình đã tìm ra rồi
Hay quá. Bác còn nợ phần 2 nhé
Cuối cùng thì em quyết định dùng https://konvajs.github.io/ http://heasygame.com/games/greenme
Cảm ơn bác
(y), đúng rồi, ngày trước mình code cũng không biết, cứ tưởng cái nào .equal cũng được. Về sau, mới biết là cái nào khác null thì nên để ra trước (y). Còn chuyện trong bài viết, thì đoạn code đó cũng là đoạn ko đẹp, và ko có được approve ,
quá hay anh ơi!!!
Mình thấy một vấn đề khá quen thuộc khi training một NN đó là Vanishing Gradients - gradient error sẽ nhỏ dần trong quá trình backpropagation. Đến một thời điểm nào đó connection weights của các layer thấp hơn sẽ không thay đổi (khi sử dụng Gradient Descent chẳng hạn), quá trình trainning sẽ không tìm được một kết quả tốt. Ngược lại nếu gradient lớn dần trong quá trình backpropagation thì sẽ dẫn đến hiện tượng Exploding Gradients - cũng không tốt một chút nào.
Có hai nguyên nhân chính dẫn đến hiện tượng trên:
Ví dụ trong trường hợp sigmoid function, khi input lớn thì function sẽ trở nên bão hòa (saturating) tại 0 và 1, đạo hàm rất gần với 0, gradients trong quá trình backpropagation sẽ nhỏ dần khi đến các layer thấp hơn.
ReLU và các biến thể của nó thường được sử dụng thay cho sigmoid function, do nó không có hiện tượng bão hòa và khá nhanh khi tính toán.
ReLU(z)=max(0,z)
Tuy nhiên khi sử dụng ReLU chúng ta gặp phải một hiện tượng đó là Dying ReLUs, khi một số neuron sẽ chỉ cho ra giá trị là 0 trong quá trình trainning (khi connection weights của neuron được update và weighted sum của các inputs nhỏ hơn 0 -> output = 0 -> gradient = 0). Để giải quyết vấn đề này thì chúng ta sẽ dùng một số biến thể của ReLU.
Leaky ReLU
Ref: https://en.wikipedia.org/wiki/Rectifier_(neural_networks)#Leaky_ReLUs Ref: https://arxiv.org/pdf/1505.00853.pdf
LeakyReLU(z)=max(αz,z)
Ở đây alpha có tác dụng điều chỉnh độ dốc của hàm khi z < 0. Thay vì bằng 0 như trong ReLU output sẽ có giá trị thay đổi, tránh được hiện tượng dying ReLUs.
RReLU - Randomized Leaky ReLU
Tương tự như Leaky ReLU nhưng alpha sẽ được chọn ngẫu nhiên trong một khoảng nào đó khi training và được giữ nguyên trong quá trình testing -> tránh được hiện tượng overfitting.
PReLU - Parametric Leaky ReLU
Ở biến thể này thì alpha sẽ được "learn" trong quá trình trainning thay vì là một hyperparameter. Nó hoạt động khá tốt khi dataset lớn nhưng có thể dẫn đến overfitting nếu dataset quá nhỏ.
ELU - Exponential Linear Unit
Ref: https://en.wikipedia.org/wiki/Rectifier_(neural_networks)#ELUs
ELU(z)={zα[exp(z)−1]if z>=0otherwise
ELU có performance khá tốt so với các biến thể trước đó của ReLU, với một số cải tiến như sau:
SELU (Scaled Exponential Linear Units)
Ref: https://arxiv.org/pdf/1706.02515.pdf Ref: SELU + Dropout: https://github.com/bioinf-jku/SNNs/blob/master/selu.py
SELU(z)=λ{zα[exp(z)−α]if z>0if z<=0
Một loại activation function khá mới (2017) và có performance rất tốt so với các loại activation function khác.
Kết luận
:slight_smile:
Bài viết hay quá cảm ơn bạn. mà mục 8 chuyện 2 mình thấy nên đổi thành a.equals(input) để tránh NPE nếu input vào là null
Cho mình xin query của bạn
getANumberObservable() //this will run on main thread .observeOn(Schedulers.io()) .map(new Func1<Integer, String>() { // this will run on a thread intended for I/O bound @Override public String call(Integer integer) { Log.i("Operator thread", Thread.currentThread().getName()); return String.valueOf(integer); } }) .subscribe(new Action1<String>() { // this will run on a thread intended for I/O bound @Override public void call(String s) { Log.i("Subscriber thread", Thread.currentThread().getName()); } });
Observable thread: main Operator thread: RxIoScheduler-2 // io Subscriber thread: RxIoScheduler-2 // io
Chào bạn. Cho mình hỏi sample của bạn gọi hàm .observeOn(Schedulers.io()) thì subscribe() sẽ chạy trên RXIOThread, vậy tại sao observable lại chạy trên main vậy, vì lúc đầu có nói nếu ko để subribeOn() thì mặc định Oservable sẽ chạy trên thread của nào chạy hàm subscribe, mà lúc này nó là RXIOThread
greate topic
(y)
Có, hiện tại mình đang sử dụng pycharm cho việc code python và phpstorm phục vụ cho php.
Bạn thử dùng pycharm để code python chưa?
ad đâu rồi hihi