【筆試】20春招快手數據類筆試,Python中心極限定理,繪製ROC曲線和AUC值。

題目來源1:中國科學技術大學的牛友fancyjiang
https://www.nowcoder.com/discuss/406334?type=all&order=time&pos=&page=1html

題目來源2:煙臺大學的牛友,@連續。python

文章參考:請看原文。哈哈,博主比較急,就沒有去參考英文原文,全是從中文博客上學來的。面試

本文是給獅子大開口要了我150元諮詢費的連續同窗寫的。算法

筆試題目

1、 3道SQLapi

表A,表B;兩張表相同字段:id,timestamp(時間);問:B表中第一個事件以前A事件發生的數量;B表中第一個和第二個事件發生時間以內,A表A表中事件的數量;B表中第二個和第三個事件發生時間以內,A表中事件發生的數量;B表中第n個和第n+1個事件發生時間以內,A表中事件發生的數量;B表中100000個事件發生以後A表事件的數量
也是時間的表,字段:timestamp,問最後一個事件和倒數第二個事件發生的間隔時間
表A:觀看直播的表,字段:userid(惟一),photoid(惟一),timestamp;表B:觀看視頻的表,字段:字段:userid(惟一),photoid(惟一),timestamp;求只看直播的人數佔比,只看視頻人數佔比,二者都看人數佔比數組

2、 2道數據科學題目,能夠選擇運用python或者r
(1)寫出繪製ROC曲線和計算AUC值的代碼
(2)證實中心極限定理
[這個證實究竟是拋色子驗證,仍是用Python寫數學公式驗證啊,懵了]app

Python證實中心極限定理

請對照後面的註釋,看這段代碼dom

import numpy as np
import matplotlib.pyplot as plt
random_data = np.random.randint(1, 50, 100000)#隨機生成100000個整數,造成一個數組(1-49之間,不含50,左含右不含)
samples_mean = [] # 樣本均值
for _ in range(10000):#此類語法見②
    sample=np.random.choice(random_data,1000)#見①,從random_data數組中返回1000個數據,存入sample數組
    samples_mean.append(sample.mean())#見③,給sample數組總體求均值,集齊9999個sample均值合成samples_mean數組
samples_mean=np.array(samples_mean)#見④,將Python的List對象,變爲Numpy的ndarray對象
plt.hist(samples_mean,bins=100,color='g')#見⑤,直方圖
plt.grid()#網格線
plt.show()#圖形由show函數顯示

①、choice(seq) 方法返回一個seq[能夠是列表,元組或字符串]的隨機項。
注意:choice()是不能直接訪問的,須要導入 random 模塊,而後經過 random 靜態對象調用該方法。
np.random.choice(5,3)和np.random.randint(0,5,3)意思相同,表示從[0,5)之間隨機以等機率選取3個數機器學習

②、for _ in range(10000)表明從0到9999循環
函數

③、sample.mean()

④np.array(一維數組),有什麼用呢
Numpy提供ndarray(N-dimensional array object)對象,存儲單一數據類型的多維數組,節約內存和CPU,出自👉連接

若是你親自使用,對比一下便可知道,用了np.array轉換,明顯感受更快。在數值分析時,建議所有使用np的ndarray對象。

⑤plt.hist( x,bins=100,color='g')畫直方圖 👉官網說明文檔
直方圖與柱狀圖外觀表現很類似,用來展示連續型數據分佈特徵的統計圖形(柱狀圖主要展示離散型數據分佈)
x: 數據集,最終的直方圖將對數據集進行統計
bins=100:這個參數指定bin(箱子)的個數,也就是總共有幾根樹狀條形圖。
color:指定綠色用g和green均可以,源碼裏沒說。用標準顏色就能夠。

👉參考:plt.hist()與plt.hist2d()直方圖和雙直方圖&matplotlib可視化篇hist()--直方圖
後文寫的更好,參數介紹的更全


