Nguyên nhân phổ biến gây ra tình trạng chập chờn trong quá trình đào tạo


85

Tôi nhận thấy rằng một sự xuất hiện thường xuyên trong quá trình đào tạo đang NANđược giới thiệu.

Thông thường, nó dường như được đưa vào bởi trọng lượng trong các lớp sản phẩm bên trong / được kết nối đầy đủ hoặc tích tụ thổi lên.

Điều này xảy ra có phải do tính toán gradient đang tăng lên không? Hay là do khởi tạo trọng lượng (nếu vậy thì tại sao khởi tạo trọng lượng lại có tác dụng này)? Hay nó có thể do bản chất của dữ liệu đầu vào gây ra?

Câu hỏi bao quát ở đây đơn giản là: Lý do phổ biến nhất khiến NAN xuất hiện trong quá trình đào tạo là gì? Và thứ hai, một số phương pháp để chống lại điều này là gì (và tại sao chúng hoạt động)?


Bạn có đang gọi các hàm MATLAB cụ thể không? Nó có phải là tất cả mã của riêng bạn?
Matthew Gunn

2
@MatthewGunn Tôi không nghĩ câu hỏi này dành riêng cho matlab, mà là tương caffequan.
Shai

Câu trả lời:


134

Câu hỏi hay.
Tôi đã bắt gặp hiện tượng này vài lần. Đây là những quan sát của tôi:


Gradient thổi lên

Lý do: độ dốc lớn khiến quá trình học tập đi chệch hướng.

Những gì bạn nên mong đợi: Nhìn vào nhật ký thời gian chạy, bạn nên xem các giá trị mất mát mỗi lần lặp. Bạn sẽ nhận thấy rằng tổn thất bắt đầu tăng lên đáng kể từ lần lặp lại, cuối cùng tổn thất sẽ quá lớn để được biểu diễn bằng một biến dấu phẩy động và nó sẽ trở thành nan.

Bạn có thể làm gì: Giảm base_lr(trong solver.prototxt) theo thứ tự độ lớn (ít nhất). Nếu bạn có nhiều lớp mất mát, bạn nên kiểm tra nhật ký để xem lớp nào chịu trách nhiệm cho việc thổi tăng độ dốc và giảm loss_weight(trong train_val.prototxt) cho lớp cụ thể đó, thay vì lớp chung base_lr.


Chính sách tỷ lệ học tập kém và các thông số

Lý do: caffe không tính được tỷ lệ học hợp lệ và nhận được 'inf'hoặc 'nan'thay vào đó, tỷ lệ không hợp lệ này sẽ nhân tất cả các bản cập nhật và do đó làm mất hiệu lực của tất cả các thông số.

Những gì bạn nên mong đợi: Nhìn vào nhật ký thời gian chạy, bạn sẽ thấy rằng bản thân tốc độ học tập sẽ trở thành 'nan', ví dụ:

... sgd_solver.cpp:106] Iteration 0, lr = -nan

Bạn có thể làm gì: sửa tất cả các thông số ảnh hưởng đến tốc độ học tập trong 'solver.prototxt'tệp của bạn .
Ví dụ: nếu bạn sử dụng lr_policy: "poly"và bạn quên xác định max_itertham số, bạn sẽ kết thúc với lr = nan...
Để biết thêm thông tin về tốc độ học trong caffe, hãy xem chủ đề này .


Chức năng Mất mát

Lý do: Đôi khi việc tính toán tổn thất trong các lớp tổn thất làm nanxuất hiện s. Ví dụ: InfogainLossLớp cấp dữ liệu với các giá trị không chuẩn hóa , sử dụng lớp mất mát tùy chỉnh có lỗi, v.v.

Những gì bạn nên mong đợi: Nhìn vào nhật ký thời gian chạy, bạn có thể sẽ không nhận thấy bất kỳ điều gì bất thường: tổn thất đang giảm dần và đột nhiên nanxuất hiện.

Bạn có thể làm gì: Xem liệu bạn có thể tái tạo lỗi hay không, thêm bản in vào lớp mất mát và gỡ lỗi.

Ví dụ: Một khi tôi sử dụng lỗ đã chuẩn hóa hình phạt bằng tần suất xuất hiện nhãn trong một đợt. Nó chỉ xảy ra như vậy nếu một trong các nhãn đào tạo hoàn toàn không xuất hiện trong lô - tổn thất được tính toán tạo ra nans. Trong trường hợp đó, làm việc với các lô đủ lớn (đối với số lượng nhãn trong tập hợp) là đủ để tránh lỗi này.


Đầu vào bị lỗi

Lý do: bạn có một đầu vào với nantrong đó!

Những gì bạn nên mong đợi: một khi quá trình học tập "chạm" vào đầu vào - đầu ra bị lỗi này sẽ trở thành nan. Nhìn vào nhật ký thời gian chạy, bạn có thể sẽ không nhận thấy bất cứ điều gì bất thường: tổn thất đang giảm dần và đột nhiên nanxuất hiện.

Bạn có thể làm gì: xây dựng lại bộ dữ liệu đầu vào của mình (lmdb / leveldn / hdf5 ...) đảm bảo rằng bạn không có tệp hình ảnh xấu trong bộ đào tạo / xác thực của mình. Để gỡ lỗi, bạn có thể xây dựng một mạng đơn giản đọc lớp đầu vào, có lỗ giả ở trên và chạy qua tất cả các đầu vào: nếu một trong số chúng bị lỗi, mạng giả này cũng sẽ tạo ra nan.


sải bước lớn hơn kích thước hạt nhân trong "Pooling"lớp

Vì một số lý do, việc chọn stride> kernel_sizeđể gộp có thể dẫn đến nans. Ví dụ:

layer {
  name: "faulty_pooling"
  type: "Pooling"
  bottom: "x"
  top: "y"
  pooling_param {
    pool: AVE
    stride: 5
    kernel: 3
  }
}

kết quả với nans trong y.


Bất ổn trong "BatchNorm"

Người ta báo cáo rằng trong một số "BatchNorm"lớp cài đặt có thể xuất ra nando sự không ổn định về số.
Đây vấn đề được nêu ra trong bvlc / caffe và PR # 5136 đang cố gắng sửa chữa nó.


Gần đây, tôi đã biết về debug_infocờ: thiết lập debug_info: truein 'solver.prototxt'sẽ làm cho bản in caffein để ghi thêm thông tin gỡ lỗi (bao gồm cường độ gradient và giá trị kích hoạt) trong quá trình đào tạo: Thông tin này có thể giúp phát hiện các lỗi gradient và các vấn đề khác trong quá trình đào tạo .


Cảm ơn, làm thế nào để giải thích những con số? Những con số này là gì? pastebin.com/DLYgXK5v tại sao chỉ có một số cho mỗi đầu ra lớp !? Những con số đó nên trông như thế nào để ai đó biết rằng có vấn đề hoặc không có bất kỳ vấn đề nào !?
Rika

@Hossein, đây chính xác là nội dung của bài đăng này.
Shai

Cảm ơn vì câu trả lời này. Tôi đang bị mất NAN cho một ứng dụng phân đoạn hình ảnh được đào tạo với mất DICE (ngay cả sau khi thêm hằng số epsilon / độ mịn nhỏ). Tập dữ liệu của tôi chứa một số hình ảnh có chân đế tương ứng không chứa bất kỳ nhãn tiền cảnh nào và khi tôi xóa những hình ảnh này khỏi quá trình huấn luyện, sự mất mát đã được ổn định. Tôi không chắc tại sao lại như vậy?
samra irshad

@samrairshad Bạn đã thử tăng epsilon khi mất DICE chưa?
Shai

Vâng, tôi đã làm. Tôi đã mở bài đăng tại stack-tràn và dán diễn biến mất mát trong một số kỷ nguyên. Đây là tài liệu tham khảo: stackoverflow.com/questions/62259112/…
samra irshad

5

Trong trường hợp của tôi, không thiết lập độ lệch trong các lớp tích chập / giải mã là nguyên nhân.

Giải pháp: thêm phần sau vào các tham số lớp chập.

bias_filler {type: giá trị "hằng số": 0}


nó sẽ trông như thế nào trong matconvnet? Tôi đã một cái gì đó như 'biases'.init_bias * người (1,4, duy nhất)
h612

4

Câu trả lời này không phải về nguyên nhân nancủa s, mà là đề xuất một cách để giúp gỡ lỗi nó. Bạn có thể có lớp python này:

class checkFiniteLayer(caffe.Layer):
  def setup(self, bottom, top):
    self.prefix = self.param_str
  def reshape(self, bottom, top):
    pass
  def forward(self, bottom, top):
    for i in xrange(len(bottom)):
      isbad = np.sum(1-np.isfinite(bottom[i].data[...]))
      if isbad>0:
        raise Exception("checkFiniteLayer: %s forward pass bottom %d has %.2f%% non-finite elements" %
                        (self.prefix,i,100*float(isbad)/bottom[i].count))
  def backward(self, top, propagate_down, bottom):
    for i in xrange(len(top)):
      if not propagate_down[i]:
        continue
      isf = np.sum(1-np.isfinite(top[i].diff[...]))
        if isf>0:
          raise Exception("checkFiniteLayer: %s backward pass top %d has %.2f%% non-finite elements" %
                          (self.prefix,i,100*float(isf)/top[i].count))

Việc thêm lớp này vào của bạn train_val.prototxttại một số điểm nhất định mà bạn nghi ngờ có thể gây ra rắc rối:

layer {
  type: "Python"
  name: "check_loss"
  bottom: "fc2"
  top: "fc2"  # "in-place" layer
  python_param {
    module: "/path/to/python/file/check_finite_layer.py" # must be in $PYTHONPATH
    layer: "checkFiniteLayer"
    param_str: "prefix-check_loss" # string for printouts
  }
}

1

learning_rate cao và cần được giảm xuống Độ chính xác trong mã RNN là không đáng kể, với việc chọn giá trị thấp cho tốc độ học nó sẽ sửa


-1

Tôi đang cố gắng xây dựng một bộ mã tự động thưa thớt và có một số lớp trong đó để tạo ra sự thưa thớt. Trong khi chạy net của mình, tôi gặp phải NaN's. Khi xóa một số lớp (trong trường hợp của tôi, tôi thực sự phải xóa 1), tôi thấy rằng NaN đã biến mất. Vì vậy, tôi đoán quá nhiều sự thưa thớt cũng có thể dẫn đến NaN (một số phép tính 0/0 có thể đã được sử dụng !?)


bạn có thể cụ thể hơn một chút được không? bạn có thể cung cấp chi tiết về cấu hình đã có nanvà cấu hình cố định không? loại lớp nào? những thông số nào?
Shai

1
@shai Tôi đã sử dụng một số lớp InnerProduct (lr_mult 1, Dec_mult 1, lr_mult 2, Dec_mult 0, xavier, std: 0.01), mỗi lớp tiếp theo là ReLU (trừ lớp cuối cùng). Tôi đã làm việc với MNIST và nếu tôi nhớ không nhầm thì kiến ​​trúc là 784 -> 1000 -> 500 -> 250 -> 100 -> 30 (và một giai đoạn giải mã đối xứng); loại bỏ lớp 30 cùng với ReLU của nó làm cho NaN biến mất.
LKB
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.