实验一 朴素贝叶斯分类方法
1.
案例简介
利用朴素贝叶斯分类方法对文本数据进行情感分析,进而设计一 个留言板过滤系统.(以下代码实现不要使用 SKLEARN 模块)
2.
数据采集
以下表格中是一个文本分类的问题,区分一句话是粗鲁的还是文 明的,类别标签只有 Yes 或 No,表示是粗鲁的和不是粗鲁的语句。
![72f75c9dd6ba4c9cbac1a319964b8445.png](https://i-blog.csdnimg.cn/blog_migrate/b26434ee42ae3fd5980c3e6ec9dab139.png)
3.
数据预处理
给定一个
词典【”my”,“name”,“is”,“Devin”,“you”,“are”,“stupid”, “boyfriend”,“SB”,“looks”,“very”,“smart”,”like”,”much”】需要将 每一段文字进行离散化,即进行空间向量化。
4.
建模与分析
p1Vecp1Vec:表示正样本条件下的各单词的出现的概率,即条件 概率 p(
x
i |y=yes), p1Num=[1,0,1,0,1,1,1,1,1,0,0,0,0,0]
p1Vecp1Vec:表示负样本条件下的各单词的出现的概率,即条件 概率 p(
x
i |y=no), p0Num=[2,1,1,1,2,0,0,0,0,1,2,1,1,1]
样本中在类标签为 1 的单词出现的总次数 p1Count=7
样本中让举证 p1Num 和 p0Num 分别除以 p1Count 和 p0Count, 即可以得到各自的条件概率:
P1Vec=[1/7,0,1/7,0,1/7,1/7,1/7,1/7,1/7,0,0,0,0,0]p1
P2Vec=[1/7,0,1/7,0,1/7,1/7,1/7,1/7,1/7,0,0,0,0,0]
最后计算概率并比较大小
p1=p(y=1)*{p(x1|y=1) *p(x2|y=1)...p(xn|y=1)}
p0=p(y=0) *{p(x1|y=0) *p(x2|y=0)...p(xn|y=0)}
利用朴素贝叶斯分类方法测试语句“I like you.”是粗鲁的和不是粗鲁?(答案不粗鲁)
5.Python代码实现
import numpy as np
#数据采集
def load_dataset():
sent_list=[['my','name','is','Devin'],
['you','are','stupid'],
['my','boyfriend','is','SB'],
['you','looks','very','smart','I','like','you','very','much']]
class_vec=[-1,1,1,-1] #-1代表不粗鲁,1代表粗鲁
return sent_list,class_vec
#数据预处理
def create_vocab_list(dataset):
vocab_set=set([])
for doc in dataset:
vocab_set=vocab_set | set(doc)
return list(vocab_set)
def set_of_words2vec(vocab_list,input_set): #将每一段文字进行离散化,即进行空间向量化
return_vec=[0]*len(vocab_list)
for word in input_set:
if word in vocab_list:
return_vec[vocab_list.index(word)]=1
return return_vec
#建模与分析
def trainNB(train_matrix,train_catagory):
num_train_docs=len(train_matrix)
num_words=len(train_matrix[0])
pos_num=0
for i in train_catagory:
if i==1:
pos_num+=1
pAbusive=pos_num/float(num_train_docs)
p0_num=np.ones(num_words)
p1_num=np.ones(num_words)
p0_demon = 2.0
p1_demon = 2.0
for i in range(num_train_docs):
if train_catagory[i] == 1:
p1_num += train_matrix[i] #p1_num=[1,0,1,0,1,1,1,1,1,0,0,0,0,0]
p1_demon += sum(train_matrix[i])#样本中在类标签为1的单词出现的总次数p1_demon=7
else:
p0_num += train_matrix[i] #p0Num=[2,1,1,1,2,0,0,0,0,1,2,1,1,1]
p0_demon += sum(train_matrix[i])#样本中在类标签为2的单词出现总次数p0_demon=3
p1_vect = np.log(p1_num / p1_demon)#举证p1_num和p0_num分别除以p1_demon和p0_demon即可以得到各自的条件概率
p0_vect = np.log(p0_num / p0_demon)
return p0_vect, p1_vect, pAbusive #p1_vect表示正样本条件下的各单词的出现的概率,即条件概率 p(xi|y=yes)
#同理,p0_vect表示负样本条件下的各单词的出现的概率,即条件概率 p(xi|y=no)
#计算概率比较大小
def classifyNB(vec2classify,p0_vec,p1_vec,pClass1):
p1 = sum(vec2classify * p1_vec) + np.log(pClass1)
p0 = sum(vec2classify * p0_vec) + np.log(1.0 - pClass1)
if p1>p0:
return 1
elif p0>p1:
return -1
else:
return 0
list_sents, list_classes = load_dataset()
my_vocab_list = create_vocab_list(list_sents)
train_mat = []
for sent_in_doc in list_sents:
train_mat.append(set_of_words2vec(my_vocab_list, sent_in_doc))
p0V,p1V,pAb=trainNB(train_mat,list_classes)
test_entry=['I','like','you']
print("利用朴素贝叶斯测试语句“I like you”是粗鲁还是不粗鲁:")
print("1代表粗鲁,-1代表不粗鲁")
print("结果为:")
print(classifyNB(np.array(set_of_words2vec(my_vocab_list,test_entry)),p0V,p1V,pAb))
案例二
import pandas as pd
import numpy as np
X=["<=30","medium","yes","fair"]
data=pd.read_csv("C:/Users/wcj770801/Desktop/Python/Computers.txt",encoding="utf-8")
column_id=data.columns
label=data[column_id[-1]]#获取类标签
P_apriori=label.value_counts()/len(label)
group=data.groupby(column_id[-1])
p_label=np.empty((len(column_id)-1,label.nunique()))
for i in range(len(column_id)-1):
count=group[column_id[i]].value_counts().unstack()
count.fillna(0)#填充缺失值
p_label[i,:]=count[X[i]]/(count.sum(axis=1))
P_X=pd.DataFrame(p_label,columns=group.groups.keys())
P_X=P_X.prod()
P_bayes=P_X*P_apriori
print(f"预测结果为{P_bayes.idxmax()}")
##classes=label.unique()
## count=group[column_id[i]].value_counts()
## idx=[ (ele,X[i]) for ele in classes]
## a=count[idx]
## b=label.value_counts().sort_index()
## p_label[i,:]=a.values/b.values
##P_X=pd.DataFrame(p_label,columns=["no","yes"],index=data.columns[:-1])
##P_X=P_X.prod()
##P_bayes=P_X*P_apriori
##print(f"预测结果为{P_bayes.idxmax()}")
实验二 K近邻分类
案例一 海伦交友案例
案例简介
我的朋友海伦一直使用在线约会网站寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她没有从中找到喜欢的人。经过 一番总结,她发现曾交往过三种类型的人:
“不喜欢的人”、“魅力一
般的人”以及“极具魅力的人”。尽管发现了上述规律,但海伦依然无法将约会网站推荐的匹配对象归人恰当的分类。她觉得可以在周一到周五约会那些魅力一般的人,而周末则更喜欢与那些极具魅力的人为伴。海伦希望我们的分类软件可以更好地帮助她将匹配对象划分到确切的分类中。此外海伦还收集了一些约会网站未曾记录的数据信息,她认为这些数据更有助于匹配对象的归类。
1.
数据准备
海伦收集约会数据已经有了一段时间,她把这些数据存放在文本文件 dating TestSet. txt 中,每个样本数据占据一行,总共有 1006 海伦的样本主要包含以下 3 种特征:“每年获得的飞行常客里程数”、“玩视频游戏所耗时间百分比”以及“每周消费的冰淇淋公升数”。
2.
数据预处理
因数据属性的量纲不一致,需要进行归一化处理。
3.
数据建模
在分类准确率准则指导下,利用十折交叉验证确定最优的参数 k。
4.
模型预测
上面我们已经在数据上对分类器进行了测试,现在终于可以使用这个分类器为海伦来对人们分类。我们会给海伦一小段程序,通过该程序海伦会在约会网站上找到某个人并输入他的信息。程序会给出她对对方喜欢程度的预测值。
import matplotlib
import matplotlib.pylab as plt
# 计算函数
def classify0(inX, dataSet, labels, k):
dataSetSize = dataSet.shape[0]
diffMat = tile(inX, (dataSetSize,1)) - dataSet
sqDiffMat = diffMat**2
sqDistances = sqDiffMat.sum(axis=1)
distances = sqDistances**0.5
sortedDistIndicies = distances.argsort()
classCount={}
for i in range(k):
voteIlabel = labels[sortedDistIndicies[i]]
classCount[voteIlabel] = classCount.get(voteIlabel, 0) + 1
sortedClassCount = sorted(classCount.items(), key=operator.itemgetter(1), reverse=True)
return sortedClassCount[0][0]
# 1.将文本记录转换到numpy的解析程序
def file2matrix(filename):
fr = open(filename)
numberOfLines = len(fr.readlines())
# 该数据集有 三个特征值 一个目标向量
returnMat = zeros((numberOfLines, 3))
classLabelVector = []
index = 0
fr = open(filename)
for line in fr.readlines():
line = line.strip()
listFromLine = line.split('\t')
print("\t分割后的列表:", listFromLine)
returnMat[index, :] = listFromLine[0:3] # 提取前三个特征值赋值给矩阵
print("第", index, "行得到的列表", returnMat[index, :])
classLabelVector.append(listFromLine[-1]) # 提取位于尾末的目标向量
index += 1
return returnMat, classLabelVector
# 2.分析数据 散点图
def printData(data):
plt.rcParams['font.sans-serif'] = ['Simhei']
fig = plt.figure()
# 定义ax为大图中的子图 111:一行一列第一个
ax = fig.add_subplot(111)
# 画ax子图 坐标轴为特征值列表 索引为特征值
#plt.scatter(data[:, 0], data[:, 1])
plt.scatter(data[:, 0], data[:, 2])
#plt.scatter(data[:, 1], data[:, 2])
plt.xlabel("每年获得的飞行常客里程数")
#plt.xlabel("玩游戏每周所占时间")
#plt.ylabel("玩游戏每周所占时间")
plt.ylabel("每周消费冰激凌数")
plt.show()
# 3.数据归一化处理
def autoNormal(dataSet):
minVals = dataSet.min(0) # 参数0 按列查找最小值
maxVals = dataSet.max(0)
ranges = maxVals - minVals
normDataSet = zeros(shape(dataSet))
m = dataSet.shape[0]
normDataSet = dataSet - tile(minVals, (m, 1))
normDataSet = normDataSet / tile(ranges, (m, 1))
return normDataSet, ranges, minVals
# 测试分类器
def datingClassTest(filename):
hoRatio = 0.1 # 随机取数据集的10%
datingDataMat,datingLabels = file2matrix(filename)
printData(datingDataMat)
normMat, ranges, minVals = autoNormal(datingDataMat) # 加载归一化数据
m = normMat.shape[0]
numTestVecs = int(m*hoRatio) # 取得10%数据
errorCount = 0.0 # 错误预测数初始化
for i in range(numTestVecs):
classifierResult = classify0(normMat[i, :], normMat[numTestVecs:m, :], datingLabels[numTestVecs:m], 3)
print("数据中的是: %s, 真正的答案是: %s" % (classifierResult, datingLabels[i]))
# the classifier came back with: largeDoses, the real answer is: largeDoses
# the classifier came back with: smallDoses, the real answer is: smallDoses
# the classifier came back with: didntLike, the real answer is: didntLike
if (classifierResult != datingLabels[i]): errorCount += 1.0
print("总的错误率为: %d" % ((errorCount/float(numTestVecs))*100), "%")
print(errorCount)
if __name__ == '__main__':
datingClassTest("C:/Users/wcj770801/Desktop/Python/datingTestSet.txt")
案列二 手写自案例
案例简介:
手写识别是常见的图像识别任务。计算机通过手写体图片来识别出图片中的字,与印刷字体不同的是,不同人的手写体风格迥异,大小不一, 造成了计算机对手写识别任务的一些困难。数字手写体识别由于其有限的类别(0~9 共 10 个数字)成为了相对简单的手写识别任务。
1.
数据准备
压缩文件“digits.zip”中的文件“trainingDigits”文件夹中有 204个 txt 文件,其中每个文件对应于数字“1-9”中的某一个(经过处理为 32*32 的 0-1 数字矩阵),效果如下图所示。读取此 204 文件,并
将此每个文件中的数据转化为 1024 维的行向量,以作为训练集。
注
意:以“0_2.txt”为例,文件名中 0 代表此文件对应数字 0,即此数据向量的类标签为 2。
提示:利用 from os import listdir 获取当前文件夹中的所有文件,然后再转化为向量,并利用字符串的 split(“_”)[0]方法获取每条数据的类标签。
2.
模型构建
利用交叉验证选择最优的近邻数 K。
3.
预测分类
读取“digits.zip”中的文件夹 testDigits 中的所有数据文件,并利用上述方式对其进行向量化操作,最后利用构建的模型对其进行预测。
4.
模型评估
计算一下模型的预测分类准确率多少?
##手写自案例实验
from os import listdir
import pandas as pd
import numpy as np
#f_lists = listdir(r'.\trainingDigits')
#labels=[ins.split('_')[0] for ins in f_lists]
#data1=pd.read_csv(r'.\trainingDigits\\'+f_lists[0])
#print(data1)
#图像格式化为一个向量
#def img2vector(filename):
# returnVect = zeros((1,1024))
# fr = open(filename)
# for i in range(32):
# lineStr = fr.readline()
# for j in range(32):
# returnVect[0,32*i+j] = int(lineStr[j])
# return returnVect
def handwritingClassTest():
hwLabels = []
trainingFileList = listdir('trainingDigits')
m = len(trainingFileList)
trainingMat = zeros((m, 1024))
for i in range(m):
fileNameStr = trainingFileList[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
hwLabels.append(classNumStr)
trainingMat[i, :] = img2vector('trainingDigits/%s' % fileNameStr)
testFileList = listdir('testDigits')
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
fileNameStr = testFileList[i]
fileStr = fileNameStr.split('.')[0]
classNumStr = int(fileStr.split('_')[0])
vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
classifierResult = classify0(vectorUnderTest, trainingMat, hwLabels, 3)
print( "the classifier came back with: %d, the real answer is: %d" % (classifierResult, classNumStr))
if (classifierResult != classNumStr): errorCount += 1.0
print("\nthe total number of errors is: %d" % errorCount)
print("\nthe total error rate is: %f" % (errorCount/float(mTest)))
if __name__ == '__main__':
handwritingClassTest()
实验三 分类度量
案例简介
为让大家充分理解类不平等问题利用朴素贝叶斯分类方法对文本数据进行情感分析,进而设计一个留言板过滤系统.(以下代码实现不要使用 SKLEARN 模块)
ROC
图制作与
AUC
取值计算
(1)读取数据集“balance.dat”,并将类别属性"class"取值为"L"的类定义为正例,取值为"R"的类定义为负类
(2)将数据集分解为训练集和测试集(大小比例为 4:1)
(3)分别利用决策树和朴素贝叶斯建模,并将在二维平面上画出两算法的 ROC
(4)计算两种算法的 AUC,并比较两算法分类性能的优劣.
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn import discriminant_analysis
import matplotlib.pyplot as plt
import matplotlib
data=pd.read_csv("C:/Users/wcj770801/Desktop/Python/balance.dat",sep=",",encoding="utf-8")
column_id=data.columns
label=data[column_id[-1]]
{'R':0,'L':1}
matplotlib.rcParams['font.family'] = 'Microsoft YaHei'
matplotlib.rcParams['font.sans-serif'] = ['Microsoft YaHei']
plt.scatter(data["Class"], label="R")
plt.scatter(data["Class"], label="L")
plt.legend()
plt.show()
x_exam=data[column_id[:4]]
y_exam=data[column_id[-1]]
x_train,x_test,y_train,y_test=train_test_split(x_exam,y_exam,train_size=float(1)/5)
lda = discriminant_analysis.LinearDiscriminantAnalysis()
lda.fit(x_train, y_train)