後來通過討論,仍是認爲,中心極限定理用python來證實,用random隨機拋色子就好,不用像數學公式同樣去證實

繪製ROC曲線和計算AUC值

ROC、AUC的簡要介紹

這一小部分介紹出自公衆號「數據蛙DataFrog」-做者:wing努力學習
數據分析師常見面試題--機器學習算法篇
https://mp.weixin.qq.com/s/mrUP4XT7m28u_36sRGqOHA


1、模型評估
1.1 什麼是ROC曲線
ROC的全稱是Receiver Operating Characteristic Curve,中文名字叫「受試者工做特徵曲線」,顧名思義,其主要的分析方法就是畫這條特徵曲線。這裏在網上找了一個比較好的圖樣示例以下:

該曲線的橫座標爲假陽性率(False Positive Rate, FPR),N是真實負樣本的個數,FP是N個負樣本中被分類器預測爲正樣本的個數。縱座標爲真陽性率(True Positive Rate, TPR),公式爲:

P是真實正樣本的個數,TP是P個正樣本中被分類器預測爲正樣本的個數。

舉一個簡單的例子方便你們的理解,假設如今有10個雷達信號警報,其中8個是真的轟炸機(P)來了,2個是大鳥(N)飛過,通過某分析員解析雷達的信號,判斷出9個信號是轟炸機,剩下1個是大鳥,其中被斷定爲轟炸機的信號中,有1個實際上是大鳥的信號(FP=1),而剩下8個確實是轟炸機信號(TP=8)。

所以能夠計算出FPR0.5,TPR爲1,而就(0.5,1)對應ROC曲線上一點。

1.2 如何計算AUC

AUC(Area Under roc Cure),顧名思義,其就是ROC曲線下的面積,該值可以量化地反映基於rOC曲線衡量出的模型性能。

計算AUC值只須要沿着ROC橫軸作積分就能夠,取值通常在0.5~1之間。AUC越大,說明分類效果越好。


一鍵生成AUC-ROC-score得分的函數

另外我在研究本身的隨機森林畢設的時候,發現一個能夠直接生成AUC - ROC得分的函數

Python1的語法,須要用的本身改一改

print"AUC - ROC : ", roc_auc_score(y,model.oob_prediction)

對「文藝數字君」文章的研究

下面部分是看的這篇文章。👉ROC曲線的繪製與AUC的計算-文藝數字君👍
是對這篇文章的解析。

注意喲,本文的甲狀腺病例圖,和另一個生病圖是不同的判斷標準
甲狀腺是低於V4-Value的認爲是生病,樣本病例圖認爲是高於threshold閾值爲生病
甲狀腺功能異常(Hypothyroid)和甲狀腺功能正常(Euthyroid)

由於文章有說:咱們假設T4 Value<5的時候, 認爲是甲狀腺功能異常(Hypothyroid)
因此,咱們讀者應該有這種意識:低於T4 Value的,全認爲他有病。

Sensivity(Recall/TPR/True Positive Rate) 敏感性(召回/TPR/真陽性率)👉表明被判斷爲有病的人。實際是由於擡高了判斷線,因而認爲更多人得病了。

這裏原文寫錯了:
原:一般會取一個閾值,使值大於黑線(在黑色線右側)爲Disease,在黑色線左側表示Nomal.
改:一般會取一個判斷黑線,使值大於黑線(在黑色線右側)判斷爲有病,在黑色線左側判斷爲沒病/健康.

Specificity(特異性),翻譯的看不懂,但從預備知識的公式和圖能夠看出來👇

所以,在咱們甲狀腺這個場景中
Specificity指的是,屬實的健康人佔總體健康人的比例。就叫他"屬實健康率"吧。

由於文章後面作了一個小變換(FPR=1-Specificity,FPR假陽性率),那FPR就是,被誤診的健康人佔總體健康人的,也就是「健康人誤診率」啦。

