最大熵模型(Maximum Entropy)

来源:互联网 发布:python与 shell 编辑:程序博客网 时间:2024/05/22 01:55


五.Python代码实现

from collections import defaultdictimport mathclass maximumEntropy(object):    def __init__(self):        self.feats=defaultdict(int) #创建一个类似字典的结构,区别在于defaultdict对于不存在的key的value默认为零        self.trainSet=[]        self.labels=set() #分类标签的集合            def loadData(self,filename):        for line in open(filename):            fields=line.strip().split()            label=fields[0] #我们已知每个样本数据的第一个元素是标签/类别            self.labels.add(label)            self.trainSet.append(fields) #将原始数据转化成了二维的list形式            for f in set(fields[1:]):                self.feats[(label,f)]+=1 #一个字典key是(类别/标签,feature/如,单词),value是该形式出现次数                def initialization(self):        self.size=len(self.trainSet) #样本容量        self.M=max([len(self.trainSet[i]) for i in range(self.size)]) #训练数据中包含特征最多的样本中的特征数,其倒数作为学习率        self.w=[0.0]*len(self.feats)   #初始化权重为零        self.bestw=self.w            #初始化最终权重为零        def experienceDE(self): #计算经验分布期望        self.ep_=[0.0]*len(self.feats)   #经验分布期望是一个大小为i的列表,i的大小是样本中出现的(label,feature)的种类        for i,f in enumerate(self.feats): #i表示取得第几次从零开始,f是取得key值            self.ep_[i]=float(self.feats[f]/self.size)            self.feats[f]=i #设置feats的value值为他的索引或者序列数        def conditionalProbability(self,features): #计算条件概率P(y|x)        numeratorVec=[(self.expSum(features,la),la) for la in self.labels] #返回P(y|x)的分子的向量,向量大小为标签总数        denominator=sum([numerator for numerator,label in numeratorVec])  #计算出P(y|x)的分母的值        cP=[(numerator/denominator,label) for numerator,label in numeratorVec] #返回(P(yi|x),yi)  for yi in labels        return cP            def expSum(self,features,label): #P(y|x)的分子的向量        numerator=0.0                      for f in features:            if (label,f) in self.feats: #判断该样本中所有特征与输入标签的组合是否在feats的keys中出现                numerator+=self.w[self.feats[(label,f)]] #若出现就相当于fi(x,y)取1,在P(y|x)公式的分子中就能加到wi        return math.exp(numerator)        def probabilityDE(self): #计算概率期望分布        ep=[0.0]*len(self.feats)   #经验分布期望是一个大小为i的列表,i的大小是样本中出现的(label,feature)的种类        for line in self.trainSet:  #对于每一个样本            features=line[1:]  #每一个样本的特征是除去第一个元素类别/标签后所有的元素            cP=self.conditionalProbability(features) #计算条件概率P(y|x)            for f in features: #对于每一个样本的为一个特征                for probability,label in cP:                    if (label,f) in self.feats: #判断(label,f)这个组合是否在feats中出现,若出现就相当于fi(x,y)取1                        index=self.feats[(label,f)]  #(label,f)这个组合出现在feats中的位置,或者说fi(x,y)不等于零的位置                        ep[index]+=probability* (1.0/self.size) #index对应于ep[index]        return ep        def  convergence(self,bestw,w):        for w1,w2 in zip(bestw,w): #zip函数接受任意多个(包括0个和1个)序列作为参数,返回一个tuple,即([bestw[0],w[0]],...,bestw[n],w[n]])            if abs(w1-w2)>=0.01: #如果所有的权重变化都小于0.01,就返回True,跳出循环,训练结束                return False        return True         def train(self,iters=1000):  #训练函数        self.initialization()  #调用初始化函数,初始化参数        self.experienceDE()    #计算经验分布期望        for j in range(iters):   #迭代            self.ep=self.probabilityDE()            self.bestw=self.w[:]   #将目前最新的w值赋值给bestw            for i,w in enumerate(self.w):                self.w[i]+=1.0/self.M * math.log(self.ep_[i]/self.ep[i])   #更新权值            if self.convergence(self.bestw,self.w): #判断是否达到误差范围内                break        def predict(self,input):        features = input.strip().split()        print(features)        result=self.conditionalProbability(features)        result.sort(reverse=True)        return resultmodel=maximumEntropy()model.loadData('E:\\python\\machine_learning\\example.txt')model.train()print(model.predict(' Rainy Sad Dry'))