最大似然法
from functools import reduce
coin_1 = float(input()) #硬币1正面朝上概率
coin_2 = float(input()) #硬币2正面朝上概率
coin_3 = float(input()) #硬币3正面朝上概率
h = int(input()) #正面朝上次数
t = int(input()) #反面朝上次数
# 实现概率计算
# 输入:w:正面朝上的概率 H:正面朝上的次数 T:反面朝上的次数
# 输出:H+T次抛硬币,H次正面朝上,T次反面朝上的概率值。
def calcu_prob(w,H,T):
########## Begin ##########
# 计算正反面组合数
f1 = Factorial(H + T) / (Factorial(H) * Factorial(T))
f2 = (w ** H) * ((1.0 - w) ** T)
return f1 * f2
########## End ##########
# 求正整数x的阶乘
# 输入:正整数x
# 输出:x的阶乘
def Factorial(x):
return reduce(lambda x, y: x * y, range(1, x + 1))
# 最大似然函数求解
# 输入: 硬币1,2,3正面朝上的概率coin_1,coin_2,coin_3, 正面朝上的次数h, 反面朝上的次数t
# 输出: 打印最大硬币的概率r与最大硬币的编号
def mle(coin_1,coin_2,coin_3,h,t):
########## Begin ##########
# 参考步骤
# 1. 计算三枚硬币各自的概率,保留三位小数
# 2. 建立硬币与概率的字典,方便索引
# 3. 选出最大值
# 4. 打印最大值
# 5. 通过字典索引打印硬币编号
# 1. 计算三枚硬币各自的概率,保留三位小数
a = round(calcu_prob(coin_1,h,t),3)
b = round(calcu_prob(coin_2,h,t),3)
c = round(calcu_prob(coin_3,h,t),3)
# 2. 建立a,b,c与字典方便索引
dict = {a:'coin_1',b:'coin_2',c:'coin_3'}
# 选出最大值
r = max(a,b,c)
print(r)
print(dict[r])
########## End ##########
if __name__ == "__main__":
# 主函数执行
mle(coin_1,coin_2,coin_3,h,t)
贝叶斯方法
import numpy as np
# 创建语料库。
# postingList的每一行,代表一个样本数据
# classVec是每个样本数据所对应的标签,0是非恶意留言,1是恶意留言
def loadDataSet():
postingList = [['I', 'pig', 'has', 'flea', 'problems', 'help', 'please'],
['maybe', 'not', 'take', 'him', 'to', 'dog', 'park', 'stupid'],
['my', 'dalmation', 'is', 'so', 'cute', 'I', 'love', 'him'],
['stop', 'posting', 'stupid', 'shit', 'garbage'],
['mr', 'licks', 'ate', 'my', 'steak', 'how', 'to', 'stop', 'him'],
['quit', 'buying', 'worthless', 'fuck', 'food', 'dick']]
classVec = [0, 1, 0, 1, 0, 1]
return postingList, classVec
# 根据vocabList词汇表,将inputSet向量化,向量的每个元素为1或0。
# 输入:
# vocabList就是createVocabList方法最后返回的元素不重复的数组(词汇表)
# inputSet是取的原始数据集里的某一行,比如:['my', 'dog', 'has', 'flea', 'problems', 'help', 'please']
# 输出:词向量returnVec
def setOfWords2Vec(vocabList, inputSet):
returnVec = [0] * len(vocabList) # 创建一个所有元素都是0的数组,长度和vocabList一样
for word in inputSet: # 将词库里的每个元素遍历
if word in vocabList: # 如果某个元素在词汇表里
returnVec[vocabList.index(word)] = 1 # 那就找到该元素在词汇表中的对应索引,并在returnVec里的同样索引位置赋值,值为1
return returnVec
# 将切分的实验样本词条整理成不重复的此条例列表,也就是词汇表
# 输入: dataSet语料库,即loadDataSet方法里的postingList数据集
# 输出:词汇表
def createVocabList(dataSet):
vocabSet = set([]) # 先创建一个空的字典(set创建字典,注意字典是不能有重复元素的)
for document in dataSet: # 将dataSet的每一行都进行遍历
vocabSet = vocabSet | set(document) # set(document)表示取每行的不重复数据,每次迭代后vocabSet返回值类似于:['my','dog','flea',.....]
# 最终的词汇表应该是
#{'is', 'mr', 'ate', 'has', 'problems', 'flea', 'cute', 'stop',
# 'park', 'pig', 'love', 'fuck', 'I', 'licks', 'maybe',
# 'help', 'shit', 'so', 'to', 'worthless', 'stupid', 'steak',
# 'buying', 'quit', 'dalmation', 'dick', 'him', 'please', 'take',
# 'posting', 'how', 'my', 'food', 'garbage', 'not', 'dog'}
# 将所有行的不重复数据都进行合并之后,最后得到整个dataSet的不重复的数据集,也就是词汇表并返回。
return list(vocabSet)
# 贝叶斯分类器训练函数
# 输入: 训练词向量trainMatrix与类别trainCategory
# 输出:
# p1Vect:表示恶意留言出现的概率
# p0Vect:表示非恶意留言出现的概率
# pAbusive:恶意留言文档占总文档的概率(比例)
def trainNB1(trainMatrix, trainCategory):
numTrainDocs = len(trainMatrix) # 计算训练的文档数目
numWords = len(trainMatrix[0]) # 计算每篇文档的词条数
# 计算恶意留言文档占总文档的概率(比例),请用pAbusive表示
########## Begin ##########
pAbusive = sum(trainCategory) / float(numTrainDocs)
########## End ##########
p0Num = np.ones(numWords);
p1Num = np.ones(numWords) # 创建numpy.ones数组,词条出现数初始化为1。
p0Denom = 2.0
p1Denom = 2.0 # 分母初始化为2。
# 对类别标签进行遍历,也就是对[0,1,0,1,0,1]的每个元素进行遍历,0代表非恶意,1代表恶意
for i in range(numTrainDocs):
# 如果是恶意的
if trainCategory[i] == 1:
# 那就把trainMatrix矩阵中对应的那一行的标签累加到p1Num上,得到频次p1Num。
# p1Num数组的意思:在整个词条中,第一个词出现的频次为2,第二个词频次为0,以此类推。
p1Num += trainMatrix[i]
# 然后,将所有词出现的次数累加到p1Denom上。
p1Denom += sum(trainMatrix[i])
# 如果是非恶意的,同样操作,将得到非恶意留言文档的结果。
else:
p0Num += trainMatrix[i]
p0Denom += sum(trainMatrix[i])
# 最后需要分别计算在恶意留言和非恶意留言中,每个词出现的概率。
# 请用变量p1Vect表示恶意留言出现的概率,用变量p0Vect表示非恶意留言出现的概率。
# 注意结果取对数,防止下溢出。
########## Begin ##########
p1Vect = np.log(p1Num / p1Denom)
p0Vect = np.log(p0Num / p0Denom)
########## End ##########
return p0Vect, p1Vect, pAbusive
# 朴素贝叶斯分类器分类函数
# 输入:
# vec2Classify是待测试的词条
# p0Vec是非恶意留言的条件概率数组
# p1Vec是恶意留言的条件概率数组
# pClass1是文档属于恶意留言的概率
# 输出:0或1。(1代表恶意留言,0代表非恶意留言)
def classifyNB(vec2Classify, p0Vec, p1Vec, pClass1):
# 计算概率。注意计算公式可以省略贝叶斯公式里的分母,因为不管是计算p0还是p1,分母都是一样的,而我们要比较概率的大小,只需要比较分子即可。
# 计算该文档属于恶意留言的概率,用变量p1表示。
# 计算该文档属于非恶意留言的概率,用变量p0表示。
########## Bengin ##########
p1 = sum(vec2Classify * p1Vec) + np.log(pClass1)
p0 = sum(vec2Classify * p0Vec) + np.log(1.0 - pClass1)
########## End ##########
if p1 > p0:
# 如果p1大于p0,说明属于恶意留言的可能性更大,返回1,(1代表恶意留言)。反之,则返回0(代表非恶意留言)。
return 1
else:
return 0
# 测试函数
def testingNB():
listOPosts, listClasses = loadDataSet() # 加载语料库
myVocabList = createVocabList(listOPosts) # 创建词汇表
trainMat = []
for postinDoc in listOPosts:
trainMat.append(setOfWords2Vec(myVocabList, postinDoc)) # 样本向量化
p0V, p1V, pAb = trainNB1(np.array(trainMat), np.array(listClasses)) # 训练朴素贝叶斯分类器
# 处理输入。请输入词汇表中的词,多个分词请用英文逗号隔开,否则会不通过。
testEntry = input()
testEntry = testEntry.split(',')
thisDoc = np.array(setOfWords2Vec(myVocabList, testEntry))
# 执行分类并打印分类结果
if classifyNB(thisDoc, p0V, p1V, pAb):
print('1')
else:
print('0')
if __name__ == '__main__':
testingNB()