python-svm分類項目實戰

背景知識:

SVM是有監督的學習模型,通過求解最大分類間隔求解二分類問題。我所理解的svm粗暴點來說就是,在二維平面可用一條直線進行劃分,若二維平面不能線性可分,就把他們拋向多維空間,找到一個平面將其劃分開(就好比桌上一堆亂擺放的紅球和籃球,你拍桌子,球拋向空中,會出現一個平面將紅籃球完美分開)。所以SVM關鍵就是再找那條最優的直線或者最優平面。

比如上圖中,C是最優直線,當這個直線平移,分別到B和A的位置時,這條線就不能在平移了,否則會分類出錯。所以C到B的距離就稱為最大間隔。關於SVM牢記三點:

  1. 完全線性可分時最原始的SVM,最大的核心思想就是找到最大的分類間隔,稱之為硬間隔,能完全將兩類分開。
  2. 大部分線性可分情況下的線性分類器,引入軟間隔,允許一定量的樣本分類錯誤
  3. 針對線性不可分,引入核函數,將樣本空間投射到多維空間,從而能線性可分

利用python中的機器學習包sklearn導入svm,然後構造一個SVC或者Linear SVC分類器。LinearSVC 是個線性分類器,用於處理線性可分的數據,只能使用線性核函數。針對非線性的數據,需要用到 SVC。在 SVC 中,我們既可以使用到線性核函數 (進行線性劃分),也能使用高維的核函數(進行非線性劃分)。

SVC 的構造函數:model = svm.SVC(kernel=『rbf』, C=1.0, gamma=『auto』),kernel選擇核函數,C為分類分錯時的懲罰係數,C越大,預測越準確,泛化能力越差。

在創建SVM分類器後,就可以輸入訓練集對它進行訓練建模。使用 model.fit(train_X,train_y),傳入訓練集中的特徵值矩陣 train_X 和分類標識 train_y.使用 prediction=model.predict(test_X) 來對結果進行預測,test_X為測試集的特徵值矩陣。

項目實戰—利用SVM對乳腺癌進行檢測

數據採集:該數據集來自於美國,可以從lengxueqing/exercises_for_python_projects醫療人員採集患者乳腺癌患者經過細針穿刺的數字化圖像,對這些圖像進行特徵提取,這些特徵是對細胞核呈現的描述。腫瘤分為良性和惡性。該數據集共有569個樣本,32列。數據集的部分截圖如下:

32個欄位分別為:[ id, diagnosis, radius_mean, texture_mean......radius_se, texture_se......radius_worst, texture_worst]

通過對欄位的觀察,我們可以看出,32個欄位除了病人的ID,以及疾病診斷結果diagnosis,剩餘的30列分別是對十個屬性進行求mean,se,worst(3個最大值的平均值),所以就是10 x3 =30列,這十個屬性依次是:半徑,文理,周長,面積,平均滑度,緊密度,凹度,凹縫,對稱性,分形錐形。在569個樣本中,357個是良性,212個事惡性腫瘤。

項目目標:生成一個乳腺癌診斷的SVM分類器,並計算這個分類器的準確率。

項目執行流程:數據採集 
ightarrow 數據探索 
ightarrow 數據清洗 
ightarrow 特徵選擇 
ightarrow 模型訓練 
ightarrow 模型評估

如果 數據質量不高,就要對數據進行清洗,可以按照「完全合一」的准測評估數據的質量。

  1. 完整性:數據是否完整
  2. 全面性:觀察每條數據是否存在單位,定義不一致,比如身高記錄的有厘米和米
  3. 合法性:數據的類型,內容,大小是否合法。
  4. 唯一性:數據是否存在重複記錄

數據探索:

# 載入數據集
data = pd.read_csv("./data.csv")
# 數據探索,顯示數據列名,產看數據的基本統計值
print(data.columns)
print(data.head(5))
print(data.describe())

數據集的基本統計

數據清洗 :

根據欄位的顯示情況,病人ID列不能作為特徵,其次分類欄位diagonsis的取值為M或者B,需要將其轉化為1和0.其餘的30個欄位,可以分成三組,下劃線後面的mean、se,worst代表了每組欄位不同的度量方式,分別是平均值,標準差,最大值。

# 將特徵欄位分成3組
features_mean= list(data.columns[2:12])
features_se= list(data.columns[12:22])
features_worst=list(data.columns[22:32])

# ID列沒有用,刪除該列
data.drop("id",axis=1,inplace=True)
# 將B良性替換為0,M惡性替換為1
data[diagnosis]=data[diagnosis].map({M:1,B:0})

特徵選擇:

# 選擇十個屬性的mean作為特徵值,用熱力圖呈現features_mean欄位之間的相關性
corr = data[features_mean].corr()
plt.figure(figsize=(8,8)
# annot=True顯示每個方格的數據
sns.heatmap(corr, annot=True)
plt.show()

從熱圖上的數字越大,表明相關性越大。從圖上可以看出,被藍色框圈住的radius_mean, perimeter_mean, area_mean三者的相關性很大,compactness_mean, concavity_mean,concave_mean這三個欄位也是相關性交大,為了數據降維,我們在相關性大的欄位組別中分別取一個欄位,分別取radius_mean,compactness_mean。這樣就可以對數據進行降維。

我們用features_worst(最大值)作為特徵集,兩個熱圖相比,結果一樣。也就是說,用十種屬性的不同度量進行相關係數矩陣圖時,結果差不多。

# 特徵選擇
features_remain = [radius_mean,texture_mean, smoothness_mean,compactness_mean,symmetry_mean, fractal_dimension_mean]

# 抽取30%的數據作為測試集,其餘作為訓練集
train, test = train_test_split(data, test_size = 0.3)# in this our main data is splitted into train and test
# 抽取特徵選擇的數值作為訓練和測試數據
train_X = train[features_remain]
train_y=train[diagnosis]
test_X= test[features_remain]
test_y =test[diagnosis]

# 採用Z-Score規範化數據,保證每個特徵維度的數據均值為0,方差為1
ss = StandardScaler()
train_X = ss.fit_transform(train_X)
test_X = ss.transform(test_X)

模型訓練:

# 創建SVM分類器
model = svm.SVC()
# 用訓練集做訓練
model.fit(train_X,train_y)
# 用測試集做預測
prediction=model.predict(test_X)
print(準確率: , metrics.accuracy_score(prediction,test_y))

最後得到的準確率為0.918,說明訓練結果不錯。若我們不對特徵進行降維,最後的結果為0.988,為什麼會出現這種結果呢?猜測可能是由於多重共線性使得測試結果偏高吧。


推薦閱讀:

TAG:Python | 數據分析 | 機器學習 |