python感知機分類乳腺癌數據集


 

一、感知機介紹

感知器(英語:Perceptron)是Frank Rosenblatt在1957年就職於康奈爾航空實驗室(Cornell Aeronautical Laboratory)時所發明的一種人工神經網絡。它可以被視為一種最簡單形式的前饋神經網絡,是一種二元線性分類器。Frank Rosenblatt給出了相應的感知機學習算法,常用的有感知機學習、最小二乘法和梯度下降法。譬如,感知機利用梯度下降法對損失函數進行極小化,求出可將訓練數據進行線性划分的分離超平面,從而求得感知機模型。感知機是生物神經細胞的簡單抽象。神經細胞結構大致可分為:樹突突觸細胞體軸突。單個神經細胞可被視為一種只有兩種狀態的機器——激動時為‘是’,而未激動時為‘否’。神經細胞的狀態取決於從其它的神經細胞收到的輸入信號量,及突觸的強度(抑制或加強)。當信號量總和超過了某個閾值時,細胞體就會激動,產生電脈沖。電脈沖沿着軸突並通過突觸傳遞到其它神經元。為了模擬神經細胞行為,與之對應的感知機基礎概念被提出,如權量(突觸)、偏置(閾值)及激活函數(細胞體)。

      在人工神經網絡領域中,感知機也被指為單層的人工神經網絡,以區別於較復雜的多層感知機(Multilayer Perceptron)。作為一種線性分類器,(單層)感知機可說是最簡單的前向人工神經網絡形式。盡管結構簡單,感知機能夠學習並解決相當復雜的問題。感知機主要的本質缺陷是它不能處理線性不可分問題。

二、感知機原理

感知機算法的原理和線性回歸算法的步驟大致相同,只是預測函數H和權值更新規則不同,這里將感知機算法應用於二分類。

三、數據集介紹

乳腺癌數據集,其實例數量是569,實例中包括診斷類和屬性,幫助預測的屬性是30,各屬性包括為radius 半徑(從中心到邊緣上點的距離的平均值),texture 紋理(灰度值的標准偏差)等等,類包括:WDBC-Malignant 惡性和WDBC-Benign 良性。用數據集的70%作為訓練集,數據集的30%作為測試集,訓練集和測試集中都包括特征和診斷類。

四、感知機算法的代碼實現與結果分析

代碼實現:

import pandas as pd#用pandas讀取數據
import matplotlib.pyplot as plt
import numpy as np
from sklearn import preprocessing

from matplotlib.colors import ListedColormap
from perceptron import Perceptron
from scipy.special import expit#這是sign()函數
from sklearn.model_selection import train_test_split

def loadDataSet():
# df=pd.read_csv("Breast_ Cancer_ Data.csv")
# # print(df.head())
# # print(df.tail())
# label=df.ix[:,1]
# data=df.ix[:,2:32]#數據類型沒有轉換,比如31.48,是str類型,需要將其轉換為float
#
# m=data.shape[0]
# data=np.array(data,dtype=float)
#
# for i in range(m):
# if label[i]=='B':
# label[i]=0
# else :
# label[i]=1
# train_x, test_x, train_y, test_y = train_test_split(data, label, test_size=0.30, random_state=0) # 划分數據集和測試集

df = pd.read_csv("Breast_ Cancer_ Data.csv")
dataArray=np.array(df)
testRatio=0.3
dataSize=dataArray.shape[0]
testNum=int(testRatio*dataSize)
trainNum=dataSize-testNum

train_x=np.array(dataArray[0:trainNum,2:],dtype=np.float)
test_x=np.array(dataArray[trainNum:,2:],dtype=np.float)
train_y=dataArray[0:trainNum,1]
test_y = dataArray[trainNum:, 1]
for i in range(trainNum):
if train_y[i]=='B':
train_y[i]=1
else:
train_y[i]=0
for i in range(testNum):
if test_y[i] == 'B':
test_y[i] = 1
else:
test_y[i] = 0

return train_x,test_x,train_y,test_y

# def sign(inner_product):
# if inner_product >= 0:
# return 1
# else:
# return 0

#學習模型,學的參數theta
def train_model(train_x,train_y,theta,learning_rate,iteration):
m=train_x.shape[0]
n=train_x.shape[1]

J_theta=np.zeros((iteration,1))#列向量
train_x=np.insert(train_x,0,values=1,axis=1)#相當於x0,加在第一列上
for i in range(iteration):#迭代
# temp=theta #暫存
# J_theta[i]=sum(sum((train_y-expit(np.dot(train_x,theta)))**2)/2.0)#dot是內積,sum函數是將減掉后的列向量求和成一個數
J_theta[i]=sum((train_y[:,np.newaxis]-expit(np.dot(train_x,theta)))**2)/2.0#dot是內積,sum函數是將減掉后的列向量求和成一個數

