소박 한 베 이 루스 - 분류 및 Sklearn 라 이브 러 리 실현 (2) 기계 학습 실전

13697 단어 기계 학습
지난 글 에서 우 리 는 소박 한 베 이 루스 의 전제조건 과 실현 과정 을 간단하게 소개 하고 몇 가지 유행 하 는 소박 한 베 이 루스 분류법 을 소개 하여 가장 기본 적 인 텍스트 분 류 를 실현 했다. 이 글 은 소박 한 베 이 루스 분 류 를 계속 소개 할 것 이다. 이번 에는 주로 스 팸 메 일 여과 절 차 를 통 해 베 이 루스 분 류 를 심화 시 킬 것 이다.또한 sklearn 라 이브 러 리 를 통 해 상기 세 가지 소박 한 분류 기의 효 과 를 실현 하고 몇 가지 소박 한 베 이 루스 분류 알고리즘 의 정확성 을 비교 합 니 다.
    스 팸 메 일 여과 에 있어 서 우 리 는 먼저 메 일 데 이 터 를 일정한 처리 해 야 알고리즘 을 사용 할 수 있 습 니 다. 첫 번 째 단 계 는 텍스트 를 구분 하고 텍스트 를 하나의 독립 된 문자 로 나 누 는 것 입 니 다. 그러나 이 중 에는 쓸모없는 문자 나 구두점 기호 와 유사 할 수 있 습 니 다. 우 리 는 먼저 이 문자 들 을 읽 기 텍스트 에서 제거 해 야 합 니 다. 그 밖 에...텍스트 데이터 의 일치 성 을 유지 하기 위해 서 우 리 는 모든 문자 가 소문 자 상태 이 기 를 바 랍 니 다. 이렇게 하면 분류 식별 에 더욱 편리 합 니 다. 그래서 우 리 는 python 자체 명령 lower () 를 호출 하여 문 자 를 추출 하 는 소문 자 화 를 실현 합 니 다.이러한 데 이 터 를 초기 에 처리 한 후에 우 리 는 이전의 사상 에 따라 스 팸 메 일 을 여과 하여 분류 할 수 있다.
1. 먼저 우 리 는 지난 글 의 일부 함 수 를 가 져 왔 습 니 다. 이 스 팸 메 일 여과 역시 그들 이 실력 을 발휘 해 야 합 니 다. 함수 기능 은 지난 편 에서 이미 소개 되 었 습 니 다. 여기 서 간단하게 말씀 드 리 겠 습 니 다.
createVocablist (dataSet): dataSet 에서 문 자 를 추출 하고 모든 dataSet 의 문 자 를 중복 되 지 않 은 목록 을 되 돌려 줍 니 다.
set0fWords2Vec (vocablist, inputSet): 이전 함수 에 따라 생 성 된 중복 없 는 목록 은 입력 문자 목록 에서 입력 목록 에 있 는 문자 의 출현 횟수 를 중복 없 는 목록 의 대응 위치 에 각각 추가 합 니 다.
trainNB 0 (trainMatrix, trainCategory): 바 뀐 훈련 집 과 훈련 집 라벨 에 따라 베 이 루스 공식 에 필요 한 몇 가지 확률 치 를 구 합 니 다.
classifyNB (vec2Classifiy, p0Vec, p1Vec, p1class): 테스트 형식 으로 변 환 된 입력 문자 vec2classifiy 와 구 한 p0v, p1v, p1class 를 통 해 후 험 확률 에 따라 텍스트 분 류 를 추측 합 니 다.
import re
import random
from numpy import *

def createVocabList(dataSet):
	# """
	# :params:
	# :dataSet:      ,           
	# :return:  datSet         
	# """
    
    vocabSet = set([])  #create empty set
    for document in dataSet:
        vocabSet = vocabSet | set(document) #union of the two sets
    return list(vocabSet)

def setOfWords2Vec(vocabList, inputSet):
	# """
	# :params:
	# :vocablist:         
	# :inputSet:       
	# return:bool   ,  vocablist   

	# """
    returnVec = [0]*len(vocabList)
    for word in inputSet:
        if word in vocabList:
            returnVec[vocabList.index(word)] = 1
        else: print ("the word: %s is not in my Vocabulary!" % word)
    return returnVec

def trainNB0(trainMatrix,trainCategory):
	#"""
	#:params:
	#:trainMatri   
	#:trainCategory     
	#return p(C0|wi) p(C1|wi) p(Ci)
	#"""

    numTrainDocs = len(trainMatrix)
    numWords = len(trainMatrix[0])
    pAbusive = sum(trainCategory)/float(numTrainDocs)
    p0Num = ones(numWords); p1Num = ones(numWords)#               
    p0Denom = 2.0; p1Denom = 2.0  #                   N 2                      
    for i in range(numTrainDocs):
        if trainCategory[i] == 1:
            p1Num += trainMatrix[i]
            p1Denom += sum(trainMatrix[i])
        else:
            p0Num += trainMatrix[i]
            p0Denom += sum(trainMatrix[i])
    p1Vect = log(p1Num/p1Denom)          
    p0Vect = log(p0Num/p0Denom)          
    return p0Vect,p1Vect,pAbusive

