📄 taggingpos.cpp
字号:
//成员函数
//插值方法计算词性标记转移概率
double CCoMatrix::GetCoProb(uchar tag1, uchar tag2)
{
//参数:相邻两标记的序号
if(TagFreqs[tag1] == 0) return 0.00001;
uchar n=pTags -> GetSize();
return 0.3*TagFreqs[tag2]/(double)CorpusSize +
0.7*Matrix[tag1*n + tag2]/(double)TagFreqs[tag1];
}
double CCoMatrix::GetWordProb(double wtFreq, uchar tag)
{
//参数:该词、该标记出现次数,该标记序号
if(TagFreqs[tag1]>0)
return (double)(wFreq + 1)/TagFreqs[tag];
else return 0.00001;
}
//根据标记个数动态申请内存以存放每个标记的出现次数以及每两个标记的共现次数
void CCoMatrix::Create(CStdioFile& ar)
{
//参数:存放标记集的文本文件
if(Ready()) Clean; //清除原有标记集
CString line;
pTags = new CStringArray; //存放标记集的字符串数组
pTags->Add("&%"); //添加虚设标记
pOpenTags = new CStringArray; //存放开发类标记的字符串数组
while (pTags->GetSize() < 256 && tagFile.Reading(line)) {
int i=line.Find(';'); //分号之后是注释
if(i>=0) line=line.Left(i);else continue; //每行都要有一个分号
line.TrimLeft();
line.TrimRight();
if(line.IsEmpty()) continue;
if(line.TrimLeft(1) == "#" && pOpenTags->GetSize()<10) {
//开发标记前加“#”,不得超过10个
line = line.Mid(1);
pOpenTags->Add(line); //添加开发类标记
}
pTags->Add(line); //添加词性标记
}
tagFile.Close();
int n=pTags->GetSize();
TagFreqs = new int[n]; //建立标记频度数组
Matrix = new int[n*n]; //建立标记共现频度数组
for(int i=0;i<n;i++) {
TagFreqs[i]=0;
for(int j=0; j<n;j++) Matrix[i*n+j]=0;
}
CorpusSize = 0; Modified =TRUE;
line.Format(" 共有 %d 个词性标记",n);
if (pOpenTags->GetSize()== 0)
line+ = "\n没有定义开发类,将无法猜测新词词性";
AfxMessageBox(line);
}
void CCoMatrix::Clean()
{
if(Modified) {
CFile tf; char buf[512];
if(tf.Open((const char *)FileName, CFile::modeWrite)) {
CArchive ar(&tf, CArchive::store,512,buf);
Serialize(ar);
}
}
if(pTags) delete pTags;
if(pOpenTags) delete pOpenTags;
if(TagFreqs) delete TagFreqs;
if(Matrix) delete Matrix;
}
extern CMyDictionary * pDict; //词库指针
void CCoMatrix::AddCorpus(CStdioFile& trainFile)
{
//训练语料文件(文本)
char line[3000];
int n =pTags->GetSize();
while (trainFile.ReadString(line,3000)) { //循环处理每一行
CString s(line);
s.TrimLeft();s.TrimRight();
int lastID=0; //虚设标记
while(1 s.IsEmpty()) { //循环处理每个词
CString w,t;
w = s.SpanExcluding(" "); //取出一个词,函数参数为一空格
s = s.Mid(w.GetLength());s.TrimLeft(); //从s中去掉这个词
int i=w.Find('/'); //找词语跟标记的界限标记
if(i<0) {lastID =0;continue;} //训练语料有误
CorpusSize ++; //计算语料库规模
t = w.Mid(i+1); w = w.Left(i); //将词语跟标记切开
pDict->Insert(w,t);
int curID = GetIndexOf(t); //计算当前标记的序号
if(curID>0) {
TagFreqs[curID]++;
if(lastID>=0) Matrix[lastID*n+curID]++; //增加相邻标记的共现次数
}
lastID = curID; //将当前标记设置为前一个标记
}
}
trainFile.Close();
Modified = TRUE; // 语料库修改过
}
//序列化函数
IMPLEMENT_SERIAL(CCoMatrix, CObject, 0)
void CCoMatrix::Serialize(CArchive& ar)
{
if(ar.IsStoring() && !Modified) return; //如果未修改则无须存盘
if(! ar.ar.IsStoring()) { //如果是读入,先建立两个字符串数组以读入标记集
pTags = new CStringArray;
pOpenTags = new CStringArray;
}
pTags-> Serialize(ar); //标记集序列化
pOpenTags->Serialize(ar); //开发类标记序列化
int n = pTags->GetSize(); //标记集的规模
if(! ar.IsStoring()) { //如果是读入,申请内存以存放频度数据
TagFreqs = new int[i];
Matrix = new int n[n*n];
}
if(ar.IsStoring()) { //如果是存盘,写入以下数据
ar << CorpusSize;
for(int i=0;i<pTags->GetSize();i++){
ar << TagFreqs[i];
for(int j=0;j<pTags->GetSize();j++)
ar << Matrix[i*n+j];
}
}
else{
ar >> CorpusSize;
for(int i=0;i<pTags->GetSize();i++){
ar >> TagFreqs[i];
for(int j=0;j<pTags->GetSize();j++)
ar >> Matrix[i*n+j];
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -