简单感知器实现中文词性标注

简单感知器实现中文词性标注


感知器算法

感知器可以认为是一个内置权重 weight 的分类器,对于输入特征 features ,输—出 h(features)=weightT ˙feature

感知器对输入是否属于这个类别估计的输出 predict(features)=h(features)

那么感知器一般用于二分类,对于中文词性划分这个多分类问题,可以准备多个感知器组成一层神经网络:
tag=arg maxtag{htag(features)} 为神经网络判断的类别输出。

神经网络整体输出为 predictTag(features)=arg maxtagpredicttag(features)

然后对于一个训练样本 [features, tag] ,如果对于神经网络 predictTag(features) 正确,则不做处理,否则对于神经网络中的正确和错误标签的感知器 weight 做出相应调整。迭代一定轮此后认为训练结束。


抽特征

对于句子中的第 i 个位置,可以抽出的特征有 word[i]word[i1]word[i+1]tag[i1] (如果对应的位置越界了,则用BEGIN, END等符号代替特征)等等,或者再增加窗口长度,增加额外的特征。


训练算法

1.构造初始网络

根据读入的训练数据,构造初始神经网络,可以简单地把权重设置为特征出现的次数。

2.迭代训练

我的迭代训练算法完整实现如下。


def trainNet():
    for turn in range(ITER_ROUNDS):
        correct = 0
        total = 0
        for i in range(record.size):
            tagPredict = predictTag(record.features[i])
            tagTruth = record.tag[i]
            total += 1
            if tagPredict != tagTruth:
                net[tagPredict].upgrade(record.features[i], -1 * LEARNING_RATE)
                net[tagTruth].upgrade(record.features[i], 1 * LEARNING_RATE)
            else:
                correct += 1
        print('iter_round = %3d, Accuracy in train set = %.5f' % (turn + 1, correct / total))

而upgrade()算法为感知器的调整算法,实现如下

    def upgrade(self, features, value):
        for feature in features:
            if feature in self.weight:
                self.weight[feature] += value

3.预测词性

预测词性可以把以 tag=arg maxtag{htag(features)} 为神经网络判断的类别输出。


训练结果

训练集上多个迭代轮次的神经网络正确率和测试集上的正确率如下:

(训练集,测试集)\迭代轮次 1 5 10 15 20 50 正确率
(100,10) 0.58918 0.89692 0.96327 0.98564 0.99274 - 0.72261
(1000,20) 0.57000 0.84265 0.91559 0.94379 0.96139 0.98792 0.82908
(10000,50) 0.57042 0.82151 0.88852 - - - -

事实上,这个简单感知器可能特征抽的不仔细,而且也没有平均感知器处理。所以效果还不好,还需要优化。

另外,我似乎对平均感知器有理解上的误解,我写的平均感知器似乎没有效果,改天学习一下平均感知器。

你可能感兴趣的:(Machine,Learing)