def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
    p1 = sum(vec2Classify * p1Vec) + log(pClass1)    #        ,      1 
    p0 = sum(vec2Classify * p0Vec) + log(1.0 - pClass1)
    if p1 > p0:#            ,           
        return 1
    else: 
        return 0 

다음은 테스트 알고리즘 입 니 다. 소박 한 베 이 루스 로 교차 검증 을 합 니 다.
def textParse(bigString):
	import re
	listOfTokens=re.split(r'\W*',bigString)#   ,   ,   
	return [tok.lower() for tok in listOfTokens if len(tok)>2] #    2        


함수 textParse 는 주로 입력 한 데 이 터 를 문장 첫머리 에 말 한 데 이 터 를 미리 처리 하고 필요 하지 않 은 기호 문 자 를 제거 하 며 문자 의 길이 에 따라 너무 짧 고 의미 가 크 지 않 은 문 자 를 버 리 고 이상 적 인 데이터 세트 를 되 돌려 줍 니 다.
def spamTest():
	docList = []; classList = []; fullText = []
	for i in range(1,26):#               25
		wordList = textParse(open('email/spam/%d.txt' % i ,'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(1)
		wordList = textParse(open('email/ham/%d.txt' % i, 'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(0)
	vocabList = createVocabList(docList)#           
	trainingSet = list(range(50));testSet= []
	
	for i in list(range(10)):#       ,      10
		randIndex = int(random.uniform(0,len(trainingSet)))
		testSet.append(trainingSet[randIndex])
		del(trainingSet[randIndex])
	trainMat = []; trainClasses = []
	for docIndex in trainingSet:#     ,         
		trainMat.append(setOfWords2Vec(vocabList,docList[docIndex]))#               
		trainClasses.append(classList[docIndex])#                
	p0V,p1V,pSpam = trainNB0(array(trainMat),array(trainClasses))
	#                       ,           
	errorCount = 0#        
	for docIndex in testSet:#        
		wordVector = setOfWords2Vec(vocabList,docList[docIndex])#         
		if classifyNB(array(wordVector),p0V,p1V,pSpam) != classList[docIndex]:#             
			#           ,       1
			errorCount += 1
	# print('the error rate is : ',float(errorCount)/len(testSet))#     
	
	return float(errorCount)/len(testSet)

두 번 째 함수 spamTset 은 첫 번 째 글 에 대한 호출 입 니 다. 먼저 textParse 함수 가 되 돌아 온 데이터 세트 를 중복 없 는 목록 으로 추출 하고 classlist 에 해당 하 는 분 류 를 추가 합 니 다. 그 다음 에 교차 검증 입 니 다. 50 통 의 메 일 에서 10 통 을 테스트 집합 으로 추출 하고 40 통 을 훈련 집합 으로 하여 알고리즘 의 정확성 을 검증 합 니 다.라 이브 러 리 를 조정 하지 않 으 면 여기 서 교차 검증 을 실현 하 는 방법 은 앞으로 도 참고 할 수 있 을 것 같 습 니 다. 한 정 된 범위 내 에서 random 함 수 를 사용 하여 랜 덤 으로 색인 을 생 성하 여 훈련 집 과 테스트 집 을 나 눌 수 있 습 니 다.다음은 알고리즘 분류 정확 도 를 검증 하기 시작 합 니 다. 먼저 다음 코드 를 가 져 옵 니 다.
ratio = []
for i in range(50):
	ratio.append(spamTest())
print('the total right rate is : ',(1.0-float(sum(array(ratio)))/50.0)*100,'%')

여기 서 우 리 는 교차 검 증 된 프로그램 을 50 회 순환 시 켜 50 회의 계산 을 통 해 분류의 평균 정확 도 를 얻 을 것 이다.
the total right rate by <<>> is :  96.39999999999999 %

우 리 는 계산 을 통 해 50 번 의 평균 예측 율 이 96.39% 이 고 분류 정확 도 는 이미 좋 은 편 이다. 물론 교차 검증 과 random 함수 의 임 의 성 으로 인해 이 수 치 는 매번 프로그램 이 다 를 수 있 지만 대체적으로 이 수치 부근 에서 변동 하여 큰 오차 가 나 지 않 을 것 이다.
2. 다음 에 우 리 는 지난 글 에서 언급 한 GaussianNB 고 스 박 소 베 이 루스, MultinomialNB 여러 가지 분포 소박 한 베 이 루스 와 BernoulliNB 다 중 베 르 누 리 분포 소박 한 베 이 루스 알고리즘 이 sklearn. cross 에 있 습 니 다.vaidation 교차 검증 을 바탕 으로 알고리즘 분류 검증 을 하고 상기 알고리즘 을 포함 한 네 가지 알고리즘 의 정확도 높 고 낮 음 을 비교 합 니 다.
A. 가우스 소박 베 이 루스
def sklearnNB(test_size = 0.2):#       
	from sklearn.naive_bayes import GaussianNB
	from sklearn.cross_validation import train_test_split
	
	docList = []; classList = []; fullText = []
	for i in range(1,26):
		wordList = textParse(open('email/spam/%d.txt' % i ,'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(1)
		wordList = textParse(open('email/ham/%d.txt' % i, 'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(0)
	
	vocabList = createVocabList(docList)#           

	total_Mat = []#            list 
	for data in docList:
		train_data =setOfWords2Vec(vocabList,data) 
		total_Mat.append(train_data)
	#           ,   
	X_train,X_test, y_train, y_test =  train_test_split(total_Mat,classList,test_size=test_size) 

	errorCount = 0#        
	
	gnb = GaussianNB()#    bayes  
	gnb.fit(X_train,y_train)#    
	
	email_predicted = gnb.predict(X_test)

	for i in range(int(len(total_Mat)*test_size)):
		if email_predicted[i] != y_test[i]:
			errorCount += 1
	# print('the total right rate is : ',(1.0-float(errorCount)/50.0)*100,'%')
	return float(errorCount)/len(y_test)

, Sklearn , , , test_size = 0.2, , , , :

ratio = []
for i in range(50):
	ratio.append(sklearnNB())
print('the total right rate by <<>> is : ',(1.0-float(sum(array(ratio)))/50.0)*100,'%')

, 50 。

the total right rate by <<>> is :  96.8 %

, , , 。


MultinomialNB BernoulliNB , , , 。

B.

def sklearnNB(test_size = 0.2):
	from sklearn.naive_bayes import MultinomialNB
	from sklearn.cross_validation import train_test_split
	
	docList = []; classList = []; fullText = []
	for i in range(1,26):
		wordList = textParse(open('email/spam/%d.txt' % i ,'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(1)
		wordList = textParse(open('email/ham/%d.txt' % i, 'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(0)
	
	vocabList = createVocabList(docList)#           

	total_Mat = []#            list 
	for data in docList:
		train_data =setOfWords2Vec(vocabList,data) 
		total_Mat.append(train_data)
	#           ,   
	X_train,X_test, y_train, y_test =  train_test_split(total_Mat,classList,test_size=test_size) 

	errorCount = 0#        
	
	gnb = MultinomialNB()#     bayes  
	gnb.fit(X_train,y_train)#    
	
	email_predicted = gnb.predict(X_test)

	for i in range(int(len(total_Mat)*test_size)):
		if email_predicted[i] != y_test[i]:
			errorCount += 1
	# print('the total right rate is : ',(1.0-float(errorCount)/50.0)*100,'%')
	return float(errorCount)/len(y_test)
    
ratio = []
for i in range(50):
	ratio.append(sklearnNB())
print('the total right rate by <<>> is : ',(1.0-float(sum(array(ratio)))/50.0)*100,'%')
the total right rate by <<>> is :  96.39999999999999 %

~ , 。


C.BernoulliNB

def sklearnNB(test_size = 0.2):
	from sklearn.naive_bayes import BernoulliNB
	from sklearn.cross_validation import train_test_split, cross_val_score
	
	docList = []; classList = []; fullText = []
	for i in range(1,26):
		wordList = textParse(open('email/spam/%d.txt' % i ,'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(1)
		wordList = textParse(open('email/ham/%d.txt' % i, 'r').read())# text    
		docList.append(wordList)#   wordlist
		fullText.extend(wordList)
		classList.append(0)
	
	vocabList = createVocabList(docList)#           

	total_Mat = []#            list 
	for data in docList:
		train_data =setOfWords2Vec(vocabList,data) 
		total_Mat.append(train_data)
	#           ,   
	X_train,X_test, y_train, y_test =  train_test_split(total_Mat,classList,test_size=test_size) 

	errorCount = 0#        
	
	gnb = BernoulliNB()#     bayes  
	gnb.fit(X_train,y_train)#    
	
	email_predicted = gnb.predict(X_test)

	for i in range(int(len(total_Mat)*test_size)):
		if email_predicted[i] != y_test[i]:
			errorCount += 1
	# print('the total right rate is : ',(1.0-float(errorCount)/50.0)*100,'%')
	return float(errorCount)/len(y_test)
    
ratio = []
for i in range(50):
	ratio.append(sklearnNB())
print('the total right rate by <<>> is : ',(1.0-float(sum(array(ratio)))/50.0)*100,'%')
the total right rate by <<>> is :  90.60000000000001 %

, , 89%-91% , BernoulliNB C i, MultinomialNB , , 。 , , 。


, , , , , , 《 》 EM ; , , , , 。 ~





좋은 웹페이지 즐겨찾기