Làm thế nào để đối phó với sự phức tạp trong mã số, ví dụ, khi xử lý các ma trận Jacobian lớn?


10

Tôi đang giải một hệ phương trình phi tuyến tính của các phương trình kết hợp, và đã tính toán Jacobian của hệ thống rời rạc. Kết quả thực sự phức tạp, bên dưới là (chỉ!) 3 cột đầu tiên của ma trận 3×9 ,

Ma trận một phần Jacobian

(Một phần phức tạp nảy sinh, bởi vì sơ đồ số đòi hỏi phải phù hợp theo cấp số nhân cho sự ổn định.)

Tôi có một câu hỏi chung về việc triển khai mã số bằng cách sử dụng Jacobian.

Tôi có thể tiếp tục và thực hiện ma trận này trong mã. Nhưng trực giác của tôi đang bảo tôi mong đợi một vài ngày (có thể vài tuần!) Về việc sửa lỗi tẻ nhạt do sự phức tạp tuyệt đối và không thể tránh khỏi việc đưa ra lỗi. Làm thế nào mà một người đối phó với sự phức tạp như điều này trong mã số, dường như không thể tránh khỏi?! Bạn có sử dụng tạo tự động từ các gói tượng trưng (sau đó tinh chỉnh mã bằng tay) không?

Đầu tiên tôi dự định gỡ lỗi Jacobian phân tích với xấp xỉ sai phân hữu hạn, tôi có nên nhận ra bất kỳ cạm bẫy nào không? Làm thế nào để bạn đối phó với các vấn đề tương tự trong mã của bạn?

Cập nhật

Tôi đang mã hóa điều này bằng Python và sử dụng sympy để tạo Jacobian. Có lẽ tôi có thể sử dụng tính năng tạo mã ?


Hệ thống đại số máy tính nào bạn đang sử dụng để tạo các biểu thức Jacobian? Nếu bạn đang sử dụng Maple, bạn có thể muốn xem codegengói đó vì nó có thể tạo mã C hoặc Fortran nhỏ gọn và hiệu quả cho mỗi hoặc tất cả các biểu thức một cách tự động.
Pedro

Có rất nhiều câu trả lời hữu ích ở đây, thật không hợp lý khi chọn một câu trả lời. Tôi có nên làm điều này một bài viết Wiki cộng đồng?
boyfarrell

Câu trả lời:


6

Một từ: Tính mô đun .

Có rất nhiều biểu thức lặp đi lặp lại trong Jacobian của bạn có thể được viết dưới dạng hàm riêng của chúng. Không có lý do gì để bạn viết cùng một thao tác nhiều lần và điều đó sẽ giúp việc gỡ lỗi dễ dàng hơn; nếu bạn chỉ viết nó một lần thì chỉ có một chỗ bị lỗi (theo lý thuyết).

Mã mô-đun cũng sẽ làm cho thử nghiệm dễ dàng hơn; Bạn có thể viết các bài kiểm tra cho từng thành phần của Jacobian thay vì cố gắng kiểm tra toàn bộ ma trận. Ví dụ: nếu bạn viết hàm am () theo kiểu mô-đun, bạn có thể dễ dàng viết các bài kiểm tra độ tỉnh táo cho nó, kiểm tra xem bạn có phân biệt đúng không, v.v.

Một đề nghị khác là xem xét các thư viện khác biệt tự động để lắp ráp Jacobian. Không có gì đảm bảo chúng không có lỗi, nhưng có lẽ sẽ có ít lỗi hơn / ít lỗi hơn so với việc tự viết. Dưới đây là một số bạn có thể muốn xem xét nó:

  • Sacado (Phòng thí nghiệm Sandia)
  • ADIC (Argonne)

Xin lỗi, chỉ cần thấy rằng bạn đang sử dụng python. SciencePython có hỗ trợ cho AD.


Lời khuyên tốt. Các biểu thức trung gian thường không cần phải có các hàm riêng - chỉ cần lưu trữ chúng trong các biến trung gian.
David Ketcheson

5

Hãy để tôi cân nhắc ở đây với một vài lời cảnh báo, mở đầu bằng một câu chuyện. Từ lâu, tôi đã làm việc với một đồng nghiệp khi tôi mới bắt đầu. Ông có một vấn đề tối ưu hóa để giải quyết, với một mục tiêu khá lộn xộn. Giải pháp của ông là tạo ra các dẫn xuất phân tích để tối ưu hóa.

Vấn đề mà tôi thấy là những dẫn xuất này thật khó chịu. Được tạo bằng Macsyma, được chuyển đổi thành mã fortran, chúng là hàng chục câu lệnh tiếp tục dài. Trong thực tế, trình biên dịch Fortran đã khó chịu vì điều đó, vì nó vượt quá số lượng báo cáo tiếp tục tối đa. Trong khi chúng tôi tìm thấy một lá cờ cho phép chúng tôi khắc phục vấn đề đó, có những vấn đề khác.

  • Trong các biểu thức dài, như thường được tạo ra bởi các hệ thống CA, có nguy cơ hủy bỏ trừ lớn. Tính toán rất nhiều số lớn, chỉ để thấy tất cả chúng triệt tiêu lẫn nhau để mang lại một số nhỏ.

  • Thông thường các công cụ phái sinh được phân tích thực sự tốn kém hơn để đánh giá so với các công cụ phái sinh được tạo số bằng cách sử dụng các khác biệt hữu hạn. Một gradient cho n biến có thể mất hơn n lần so với chi phí đánh giá hàm mục tiêu của bạn. (Bạn có thể tiết kiệm thời gian vì nhiều thuật ngữ có thể được sử dụng lại trên các công cụ phái sinh khác nhau, nhưng điều đó cũng sẽ buộc bạn phải mã hóa tay cẩn thận, thay vì sử dụng các biểu thức do máy tính tạo ra. biểu thức, xác suất xảy ra lỗi không phải là nhỏ. Hãy chắc chắn rằng bạn xác minh các dẫn xuất này cho chính xác.)

