【基础算法】常见的ML、DL编程题
原文作者:Jack Stark
原文連接:https://zhuanlan.zhihu.com/p/81891467
在算法崗的面試中,除了數據結構和算法的編程題外,機器學習/深度學習的編程題也常常用來考察候選人的基礎能力。不能講了一大堆天花亂墜的算法,連個簡單的算法都不能獨立實現。
非極大值抑制(NMS)
NMS用來去掉重復的框。輸入前面得到的框,對于每一類,按照score進行降序排序,最大的那個一定保留,然后和其他的框計算IOU。IOU大于一定閾值視為重復的框,丟棄掉。
import?numpy?as?np def?nms(dets,?thresh):x1?=?dets[:,?0]?#?bbox?top_xy1?=?dets[:,?1]?#?bbox?top_yx2?=?dets[:,?2]?#?bbox?bottom_xy2?=?dets[:,?3]?#?bbox?bottom_yscores?=?dets[:,?4]?#?分類scoreareas?=?(x2?-?x1?+?1)?*?(y2?-?y1?+?1)order?=?scores.argsort()[::-1]?#?按score做降序排序keep?=?[]while?order.size?>?0:i?=?order[0]keep.append(i)xx1?=?np.maximum(x1[i],?x1[order[1:]])yy1?=?np.maximum(y1[i],?y1[order[1:]])xx2?=?np.minimum(x2[i],?x2[order[1:]])yy2?=?np.minimum(y2[i],?y2[order[1:]])w?=?np.maximum(0.0,?xx2?-?xx1?+?1)h?=?np.maximum(0.0,?yy2?-?yy1?+?1)interp?=?w?*?hiou?=?interp?/?(areas[i]?+?areas[order[1:]]?-?interp)inds?=?np.where(iou?<=?thresh)[0]order?=?order[inds?+?1]?#?加1的原因。假設一個類別有n個框,這里的索引是n-1個iou是對應的,#?這里要映射到原來長度為n的order,所以加1。return?keepBatch Normalization
訓練階段,求均值和方差時,在N、H、W上操作,而保留通道 C 的維度。具體來說,就是把第1個樣本的第1個通道,加上第2個樣本第1個通道 ...... 加上第 N 個樣本第1個通道,求平均,得到通道 1 的均值(注意是除以 N×H×W 而不是單純除以 N,最后得到的是一個代表這個 batch 第1個通道平均值的數字,而不是一個 H×W 的矩陣)。
import?numpy?as?np def?batch_rorm(x,?gamma,?beta):#?x_shape:[N,?C,?H,?W]results?=?0.eps?=?1e-5x_mean?=?np.mean(x,?axis=(0,?2,?3),?keepdims=True)x_var?=?np.var(x,?axis=(0,?2,?3),?keepdims=True)x_normalized?=?(x?-?x_mean)?/?np.sqrt(x_var?+?eps)results?=?gamma?*?x_normalized?+?betareturn?resultsBN在測試階段使用的統計量不是在一個batch上計算的,而是整個數據集上的,可以用移動平均法求得。
Group Normalization
計算均值和標準差時,把每一個樣本 feature map 的 channel 分成 G 組,每組將有 C/G 個 channel,然后將這些 channel 中的元素求均值和標準差。各組 channel 用其對應的歸一化參數獨立地歸一化。多用于檢測分割等占用顯存較大的任務。
import?numpy?as?np def?group_norm(x,?gamma,?beta,?G=16):#?x_shape:[N,?C,?H,?W]results?=?0.eps?=?1e-5x?=?np.reshape(x,?(x.shape[0],?G,?x.shape[1]//G,?x.shape[2],?x.shape[3]))x_mean?=?np.mean(x,?axis=(2,?3,?4),?keepdims=True)x_var?=?np.var(x,?axis=(2,?3,?4),?keepdims=True)x_normalized?=?(x?-?x_mean)?/?np.sqrt(x_var?+?eps)results?=?gamma?*?x_normalized?+?betaresults?=?np.reshape(results,?(results.shape[0],?results.shape[1]*results.shape[2],?results.shape[3],?results.shape[4]))return?resultsKmeans聚類
下面是簡易版本的實現。
注意,np.random.randint()是取值范圍是左閉右開區間,python自帶的random.randint()是閉區間。
import?numpy?as?np import?randomdef?kmeans(data,?k):m?=?len(data)?????#?樣本個數n?=?len(data[0])??#?維度cluster_center?=?np.zeros((k,?n))???#?k個聚類中心#?選擇合適的初始聚類中心#?在已有數據中隨機選擇聚類中心#?也可以直接用隨機的聚類中心init_list?=?np.random.randint(low=0,?high=m,?size=k)????#?[0,?m)for?index,?j?in?enumerate(init_list):cluster_center[index]?=?data[j][:]#?聚類cluster?=?np.zeros(m,?dtype=np.int)?-?1?#?所有樣本尚未聚類cc?=?np.zeros((k,?n))???#?下一輪的聚類中心c_number?=?np.zeros(k)????#?每個簇樣本的數目for?times?in?range(1000):for?i?in?range(m):c?=?nearst(data[i],?cluster_center)cluster[i]?=?c??#?第i個樣本歸于第c簇c_number[c]?+=?1cc[c]?+=?data[i]for?i?in?range(k):cluster_center[i]?=?cc[i]?/?c_number[i]cc.flat?=?0c_number.flat?=?0return?clusterdef?nearst(data,?cluster_center):nearst_center_index?=?0dis?=?np.sum((cluster_center[0]?-?data)?**?2)for?index,?center?in?enumerate(cluster_center):dis_temp?=?np.sum((center?-?data)?**?2)if?dis_temp?<?dis:nearst_center_index?=?indexdis?=?dis_tempreturn?nearst_center_indexif?__name__?==?"__main__":data?=?[[0,0],?[1,0],?[0,1],?[100,100],?[101,101],?[102,?100],?[-100,-100],?[-101,-101],?[-102,?-100]]data?=?np.array(data)cluster?=?kmeans(data,?3)print(cluster)#?[0?0?0?1?1?1?2?2?2]?每個樣本對應的類別,結果有隨機性softmax
import?numpy?as?npdef?convert_label_to_onehot(classes,?labels):"""classes:?類別數labels:?array,shape=(N,)"""return?np.eye(classes)[labels].Tdef?softmax(logits):"""logits:?array,?shape=(N,?C)"""res?=?np.zeros_like(logits)for?i,?row?in?enumerate(logits):exp_sum?=?np.sum(np.exp(row))for?j,?val?in?enumerate(row):res[i,j]?=?np.exp(val)/?exp_sumreturn?resif?__name__?==?'__main__':#?有四個樣本,有三個類別logits?=?np.array([[0,?0.45,?0.55],[0.9,?0.05,?0.05],[0.4,?0.6,?0],[1,?0,?0]])pred?=?np.argmax(softmax(logits),?axis=1)print(pred)softmax的上、下溢出問題
首先,什么是上溢出和下溢出?實數在計算機內用二進制表示,不是一個精確值。
當數值過小的時候,被四舍五入為0,這就是下溢出。此時如果除以它就會出問題。(也有說法指超出所能表示的最小數字時是下溢出)。
當數值過大超出所能表示的最大正數時,就會發生上溢出。
如對于一個數組??求softmax,
?,如果 某個?非常大,那么??將會非常大,有可能上溢出;當所有??都非常小(絕對值很大的負數),求指數之后會接近于0,就有可能下溢出。
有個方法可以同時解決上溢出和下溢出的問題:
求所有z中的最大值max_z,然后求??即可,這樣肯定不會有上溢出的風險,同時由于在分母上肯定有一個1,因此也不會有下溢出的風險。
PR曲線和ROC曲線的繪制
這兩種曲線是評價分類模型performance的常用方法。其中,PR圖的縱坐標是precision,橫坐標是recall;ROC曲線的縱坐標是True Positive Rate,橫坐標是False Positive Rate。它們的公式如下:
?,
?,
?,
?.
實現的代碼如下:
import?numpy?as?np import?matplotlib.pyplot?as?plt data_number?=?50 labels?=?np.random.randint(0,?2,?size=data_number)??#?真實的類別 scores?=?np.random.choice(np.arange(0.1,?1,?0.01),?data_number)??#?模型判斷樣本為類別1的置信度def?pr_curve(y,?pred):pos?=?np.sum(y?==?1)neg?=?np.sum(y?==?0)pred_sort?=?np.sort(pred)[::-1]??index?=?np.argsort(pred)[::-1]??y_sort?=?y[index]print(y_sort)pre?=?[]rec?=?[]for?i,?item?in?enumerate(pred_sort):if?i?==?0:??pre.append(1)rec.append(0)else:pre.append(np.sum((y_sort[:i]?==?1))?/?i)rec.append(np.sum((y_sort[:i]?==?1))?/?pos)#?畫圖plt.plot(rec,?pre,?'k')#?plt.legend(loc='lower?right')plt.title('PR?curve')plt.plot([(0,?0),?(1,?1)],?'r--')plt.xlim([-0.01,?1.01])plt.ylim([-0.01,?01.01])plt.ylabel('precision')plt.xlabel('recall')plt.show()def?roc_curve(y,?pred):pos?=?np.sum(y?==?1)neg?=?np.sum(y?==?0)pred_sort?=?np.sort(pred)[::-1]??index?=?np.argsort(pred)[::-1]??y_sort?=?y[index]print(y_sort)tpr?=?[]fpr?=?[]thr?=?[]for?i,?item?in?enumerate(pred_sort):tpr.append(np.sum((y_sort[:i]?==?1))?/?pos)fpr.append(np.sum((y_sort[:i]?==?0))?/?neg)thr.append(item)#?畫圖plt.plot(fpr,?tpr,?'k')plt.title('ROC?curve')plt.plot([(0,?0),?(1,?1)],?'r--')plt.xlim([-0.01,?1.01])plt.ylim([-0.01,?01.01])plt.ylabel('True?Positive?Rate')plt.xlabel('False?Positive?Rate')plt.show()pr_curve(labels,?scores) roc_curve(labels,?scores)往期精彩回顧適合初學者入門人工智能的路線及資料下載機器學習在線手冊深度學習在線手冊AI基礎下載(pdf更新到25集)本站qq群1003271085,加入微信群請回復“加群”獲取一折本站知識星球優惠券,復制鏈接直接打開:https://t.zsxq.com/yFQV7am喜歡文章,點個在看
總結
以上是生活随笔為你收集整理的【基础算法】常见的ML、DL编程题的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 解决Github速度太慢的几种方案
- 下一篇: 【基础算法】 GBDT/XGBoost