简单感知器实现中文词性标注
感知器算法
感知器可以认为是一个内置权重 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
个位置,可以抽出的特征有
训练算法
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 | - | - | - | - |
事实上,这个简单感知器可能特征抽的不仔细,而且也没有平均感知器处理。所以效果还不好,还需要优化。
另外,我似乎对平均感知器有理解上的误解,我写的平均感知器似乎没有效果,改天学习一下平均感知器。