Sensivity(Recall/TPR/True Positive Rate真陽性率),TPR(被查出來的病人佔總病人的比例),那TPR就是「已查明的病患率」啦

FPR假陽性率----對應-----健康人誤診率
TPR真陽性率----對應-----已查明的病患率

上面這種圖比較重要,解釋這麼多,是由於涉及理解下面的TPR=FPR=1和0。


這副圖像的橫縱座標是經過調整不一樣的閾值,計算出TPR與FPR獲得的。對於座標(1,1)和座標(0,0)咱們能夠理解爲:

  • 當閾值T4 Value咱們調整爲最大的時候,這個時候就是所有預測爲甲狀腺功能異常(Hypothyroid),此時的TPR=FPR=1;
  • 當閾值T4 Value咱們調整爲最小的時候,這個時候就是所有預測爲甲狀腺功能正常(Euthyroid),此時的TPR=FPR=0;

因而結合兩個指標的意思,就能理解了。

咱們也能夠經過下面的圖進行理解,若是正負樣本是徹底分離的,那麼ROC曲線繪製出來就是兩條直線的拼接,以下圖所示:

我把原文的圖改了一下。但願沒錯,若是出錯了,請直接聯繫我喲。

原文這個圖下面的那句話應該是都寫錯了,因此就不要管了,知道ROC是表明TPR和FPR根據threshold的走勢就行。

原文這句話應該是對的,我做圖解釋一下

當閾值(Threshold)調整的很大的時候,此時TPR=FPR=1。當閾值逐漸減少,咱們但願咱們的模型TPR=1, 可是FPR能夠降低。當到了臨界點的時候,此時FPR的值保持不變,TPR的值逐漸降低。

而且由於區分的很好,因此AUC在這個時候=1,【閾值=0.5,ROC曲線爲直角,病人和健康人徹底被劃分開來的時候】

最後,咱們終於知道,ROC是表明TPR和FPR根據threshold的走勢

那麼,AUC的值就是ROC曲線的下半部分佔全體的比例。AUC值理解爲區分度,即區分模型【在這個閾值時】對於正常樣本與異常樣本的區分度。

AUC值越大,即當前閾值狀況下的ROC曲線區分度越好

能夠看到,這個原文裏的代碼,展現了不少個(有5個)二分類器。分別是宏觀平均ROC曲線/微觀平均ROC曲線/第0類ROC曲線/第1類ROC曲線/第2類ROC曲線

這些都是ROC曲線,並都已經把AUC值求出來了(area就是AUC,區分度)

ROC、AUC的詳細代碼

最後貼一下原文章的代碼整合,這段代碼能夠直接畫出5種ROC曲線。

若是Plot all ROC curves這段代碼刪掉,那就會直接畫出ROC曲線。

【這個直接畫出來的ROC曲線有什麼意義我得問一下原做者,還有宏觀平均ROC曲線的意義他也沒說】

看了代碼後,我發現單獨畫出來的ROC曲線是第二種分類的ROC曲線

通過原博主的解釋,我懂啦,micro-average ROC(微觀平均)是把全部分類所有展開從新計算ROC,當作一個大的二分類來計算平均值(ROC曲線的平均和AUC值的平均)

macro-average ROC(宏觀平均)是把三個分類分別擬合出三條ROC曲線,接着給定一組FPR(假陽性率),用擬合出的三個ROC去預測TPR,最後求平均,得出ROC曲線的平均和AUC值的平均

這是兩種對多分類問題求平均的方式,看那個效果好,用那個(AUC值高的那個區分度好,效果好)

由於我沒有親自作過快手的筆試題,因此就直接把原博主解釋過的官方ROC代碼放在這邊的,但願考試的小夥伴能夠本身改編改編作出來喲。

