C++實現softmax函數的面試經驗
背景
今天面試字節算法崗時被問到的問題,讓我用C++實現一個softmax函數。softmax是邏輯回歸在多分類問題上的推廣。大概的公式如下:
即判斷該變量在總體變量中的占比。
第一次實現
實現
我們用vector來封裝輸入和輸出,簡單的按公式復現。
vector<double> softmax(vector<double> input) { double total=0; for(auto x:input) { total+=exp(x); } vector<double> result; for(auto x:input) { result.push_back(exp(x)/total); } return result; }
測試
test 1
- 測試用例1: {1, 2, 3, 4, 5}
- 測試輸出1: {0.0116562, 0.0316849, 0.0861285, 0.234122, 0.636409}
經過簡單測試是正常的。
test 2
但是這時面試官提出瞭一個問題,即如果有較大輸入變量時會怎麼樣?
- 測試用例2: {1, 2, 3, 4, 5, 1000}
- 測試輸出2: {0, 0, 0, 0, 0, nan}
由於 e^1000已經溢出瞭雙精度浮點(double)所能表示的范圍,所以變成瞭NaN(not a number)。
第二次實現(改進)
改進原理
我們註意觀察softmax的公式:
如果我們給上下同時乘以一個很小的數,最後答案的值是不變的。
那我們可以給每一個輸入 x i 都減去一個值 a ,防止爆精度。
大致表示如下:
實現
vector<double> softmax(vector<double> input) { double total=0; double MAX=input[0]; for(auto x:input) { MAX=max(x,MAX); } for(auto x:input) { total+=exp(x-MAX); } vector<double> result; for(auto x:input) { result.push_back(exp(x-MAX)/total); } return result; }
測試
test 1
- 測試用例1: {1, 2, 3, 4, 5, 1000}
- 測試輸出1: {0, 0, 0, 0, 0, 1}
test 2
- 測試用例1: {0, 19260817, 19260817}
- 測試輸出1: {0, 0.5, 0.5}
我們發現結果正常瞭。
完整代碼
#include <iostream> #include <vector> #include <math.h> using namespace std; vector<double> softmax(vector<double> input) { double total=0; double MAX=input[0]; for(auto x:input) { MAX=max(x,MAX); } for(auto x:input) { total+=exp(x-MAX); } vector<double> result; for(auto x:input) { result.push_back(exp(x-MAX)/total); } return result; } int main(int argc, char *argv[]) { int n; cin>>n; vector<double> input; while(n--) { double x; cin>>x; input.push_back(x); } for(auto y:softmax(input)) { cout<<y<<' '; } }
以上就是C++實現softmax函數的面試經驗的詳細內容,更多關於C++ softmax函數的資料請關註WalkonNet其它相關文章!
推薦閱讀:
- C++vector的用法你都知道嘛
- C++ Effective詳解
- 一篇文章帶你瞭解C++(STL基礎、Vector)
- C++ stringstream格式化輸出輸入詳情
- 一篇文章徹底搞懂C++常見容器