for j in range(n):#j是第j個屬性,但是所有屬性對應的的theta都要更新,故要循環
# temp[j]=temp[j]+learning_rate*np.dot((train_x[:,j].T)[np.newaxis],(train_y[:,np.newaxis]-expit(np.dot(train_x,theta))))#T是轉置
# temp[j]=temp[j]+learning_rate*np.dot(train_x[:,j].T,(train_y-expit(np.dot(train_x,theta))))#T是轉置
theta[j]=theta[j]+learning_rate*np.dot((train_x[:,j].T)[np.newaxis],(train_y[:,np.newaxis]-expit(np.dot(train_x,theta))))#T是轉置


# theta=temp

x_iteration=np.linspace(0,iteration,num=iteration)
plt.plot(x_iteration,J_theta)
plt.show()
return theta

def predict(test_x,test_y,theta):#假設theta是已經學習好的參數傳遞進來
errorCount=0
m=test_x.shape[0]
test_x=np.insert(test_x,0,values=1,axis=1)#相當於x0
h_theta = expit(np.dot(test_x, theta))

for i in range(m):
if h_theta[i]>0.5:
h_theta[i]=1
else:
h_theta[i]=0
if h_theta[i]!=test_y[i]:#test_y[i]需要是0或者1才能比較,因為h_theta[i]就是0或者1
errorCount+=1
error_rate=float(errorCount)/m
print("error_rate ",error_rate)

#特征縮放中的標准化方法,注意:numpy中的矩陣運算要多運用
def Standardization(x):#x是data
m=x.shape[0]
n=x.shape[1]
x_average=np.zeros((1,n))#x_average是1*n矩陣
sigma = np.zeros((1, n)) # sigma是1*n矩陣
x_result=np.zeros((m, n)) # x_result是m*n矩陣

x_average=sum(x)/m
# x_average = x.mean(axis=0)#用np的mean函數也可以求得每一列的平均值

# for i in range(n):
# for j in range(m):
# x_average[0][i] +=(float(x[j][i]))
# x_average[0][i]/=m

# sigma=(sum((x-x_average)**2)/m)**0.5#m*n的矩陣減去1*n的矩陣的話,會廣播,1*n的矩陣會復制成m*n的矩陣
sigma = x.var(axis=0) # 用np的var函數來求每一列的方差
# for i in range(n):
# for j in range(m):
# sigma[0][i]+=((x[j][i]-x_average[0][i])**2.0)
# sigma[0][i]=(sigma[0][i]/m)**0.5

x_result=(x-x_average)/sigma#對應的元素相除
# for i in range(n):
# for j in range(m):
# x_result[j][i]=(x[j][i]-x_average[0][i])/sigma[0][i]

return x_result

#特征縮放中的調節比例方法
def Rescaling(x):
m = x.shape[0]
n = x.shape[1]
x_min=np.zeros((1,n))#x_min是1*n矩陣
x_max=np.zeros((1,n))#x_max是1*n矩陣
x_result = np.zeros((m, n)) # x_result是m*n矩陣
# for i in range(n):
# x_min[0][i]=x[0][i]
# x_max[0][i]=x[0][i]
# for j in range(1,m):
# if x_min[0][i]>x[j][i]:
# x_min[0][i]=x[j][i]
# if x_max[0][i]<x[j][i]:
# x_max[0][i]=x[j][i]
# for i in range(n):
# for j in range(m):
# x_result[j][i]=(x[j][i]-x_min[0][i])/(x_max[0][i]-x_min[0][i])

x_min=x.min(axis=0)#獲得每個列的最小值
x_max=x.max(axis=0)#獲得每個列的最大值
x_result = (x - x_min) / (x_max - x_min)

return x_result


if __name__=='__main__':
train_x, test_x, train_y, test_y=loadDataSet()
# scaler=preprocessing.MinMaxScaler()
# train_x=scaler.fit_transform(train_x)
# test_x=scaler.fit_transform(test_x)

# train_x=Standardization(train_x)
# test_x=Standardization(test_x)

# train_x=Rescaling(train_x)
# test_x=Rescaling(test_x)

n=test_x.shape[1]+1
theta=np.zeros((n,1))
# theta=np.random.rand(n,1)#隨機構造1*n的矩陣
theta_new=train_model(train_x,train_y,theta,learning_rate=0.001,iteration=1000)#用rescaling的時候錯誤率0.017

predict(test_x, test_y, theta_new)


結果展示和分析:

感知機分類乳腺癌數據集的實驗

   實驗的迭代次數1000,學習率0.001,對特征縮放的方法效果進行比較,如表3所示。

表3 分類錯誤率和特征縮放的方法的關系

特征縮放

Standardization

Rescaling

分類錯誤率

0.182

0.017

 

Standardization標准化方法的J隨着迭代次數的變化圖如圖1所示:

 

圖1 標准化方法的效果圖

Rescaling調節比例方法的J隨着迭代次數的變化圖如圖2所示:

圖2 調節比例方法的效果圖

圖1 說明迭代次數和學習率等參數未調節到使效果較好的值;圖2的效果比較好,損失函數逐漸降低並且趨於平緩;比較兩種方法,相對來說調節比例的方法優於標准化方法。

 




免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM