Kiểm tra đơn vị là bạn của bạn
Có một câu nói của các nhà văn rằng "Tất cả các văn bản là viết lại" - đó là, phần lớn hơn của văn bản đang sửa đổi. Đối với các lập trình viên (hoặc ít nhất là các nhà khoa học dữ liệu), biểu thức có thể được đặt lại thành cụm từ "Tất cả mã hóa là gỡ lỗi."
Bất cứ khi nào bạn viết mã, bạn cần xác minh rằng nó hoạt động như dự định. Phương pháp tốt nhất tôi từng tìm thấy để xác minh tính chính xác là chia mã của bạn thành các phân đoạn nhỏ và xác minh rằng mỗi phân đoạn hoạt động. Điều này có thể được thực hiện bằng cách so sánh đầu ra phân khúc với những gì bạn biết là câu trả lời chính xác. Điều này được gọi là thử nghiệm đơn vị . Viết bài kiểm tra đơn vị tốt là một phần quan trọng để trở thành một nhà thống kê / nhà khoa học dữ liệu / chuyên gia học máy / chuyên gia mạng lưới thần kinh giỏi. Đơn giản là không có sự thay thế.
Bạn phải kiểm tra xem mã của bạn không có lỗi trước khi bạn có thể điều chỉnh hiệu suất mạng! Nếu không, bạn cũng có thể sắp xếp lại các ghế trên RMS Titanic .
Có hai tính năng của mạng nơ-ron khiến việc xác minh thậm chí còn quan trọng hơn so với các loại mô hình thống kê hoặc học máy khác.
Các mạng nơ-ron không phải là thuật toán "ngoài luồng" theo cách hồi quy rừng hoặc logistic ngẫu nhiên. Ngay cả đối với các mạng đơn giản, chuyển tiếp nguồn cấp dữ liệu, phần lớn người dùng sẽ đưa ra nhiều quyết định về cách cấu hình, kết nối, khởi tạo và tối ưu hóa mạng. Điều này có nghĩa là viết mã, và viết mã có nghĩa là gỡ lỗi.
Ngay cả khi một mã mạng thần kinh thực thi mà không đưa ra một ngoại lệ, mạng vẫn có thể có lỗi! Những lỗi này thậm chí có thể là loại xảo quyệt mà mạng sẽ đào tạo, nhưng bị mắc kẹt ở một giải pháp tối ưu phụ, hoặc mạng kết quả không có kiến trúc mong muốn. ( Đây là một ví dụ về sự khác biệt giữa lỗi cú pháp và ngữ nghĩa .)
Bài trung bình này , " Cách kiểm tra mã máy học ," của Chase Roberts thảo luận về kiểm thử đơn vị cho các mô hình học máy chi tiết hơn. Tôi đã mượn ví dụ này về mã lỗi từ bài viết:
def make_convnet(input_image):
net = slim.conv2d(input_image, 32, [11, 11], scope="conv1_11x11")
net = slim.conv2d(input_image, 64, [5, 5], scope="conv2_5x5")
net = slim.max_pool2d(net, [4, 4], stride=4, scope='pool1')
net = slim.conv2d(input_image, 64, [5, 5], scope="conv3_5x5")
net = slim.conv2d(input_image, 128, [3, 3], scope="conv4_3x3")
net = slim.max_pool2d(net, [2, 2], scope='pool2')
net = slim.conv2d(input_image, 128, [3, 3], scope="conv5_3x3")
net = slim.max_pool2d(net, [2, 2], scope='pool3')
net = slim.conv2d(input_image, 32, [1, 1], scope="conv6_1x1")
return net
Bạn có thấy lỗi không? Nhiều thao tác khác nhau không thực sự được sử dụng vì các kết quả trước đó được ghi đè bằng các biến mới. Sử dụng khối mã này trong mạng sẽ vẫn được đào tạo và các trọng số sẽ cập nhật và tổn thất thậm chí có thể giảm - nhưng mã chắc chắn không thực hiện được những gì đã dự định. (Tác giả cũng không nhất quán về việc sử dụng dấu ngoặc đơn hoặc dấu ngoặc kép nhưng đó hoàn toàn là phong cách.)
Các lỗi lập trình phổ biến nhất liên quan đến mạng thần kinh là
- Các biến được tạo nhưng không bao giờ được sử dụng (thường là do lỗi sao chép-dán);
- Biểu thức cho cập nhật gradient là không chính xác;
- Cập nhật trọng lượng không được áp dụng;
- Các hàm mất không được đo theo thang đo chính xác (ví dụ, tổn thất entropy chéo có thể được biểu thị theo xác suất hoặc nhật ký)
- Mất mát không phù hợp với nhiệm vụ (ví dụ: sử dụng tổn thất entropy chéo phân loại cho một nhiệm vụ hồi quy).
Bò trước khi bạn đi bộ; Đi bộ trước khi bạn chạy
Mạng lưới thần kinh rộng và sâu, và mạng lưới thần kinh với hệ thống dây điện kỳ lạ, là điều nóng nhất hiện nay trong học máy. Nhưng những mạng lưới này không hoàn toàn hình thành sự tồn tại; nhà thiết kế của họ đã xây dựng nên chúng từ các đơn vị nhỏ hơn. Đầu tiên, xây dựng một mạng nhỏ với một lớp ẩn duy nhất và xác minh rằng nó hoạt động chính xác. Sau đó, tăng dần độ phức tạp của mô hình bổ sung và xác minh rằng mỗi trong số chúng cũng hoạt động.
Quá ít tế bào thần kinh trong một lớp có thể hạn chế sự biểu diễn mà mạng học được, gây ra sự phù hợp. Quá nhiều tế bào thần kinh có thể gây ra sự phù hợp quá mức vì mạng sẽ "ghi nhớ" dữ liệu đào tạo.
Ngay cả khi bạn có thể chứng minh rằng, về mặt toán học, chỉ có một số lượng nhỏ tế bào thần kinh cần thiết để mô hình hóa một vấn đề, thì thường có trường hợp có thêm một vài tế bào thần kinh giúp trình tối ưu hóa dễ dàng tìm thấy cấu hình "tốt". (Nhưng tôi không nghĩ có ai hiểu đầy đủ lý do tại sao lại như vậy.) Tôi cung cấp một ví dụ về vấn đề này trong bối cảnh của vấn đề XOR ở đây: Không phải các lần lặp của tôi cần đào tạo NN cho XOR với MSE <0,001 quá cao? .
Việc chọn số lượng các lớp ẩn cho phép mạng tìm hiểu một sự trừu tượng hóa từ dữ liệu thô. Học sâu là tất cả những cơn thịnh nộ ngày nay, và các mạng với một số lượng lớn các lớp đã cho thấy kết quả ấn tượng. Nhưng việc thêm quá nhiều lớp ẩn có thể gây rủi ro quá mức hoặc làm cho việc tối ưu hóa mạng rất khó khăn.
Chọn một mạng lưới thông minh có thể làm rất nhiều công việc cho bạn. Là nguồn dữ liệu của bạn có thể tuân theo kiến trúc mạng chuyên ngành? Mạng thần kinh chuyển đổi có thể đạt được kết quả ấn tượng trên các nguồn dữ liệu, dữ liệu hình ảnh hoặc âm thanh "có cấu trúc". Mạng thần kinh định kỳ có thể làm tốt các loại dữ liệu tuần tự, chẳng hạn như ngôn ngữ tự nhiên hoặc dữ liệu chuỗi thời gian. Kết nối còn lại có thể cải thiện các mạng chuyển tiếp thức ăn sâu.
Đào tạo mạng lưới thần kinh giống như chọn khóa
Để đạt được kết quả hiện đại, hoặc thậm chí chỉ đơn thuần là kết quả tốt, bạn phải thiết lập tất cả các bộ phận được cấu hình để hoạt động tốt với nhau . Thiết lập cấu hình mạng thần kinh thực sự học được rất nhiều như chọn khóa: tất cả các phần phải được xếp thành hàng vừa phải. Cũng như không đủ để có một bộ tách đơn ở đúng vị trí, cũng không đủ để chỉ có kiến trúc, hoặc chỉ có trình tối ưu hóa, được thiết lập chính xác.
Điều chỉnh các lựa chọn cấu hình không thực sự đơn giản như nói rằng một loại lựa chọn cấu hình (ví dụ: tốc độ học tập) ít nhiều quan trọng hơn các loại khác (ví dụ: số lượng đơn vị), vì tất cả các lựa chọn này tương tác với tất cả các lựa chọn khác, vì vậy một sự lựa chọn có thể làm tốt kết hợp với sự lựa chọn khác được thực hiện ở nơi khác .
Đây là danh sách không đầy đủ các tùy chọn cấu hình không phải là tùy chọn chính quy hoặc tùy chọn tối ưu hóa số.
Tất cả các chủ đề này là lĩnh vực hoạt động nghiên cứu.
Tối ưu hóa không lồi là khó
Hàm mục tiêu của mạng nơ ron chỉ lồi khi không có đơn vị ẩn, tất cả các kích hoạt là tuyến tính và ma trận thiết kế là toàn hạng - vì cấu hình này là một vấn đề hồi quy thông thường.
Trong tất cả các trường hợp khác, vấn đề tối ưu hóa là không lồi và tối ưu hóa không lồi là khó. Những thách thức của việc đào tạo mạng lưới thần kinh là nổi tiếng (xem: Tại sao khó đào tạo mạng lưới thần kinh sâu? ). Ngoài ra, các mạng thần kinh có số lượng tham số rất lớn, điều này hạn chế chúng ta chỉ sử dụng các phương pháp bậc nhất (xem: Tại sao phương pháp của Newton không được sử dụng rộng rãi trong học máy? ). Đây là một lĩnh vực nghiên cứu rất tích cực.
Đặt tốc độ học tập quá lớn sẽ khiến tối ưu hóa phân kỳ, bởi vì bạn sẽ nhảy từ một bên của "hẻm núi" sang bên kia. Đặt cài đặt này quá nhỏ sẽ khiến bạn không thực hiện được bất kỳ tiến triển thực sự nào và có thể cho phép tiếng ồn vốn có trong SGD lấn át các ước tính độ dốc của bạn.
Cắt độ dốc quy mô lại định mức của độ dốc nếu nó vượt quá ngưỡng nào đó. Tôi đã từng nghĩ rằng đây là một tham số thiết lập và quên, thường là 1.0, nhưng tôi thấy rằng tôi có thể làm cho một mô hình ngôn ngữ LSTM tốt hơn đáng kể bằng cách đặt nó thành 0,25. Tôi không biết tại sao lại như vậy.
Lập kế hoạch tỷ lệ học tập có thể làm giảm tỷ lệ học tập trong quá trình đào tạo. Theo kinh nghiệm của tôi, cố gắng sử dụng lập lịch rất giống với regex : nó thay thế một vấn đề ("Làm thế nào để tôi học tiếp tục sau một kỷ nguyên nhất định?") Với hai vấn đề ("Làm thế nào để tôi học tiếp tục sau một kỷ nguyên nhất định ? "Và" Làm thế nào để tôi chọn một lịch trình tốt? "). Những người khác nhấn mạnh rằng lập kế hoạch là cần thiết. Tôi sẽ để bạn quyết định.
Chọn kích thước xe buýt nhỏ tốt có thể ảnh hưởng gián tiếp đến quá trình học tập, vì một lô nhỏ lớn hơn sẽ có xu hướng có phương sai nhỏ hơn ( luật số lượng lớn ) so với lô nhỏ hơn. Bạn muốn lô nhỏ đủ lớn để có thể cung cấp thông tin về hướng của độ dốc, nhưng đủ nhỏ để SGD có thể thường xuyên hóa mạng của bạn.
Có một số biến thể về độ dốc dốc ngẫu nhiên sử dụng động lượng, tốc độ học tập thích ứng, cập nhật Nesterov, v.v để cải thiện vanilla SGD. Thiết kế một trình tối ưu hóa tốt hơn là một lĩnh vực nghiên cứu tích cực. Vài ví dụ:
Khi mới ra mắt, trình tối ưu hóa Adam đã tạo ra rất nhiều sự quan tâm. Nhưng một số nghiên cứu gần đây đã phát hiện ra rằng SGD với động lượng có thể thực hiện các phương pháp gradient thích ứng cho các mạng thần kinh. " Giá trị cận biên của các phương pháp chuyển đổi thích nghi trong học máy " của Ashia C. Wilson, Rebecca Roelofs, Mitchell Stern, Nathan Srebro, Benjamin Recht
Nhưng mặt khác, bài báo gần đây này đề xuất một trình tối ưu hóa tỷ lệ học tập thích ứng mới, được cho là sẽ thu hẹp khoảng cách giữa các phương pháp tỷ lệ thích ứng và SGD với động lượng. " Đóng khoảng cách khái quát hóa của các phương pháp Gradient thích ứng trong việc đào tạo mạng lưới thần kinh sâu " của Jinghui Chen, Quanquan Gu
Các phương pháp gradient thích ứng, sử dụng thông tin độ dốc lịch sử để tự động điều chỉnh tốc độ học tập, đã được quan sát để khái quát hóa kém hơn so với độ dốc dốc ngẫu nhiên (SGD) với động lực trong việc đào tạo mạng lưới thần kinh sâu. Điều này để lại cách thu hẹp khoảng cách khái quát hóa của các phương thức gradient thích ứng là một vấn đề mở. Trong công việc này, chúng tôi chỉ ra rằng các phương thức gradient thích ứng như Adam, Amsgrad, đôi khi "quá thích nghi". Chúng tôi thiết kế một thuật toán mới, được gọi là phương pháp ước lượng động lượng thích ứng một phần (Padam), hợp nhất Adam / Amsgrad với SGD để đạt được kết quả tốt nhất từ cả hai thế giới. Các thử nghiệm về điểm chuẩn tiêu chuẩn cho thấy Padam có thể duy trì tốc độ hội tụ nhanh như Adam / Amsgrad trong khi khái quát hóa cũng như SGD trong việc đào tạo mạng lưới thần kinh sâu.
Bình thường hóa
Quy mô của dữ liệu có thể tạo ra sự khác biệt lớn về đào tạo.
[ - 0,5 , 0,5 ]
Chuẩn hóa lớp có thể cải thiện đào tạo mạng bằng cách giữ trung bình hoạt động và độ lệch chuẩn cho kích hoạt tế bào thần kinh. Nó không được hiểu rõ tại sao điều này giúp đào tạo, và vẫn là một lĩnh vực nghiên cứu tích cực.
- " Hiểu về bình thường hóa hàng loạt " của Johan Bjorck, Carla Gomes, Bart Selman
- " Hướng tới một sự hiểu biết lý thuyết về bình thường hóa hàng loạt " của Jonas Kohler, Hadi Daneshmand, Aurelien Lucchi, Ming Zhou, Klaus Neymeyr, Thomas Hofmann
- " Làm thế nào để bình thường hóa hàng loạt giúp tối ưu hóa? (Không, nó không phải là về sự thay đổi đồng biến nội bộ) " của Shibani Santurkar, Dimitris Tsipras, Andrew Ilyas, Aleksander Madry
Chính quy
Chọn và điều chỉnh chính quy mạng là một phần quan trọng trong việc xây dựng một mô hình khái quát tốt (nghĩa là một mô hình không phù hợp với dữ liệu đào tạo). Tuy nhiên, tại thời điểm mạng của bạn đang vật lộn để giảm tổn thất về dữ liệu đào tạo - khi mạng không học - việc chính quy hóa có thể làm mờ vấn đề là gì.
Khi mạng của tôi không học, tôi tắt tất cả các chương trình chính quy và xác minh rằng mạng không chính quy hoạt động chính xác. Sau đó, tôi thêm từng phần chính quy trở lại và xác minh rằng mỗi phần đó hoạt động trên đường đi.
Chiến thuật này có thể xác định chính xác nơi một số chính quy có thể được thiết lập kém. Một số ví dụ
L2L1
Hai phần của chính quy là xung đột. Ví dụ, quan sát rộng rãi rằng bình thường hóa lớp và bỏ học rất khó sử dụng cùng nhau. Vì bản thân nó rất hữu ích, hiểu cách sử dụng cả hai là một lĩnh vực nghiên cứu tích cực.
Giữ một Nhật ký thí nghiệm
Khi tôi thiết lập mạng thần kinh, tôi không mã hóa bất kỳ cài đặt tham số nào. Thay vào đó, tôi thực hiện điều đó trong một tệp cấu hình (ví dụ: JSON) được đọc và sử dụng để điền chi tiết cấu hình mạng khi chạy. Tôi giữ tất cả các tập tin cấu hình. Nếu tôi thực hiện bất kỳ sửa đổi tham số, tôi tạo một tệp cấu hình mới. Cuối cùng, tôi viết thêm ý kiến về tất cả các tổn thất mỗi epoch cho đào tạo và xác nhận.
k
Lấy ví dụ, tôi muốn tìm hiểu về các mô hình ngôn ngữ LSTM, vì vậy tôi đã quyết định tạo một bot Twitter viết các tweet mới để đáp lại những người dùng Twitter khác. Tôi đã làm việc này trong thời gian rảnh, giữa trường học và công việc của tôi. Mất khoảng một năm và tôi đã lặp đi lặp lại khoảng 150 mô hình khác nhau trước khi đến một mô hình đã làm những gì tôi muốn: tạo văn bản tiếng Anh mới (loại) có ý nghĩa. (Một điểm dính chính và một phần lý do khiến phải mất quá nhiều nỗ lực, là nó không đủ để chỉ mất một lượng nhỏ mẫu, vì các mô hình tổn thất thấp ban đầu đã quản lý để ghi nhớ dữ liệu đào tạo, do đó, nó chỉ tái tạo các khối nguyên văn của văn bản để trả lời các lời nhắc - phải mất một số điều chỉnh để làm cho mô hình trở nên tự phát hơn và vẫn có tổn thất thấp.)