在几位志同道合的小伙伴的带领下,开始了机器学习的路程,然而一切并不是想象的那么简单,因此本文记录了自己的学习路程,希望还能坚持做好这件事。
一个简单的例子,用Python语言实现朴素贝叶斯算法,这里不再介绍算法的理论思想,我会将自己看到的理解的东西写出来做记录,这些可能 是初学者比较困惑的地方。
1.关于连续属性的概率估计
我们针对离散属性的概率估计很好理解,比如说对训练数据中的House统计,很容易得到P(House=Yes|No)=3/7。
但对于Income这一个连续的属性,我们需要使用一点点处理方式来估计他们的概率。
(1)设置区间,比如说划分[120K,>120K),[70K,120K),(<70K,70K)这样子的区间,就可以将连续的属性离散化,但这样做有个很麻烦的问题就是如何才能选取适当的区间,这个问题的解决需要根据个人经验去判断。
(2)另一个估计连续属性的条件概率的方法是通过高斯分布计算。需要计算的有两个参数,均值μ和方差δ²。参数μ可以用标签Y下所有训练记录X样本的均值来估计,δ²可以用这些训练记录的样本方差来估计。
2.训练数据中某个属性的类条件概率等于0
从下面的实例中,我们可以计算得到P(Marriage=Married|Yes)=0,这就导致一个问题,比如我要统计X=(House=No,Marriage=Married,Income=120K)的类标号,我们计算得到的类Yes下的后验概率等于0。即如果某个属性的类条件概率等于0,将会导致整个类的后验概率等于0 。解决方法:
(1)条件概率的m估计(参考数据挖掘导论 Pang-Ning Tang等著)
P(xi|yi)=nc+mpn+m
其中,n是类 yi 中的实例总数, nc 是类 yi 训练集中取值 xi 的样例个数,m为等价样本大小的参数,而p为用户指定的参数
(2)贝叶斯估计
条件概率的贝叶斯估计为:
Pλ(X(j)=ajl|Y=ck)=∑i=1NI(x(j)i=ajl,yi=ck)+λ∑i=1NI(yi=ck)+Sjλ
λ≥0. 当λ=0的时候,就是极大似然估计,λ=1为拉普拉斯平滑(Laplace smoothing)。
先验概率的贝叶斯估计为:
Pλ(Y=ck)=∑i=1NI(yi=ck)+λN+Kλ
λ≥0,N为条件( Y=ck )下的样本总数,K为Y的种类数。通常按照拉普拉斯平滑(Laplace smoothing)估计概率,即取 λ=1
Tid House Marriage Income Borrower
1 Yes Single 125K No
2 No Married 100K No
3 No Single 70K No
4 Yes Married 120K No
5 No Divorced 95K Yes
6 No Married 60K No
7 Yes Divorced 220K No
8 No Single 85K Yes
9 No Married 75K No
10 No Single 90K Yes
Tid House Marriage Income
Test No Married 120K
def loadDataSet_train(path_read):
df = pd.read_csv(path_read, sep='\t', header=0, dtype=str, na_filter=False)
group = df[['House','Marriage','Income','Borrower']]
label = df["Borrower"]
return group
def loadDataSet_test(path_read):
df = pd.read_csv(path_read, sep='\t', header=0, dtype=str, na_filter=False)
group = df[['House','Marriage','Income']]
return group
#calculate mean and variance of the sample,and then return the probability of this Inx
def calculateProbability(Inx,dataSet):
mean = np.sum(dataSet)/len(dataSet)
dataSetSize = len(dataSet)
diffMat = np.tile(mean, (dataSetSize,1)) - dataSet
variance = np.sum(diffMat ** 2)/(dataSetSize-1)
probobility = np.exp(-((Inx-mean) ** 2/(2*variance))) * (1/(((2*np.pi)**0.5)*variance**0.5))
return probobility
#Through the tag classification, generate numpy two-dimensional array
def separateByClassYes(dataset):
separatedYes = []
for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] == 'Yes'):
separatedYes = np.append(separatedYes,np.array(vector),axis=0)
return separatedYes.reshape(-1,4)
def separateByClassNo(dataset):
separatedNo = []
for i in range(len(dataset)):
vector = dataset[i]
if (vector[-1] == 'No'):
separatedNo = np.append(separatedNo,np.array(vector),axis=0)
return separatedNo.reshape(-1,4)
def trainNB(trainMatrix,testMatrix):
newtrainMatrix = np.array(trainMatrix[0:,:3])
numTrain = len(newtrainMatrix)
calculateArr = np.zeros(newtrainMatrix.shape)
calculateArr[newtrainMatrix==testMatrix[0][0]]=1
calculateArr[newtrainMatrix==testMatrix[0][1]]=1
for i in trainMatrix[:,2]:
calculateArr[newtrainMatrix==i]=i[0:-1]
numFirstRank = sum(calculateArr[:,0])
numSecondRank = sum(calculateArr[:,1])
firstPrabobility = (numFirstRank+1)/(numTrain+2)
secondPrabobility = (numSecondRank+1)/(numTrain+2) #Laplace smoothing
trirdRank = calculateArr[:,2].reshape(-1,1)
trirdProbobility = calculateProbability(int(testMatrix[0][2]),trirdRank)
probobility = firstPrabobility*secondPrabobility*trirdProbobility
# print(probobility)
return probobility
初学者代码写得很low,在文章中有什么错误的地方还希望大家指正出来,一起交流。