Đề bài
Hàm softmax biến một danh sách điểm số (logit) thành xác suất. Các mô hình ngôn ngữ dùng nó để chọn từ tiếp theo:
softmax(x)_i = e^(x_i) / (e^(x_1) + e^(x_2) + … + e^(x_n))
Điểm số lớn làm e^x bị tràn số, nên trước tiên hãy trừ điểm lớn nhất khỏi mọi điểm. Về mặt toán học, kết quả không đổi.
Hãy cài đặt softmax(logits).
Đầu vào
logits: Một danh sách điểm số.
Đầu ra
Trả về danh sách xác suất theo đúng thứ tự. Tất cả nằm trong khoảng 0 đến 1 và có tổng bằng 1.
Ràng buộc
1 ≤ độ dài ≤ 1.000
-1.000 ≤ mỗi điểm số ≤ 1.000
Ví dụ
Đầu vào:
logits = [1.0, 2.0, 3.0]
Kết quả mong đợi:
expected = [0.090031, 0.244728, 0.665241]
Đầu vào:
std::vector<double> logits = {1.0, 2.0, 3.0};
Kết quả mong đợi:
std::vector<double> expected = {0.090031, 0.244728, 0.665241};
Đầu vào:
double[] logits = new double[] {1.0, 2.0, 3.0};
Kết quả mong đợi:
double[] expected = new double[] {0.090031, 0.244728, 0.665241};
Giải thích
e¹ ≈ 2.718, e² ≈ 7.389 và e³ ≈ 20.086 có tổng là 30.193, nên các xác suất vào khoảng [0.090031, 0.244728, 0.665241].
Đầu vào:
logits = [1000.0, 1000.0]
Kết quả mong đợi:
expected = [0.5, 0.5]
Đầu vào:
std::vector<double> logits = {1000.0, 1000.0};
Kết quả mong đợi:
std::vector<double> expected = {0.5, 0.5};
Đầu vào:
double[] logits = new double[] {1000.0, 1000.0};
Kết quả mong đợi:
double[] expected = new double[] {0.5, 0.5};
Giải thích
Tính trực tiếp e^1000 sẽ bị tràn số. Trừ đi giá trị lớn nhất cho [0, 0], và e⁰ / (e⁰ + e⁰) = 0.5 cho cả hai.
Tham khảo
Thử thách này đã được điều chỉnh cho CodeUtility. Hãy làm theo đề bài và các ràng buộc ở trên.