import numpy as np
import matplotlib.pyplot as plt
from itertools import cycle
from sklearn import svm, datasets
from sklearn.metrics import roc_curve, auc
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import label_binarize
from sklearn.multiclass import OneVsRestClassifier
from scipy import interp
# Import some data to play with
iris = datasets.load_iris()
X = iris.data
y = iris.target
# Binarize the output
y = label_binarize(y, classes=[0, 1, 2])
n_classes = y.shape[1]
# Add noisy features to make the problem harder
random_state = np.random.RandomState(0)
n_samples, n_features = X.shape
X = np.c_[X, random_state.randn(n_samples, 200 * n_features)]
# shuffle and split training and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=.5,
                                                    random_state=0)
# Learn to predict each class against the other
classifier = OneVsRestClassifier(svm.SVC(kernel='linear', probability=True,
                                 random_state=random_state))
y_score = classifier.fit(X_train, y_train).decision_function(X_test)


# Compute ROC curve and ROC area for each class
fpr = dict()
tpr = dict()
roc_auc = dict()
for i in range(n_classes):
    fpr[i], tpr[i], _ = roc_curve(y_test[:, i], y_score[:, i])
    roc_auc[i] = auc(fpr[i], tpr[i])
# 這個AUC值
print(roc_auc)
# Compute micro-average ROC curve and ROC area
fpr["micro"], tpr["micro"], _ = roc_curve(y_test.ravel(), y_score.ravel()) # 這個是ROC曲線的座標
roc_auc["micro"] = auc(fpr["micro"], tpr["micro"]) # 這個是計算AUC的值
print(roc_auc)
# micro-average ROC(這個至關因而把全部的分類所有展開從新計算ROC, 當作一個大的二分類的結果)

# Compute macro-average ROC curve and ROC area
# First aggregate all false positive rates
all_fpr = np.unique(np.concatenate([fpr[i] for i in range(n_classes)]))
# Then interpolate all ROC curves at this points
mean_tpr = np.zeros_like(all_fpr)
for i in range(n_classes):
    mean_tpr += interp(all_fpr, fpr[i], tpr[i])
# Finally average it and compute AUC
mean_tpr /= n_classes
fpr["macro"] = all_fpr
tpr["macro"] = mean_tpr
roc_auc["macro"] = auc(fpr["macro"], tpr["macro"])


plt.figure()
lw = 2 # linewidth(線條的粗細)
plt.plot(fpr[2], tpr[2], color='darkorange',
         lw=lw, label='ROC curve (area = %0.2f)' % roc_auc[2])
plt.plot([0, 1], [0, 1], color='navy', lw=lw, linestyle='--') # 這是繪製中間的直線
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Receiver operating characteristic example')
plt.legend(loc="lower right")
plt.show()


# Plot all ROC curves
plt.figure()
plt.plot(fpr["micro"], tpr["micro"],
         label='micro-average ROC curve (area = {0:0.2f})'
               ''.format(roc_auc["micro"]),
         color='deeppink', linestyle=':', linewidth=4)
plt.plot(fpr["macro"], tpr["macro"],
         label='macro-average ROC curve (area = {0:0.2f})'
               ''.format(roc_auc["macro"]),
         color='navy', linestyle=':', linewidth=4)
colors = cycle(['aqua', 'darkorange', 'cornflowerblue'])
for i, color in zip(range(n_classes), colors):
    plt.plot(fpr[i], tpr[i], color=color, lw=lw,
             label='ROC curve of class {0} (area = {1:0.2f})'
             ''.format(i, roc_auc[i]))
plt.plot([0, 1], [0, 1], 'k--', lw=lw)
plt.xlim([0.0, 1.0])
plt.ylim([0.0, 1.05])
plt.xlabel('False Positive Rate')
plt.ylabel('True Positive Rate')
plt.title('Some extension of Receiver operating characteristic to multi-class')
plt.legend(loc="lower right")
plt.show()

附網上一道ROC的題,已經很好理解啦

相關文章
相關標籤/搜索