Điểm của câu chuyện của tôi là các biểu thức CA tạo ra có vấn đề của riêng họ. Điều buồn cười là đồng nghiệp của tôi thực sự tự hào về sự phức tạp của vấn đề, rằng anh ấy rõ ràng đang giải quyết một vấn đề thực sự khó khăn vì đại số rất khó chịu. Điều tôi không nghĩ là anh ta cân nhắc là nếu đại số đó thực sự tính toán đúng, liệu nó có hoạt động chính xác không, và nó có hoạt động hiệu quả như vậy không.

Nếu tôi là người cao cấp tại thời điểm đó trong dự án này, tôi sẽ đọc cho anh ấy hành động bạo loạn. Niềm kiêu hãnh của anh ta đã khiến anh ta sử dụng một giải pháp có lẽ phức tạp không cần thiết, thậm chí không kiểm tra xem độ dốc dựa trên sự khác biệt hữu hạn là đủ. Tôi cá là chúng tôi đã dành khoảng một tuần thời gian để chạy tối ưu hóa này. Ít nhất, tôi sẽ khuyên anh ta kiểm tra cẩn thận độ dốc được tạo ra. Nó có chính xác không? Làm thế nào chính xác là nó, so với các dẫn xuất khác biệt hữu hạn? Trên thực tế, có những công cụ xung quanh ngày hôm nay cũng sẽ trả về ước tính lỗi trong dự đoán phái sinh của họ. Điều này chắc chắn đúng với mã phân biệt thích ứng, (derivest) tôi đã viết bằng MATLAB.

Kiểm tra mã. Xác nhận các dẫn xuất.

Nhưng trước khi bạn làm BẤT K of việc này, hãy xem xét nếu khác, các kế hoạch tối ưu hóa tốt hơn là một lựa chọn. Ví dụ: nếu bạn đang thực hiện điều chỉnh theo cấp số nhân, thì rất có khả năng bạn có thể sử dụng một bình phương nhỏ nhất phi tuyến được phân vùng (đôi khi được gọi là bình phương nhỏ nhất có thể tách rời. Tôi nghĩ đó là thuật ngữ được sử dụng bởi Seber và Wild trong cuốn sách của họ.) là để phá vỡ tập hợp các tham số thành tập hợp tuyến tính và phi tuyến nội tại. Sử dụng tối ưu hóa chỉ hoạt động trên các tham số phi tuyến. Với các tham số đó là "đã biết", thì các tham số tuyến tính nội tại có thể được ước tính bằng cách sử dụng bình phương tuyến tính tối thiểu đơn giản. Sơ đồ này sẽ giảm không gian tham số trong tối ưu hóa. Nó làm cho vấn đề trở nên mạnh mẽ hơn, vì bạn không cần phải tìm các giá trị bắt đầu cho các tham số tuyến tính. Nó làm giảm tính chiều của không gian tìm kiếm của bạn, do đó làm cho vấn đề chạy nhanh hơn. Một lần nữa tôi đã cung cấpmột công cụ cho mục đích này , nhưng chỉ trong MATLAB.

Nếu bạn sử dụng các dẫn xuất phân tích, hãy mã hóa chúng để sử dụng lại các thuật ngữ. Đây có thể là một tiết kiệm thời gian nghiêm trọng, và thực sự có thể làm giảm các lỗi, tiết kiệm thời gian của riêng bạn. Nhưng sau đó kiểm tra những con số đó!


5

Có một số chiến lược để xem xét:

  1. Tìm các đạo hàm ở dạng biểu tượng bằng cách sử dụng CAS, sau đó xuất mã để tính toán các đạo hàm.

  2. Sử dụng công cụ phân biệt tự động (AD) để tạo mã tính toán các đạo hàm từ mã để tính các hàm.

  3. Sử dụng các xấp xỉ sai phân hữu hạn để xấp xỉ Jacobian.

Sự khác biệt tự động có thể tạo ra mã hiệu quả hơn để tính toán toàn bộ Jacobian sau đó sử dụng tính toán tượng trưng để tạo ra một công thức cho mỗi mục trong ma trận. Sự khác biệt hữu hạn là một cách tốt để kiểm tra các dẫn xuất của bạn.



1

Ngoài các đề xuất tuyệt vời của BrianBorker, một cách tiếp cận khả thi khác cho các hàm có giá trị thực là sử dụng xấp xỉ đạo hàm bậc phức (xem bài viết này (paywalled) và bài viết này ). Trong một số trường hợp, cách tiếp cận này mang lại các dẫn xuất số chính xác hơn với chi phí thay đổi giá trị của các biến trong hàm của bạn từ thực sang phức. Bài viết thứ hai liệt kê một số trường hợp gần đúng chức năng bước phức tạp có thể bị phá vỡ.

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.