Google原生输入法LatinIME词库构建流程分析(三)--N-gram信息构建

google books ngram viewer数据集的下载与使用 最近在做有关word2vec的项目,需要使用到google books ngram viewer中的数据集。但是打开网页后发现,由于数据很大,google将数据集分成了很多个文件。我如果要下载的话,需要一个一个链接去点开下载,这样似乎很麻烦。 后来我无意中发现了一个Python的package,可以直接使用到google books ngram viewer上面的数据。 首先安装一下这个包: 阅读详情

N-gram信息的构建在ngram.cpp中进行构建:

bool NGram::build_unigram(LemmaEntry *lemma_arr, size_t lemma_num,
                          LemmaIdType next_idx_unused) {
  ...
  //1、初始化freqs数组,lemma_arr数组元素的idx_by_hz字段对应freqs的索引
  //2、计算total_freq
  for (size_t pos = 0; pos < lemma_num; pos++) {
    if (lemma_arr[pos].idx_by_hz == idx_now)
      continue;
    idx_now++;
    assert(lemma_arr[pos].idx_by_hz == idx_now);
    freqs[idx_now] = lemma_arr[pos].freq;
    if (freqs[idx_now] <= 0)
      freqs[idx_now] = 0.3;
    total_freq += freqs[idx_now];
  }
  ...

  //更新freqs数组并计算最大freq,计算方式为freq/total_freq
  for (size_t pos = 0; pos < idx_num_; pos++) {
    freqs[pos] = freqs[pos] / total_freq;
    assert(freqs[pos] > 0);
    if (freqs[pos] > max_freq)
      max_freq = freqs[pos];
  }
  // calculate the code book
  ...
  //初始化freq_codes_df_数组,元素个数为256个
  for (size_t code_pos = 0; code_pos < kCodeBookSize; code_pos++) {
    bool found = true;

    while (found) {
      found = false;
      double cand = freqs[freq_pos];
      for (size_t i = 0; i < code_pos; i++)
        if (freq_codes_df_[i] == cand) {
          found = true;
          break;
        }
      if (found)
        freq_pos++;
    }

    freq_codes_df_[code_pos] = freqs[freq_pos];
    freq_pos++;
  }

  //对freq_codes_df_进行排序,共256个元素
  myqsort(freq_codes_df_, kCodeBookSize, sizeof(double), comp_double);

  ...
  iterate_codes(freqs, idx_num_, freq_codes_df_, lma_freq_idx_);

  delete [] freqs;

 ...
  for (size_t code_pos = 0; code_pos < kCodeBookSize; code_pos++) {
    double log_score = log(freq_codes_df_[code_pos]);
    float final_score = convert_psb_to_score(freq_codes_df_[code_pos]);
    if (kPrintDebug0) {
      printf("code:%ld, probability:%.9f, log score:%.3f, final score: %.3f\n",
             code_pos, freq_codes_df_[code_pos], log_score, final_score);
    }
    freq_codes_[code_pos] = static_cast<LmaScoreType>(final_score);
  }

  initialized_ = true;
  return true;
}

目前对LatinIME中的ngram还没有一个整体的了解,因此针对ngram信息构建流程分析目前先按照代码执行次序进行分析,在分析中进一步增加了解,先来看下第一个for循环:

//1、初始化freqs数组,lemma_arr数组元素的idx_by_hz字段对应freqs的索引
  //2、计算total_freq
  for (size_t pos = 0; pos < lemma_num; pos++) {
    if (lemma_arr[pos].idx_by_hz == idx_now)
      continue;
    idx_now++;
    assert(lemma_arr[pos].idx_by_hz == idx_now);
    freqs[idx_now] = lemma_arr[pos].freq;
    if (freqs[idx_now] <= 0)
      freqs[idx_now] = 0.3;
    total_freq += freqs[idx_now];
  }

lemma_num是一个unsigned long类型变量,它的值在这里等于65101,也就是lemma_arr的长度,第八行可以看到,从lemma_arr数组中取出freq字段赋值给freqs数组,同时计算total_freq,第零个元素的freq是=0.3的(第十行),这个for循环实际上是为了初始化freqs数组,此时的freqs数组元素都还是lemma_arr数组中的freq字段,无序也未经抓换的,但是紧接着往下就是对freqs数组进行转换了:

//更新freqs数组并计算最大freq,计算方式为freq/total_freq
  for (size_t pos = 0; pos < idx_num_; pos++) {
    freqs[pos] = freqs[pos] / total_freq;
    assert(freqs[pos] > 0);
    if (freqs[pos] > max_freq)
      max_freq = freqs[pos];
  }

在这个循环中使用上一个for循环计算出来的total_freq来更新freqs数组内容,同时找出max_freq变量,经过这一步转换freqs数组内容为(前十个元素为例):

(gdb) p *freqs@10
$19 = {3.1514010662811756e-09, 2.6102481776047228e-06, 0.0014117510264284483, 4.2135427367586289e-05, 3.5443016051193335e-08, 6.6320132654683491e-05, 5.0999042085147344e-08, 0.00027250210157388183, 
  3.2141248599444556e-06, 0.00028112528687696588}

然后下一个for循环中取出freqs数组256个不重复的元素并初始化给了数组freq_codes_df_:

for (size_t code_pos = 0; code_pos < kCodeBookSize; code_pos++) {
    bool found = true;

    while (found) {
      found = false;
      double cand = freqs[freq_pos];
      for (size_t i = 0; i < code_pos; i++)
        if (freq_codes_df_[i] == cand) {
          found = true;
          break;
        }
      if (found)
        freq_pos++;
    }

    freq_codes_df_[code_pos] = freqs[freq_pos];
    freq_pos++;
  }

初始化完成后又对该数组进行了排序:

  myqsort(freq_codes_df_, kCodeBookSize, sizeof(double), comp_double);

排序完成后调用了iterator_code方法:

void iterate_codes(double freqs[], size_t num, double code_book[],
                   CODEBOOK_TYPE *code_idx) {
  size_t iter_num = 0;
  double delta_last = 0;
  do {
    size_t changed = update_code_idx(freqs, num, code_book, code_idx);

    double delta = recalculate_kernel(freqs, num, code_book, code_idx);

    if (kPrintDebug0) {
      printf("---Unigram codebook iteration: %ld : %ld, %.9f\n",
             iter_num, changed, delta);
    }
    iter_num++;

    if (iter_num > 1 &&
        (delta == 0 || fabs(delta_last - delta)/fabs(delta) < 0.000000001))
      break;
    delta_last = delta;
  } while (true);
}

这个方法主要是调用了update_code_idx和recalculate_kernel方法,先来看update_code_idx方法:

size_t update_code_idx(double freqs[], size_t num, double code_book[],
                       CODEBOOK_TYPE *code_idx) {
  //使用code_book数组中的元素索引更新code_idx指针数组
  size_t changed = 0;
  for (size_t pos = 0; pos < num; pos++) {
    CODEBOOK_TYPE idx;
    idx = qsearch_nearest(code_book, freqs[pos], 0, kCodeBookSize - 1);
    if (idx != code_idx[pos])
      changed++;
    code_idx[pos] = idx;
  }
  return changed;
}

根据函数名称就大概能了解这个函数做了什么,更新code_idx数组,这个数组类型是CODEBOOK_TYPE,定义为:

typedef unsigned char CODEBOOK_TYPE;

数组code_idx中的元素值来自一个二分查找方法qsearch_nearest(),传入的参数为code_book和freqs数组,freqs数组前面说过了是经过freq/total_freq转化过的数组,那code_book数组根据调用栈可以知道它就是前面的freq_codes_df_数组并且是经过排序的,那么他们是如何进行二分查找呢?

// Find the index of the code value which is nearest to the given freq
int qsearch_nearest(double code_book[], double freq, int start, int end) {
  //根据freq查找元素,离给定freq最近的freq对应的元素索引进行返回
  if (start == end)
    return start;
  //查找到了,但是根据distance来判断返回前一个还是后一个
  if (start + 1 == end) {
    if (distance(freq, code_book[end]) > distance(freq, code_book[start]))
      return start;
    return end;
  }

  int mid = (start + end) / 2;
  //继续二分查找
  if (code_book[mid] > freq)
    return qsearch_nearest(code_book, freq, start, mid);
  else
    return qsearch_nearest(code_book, freq, mid, end);
}

start和end分别是0和255,查找的对象是freq变量也就是freqs[pos],查找的范围是code_book数组,如果start+1 != end就一直二分查找,直到落到两个相邻元素的区间内,判断离哪个元素比较近就返回较近的哪个元素的索引,最终code_idx数组中存储的是freqs数组中freq离code_book数组中每个freq比较近的元素索引,这样code_idx数组就初始化完成了,iterator_codes中还调用了recalculate_kernel方法:

double recalculate_kernel(double freqs[], size_t num, double code_book[],
                          CODEBOOK_TYPE *code_idx) {
  double ret = 0;
  //初始化容器
  size_t *item_num =  new size_t[kCodeBookSize];
  assert(item_num);
  memset(item_num, 0, sizeof(size_t) * kCodeBookSize);

  double *cb_new = new double[kCodeBookSize];
  assert(cb_new);
  memset(cb_new, 0, sizeof(double) * kCodeBookSize);
  //
  for (size_t pos = 0; pos < num; pos++) {
    ret += distance(freqs[pos], code_book[code_idx[pos]]);

    cb_new[code_idx[pos]] += freqs[pos];
    item_num[code_idx[pos]] += 1;
  }

  for (size_t code = 0; code < kCodeBookSize; code++) {
    assert(item_num[code] > 0);
    code_book[code] = cb_new[code] / item_num[code];
  }

  delete [] item_num;
  delete [] cb_new;

  return ret;
}


整体上看,这个函数最终也是循环遍历kCodeBookSize(256)次,使用cb_new和item_num两个数组来跟新code_book数组,具体过程就不说了,最终更新后的code_book数组为(前十个元素为例):

(gdb) p *code_book@10
$1 = {5.635799479070388e-09, 1.1536144437805393e-08, 1.8915161279992252e-08, 2.345806003473422e-08, 2.6750659323917793e-08, 2.9549793110303631e-08, 3.2228569987532223e-08, 3.4500060174875951e-08, 
  3.5988886505094894e-08, 3.7613863559902464e-08}

综上,iterator_codes方法主要是更新code_book和code_idx数组的内容。最后这个for循环:

for (size_t code_pos = 0; code_pos < kCodeBookSize; code_pos++) {
    double log_score = log(freq_codes_df_[code_pos]);
    float final_score = convert_psb_to_score(freq_codes_df_[code_pos]);
    if (kPrintDebug0) {
      printf("code:%ld, probability:%.9f, log score:%.3f, final score: %.3f\n",
             code_pos, freq_codes_df_[code_pos], log_score, final_score);
    }
    freq_codes_[code_pos] = static_cast<LmaScoreType>(final_score);
  }

这个for循环遍历freq_codes_df_数组,计算每个元素的自然对数(然而并未用到),调用convert_psb_to_score方法计算final_score更新到freq_codes_数组中:

(gdb) p *freq_codes_@256
$8 = {14978, 14732, 14555, 14403, 14276, 14166, 14069, 13976, 13895, 13831, 13772, 13720, 13670, 13622, 13586, 13557, 13537, 13516, 13493, 13469, 13450, 13435, 13422, 13406, 13386, 13367, 13349, 13334, 
  13317, 13303, 13289, 13273, 13256, 13235, 13208, 13181, 13156, 13132, 13108, 13088, 13075, 13060, 13042, 13024, 13007, 12990, 12967, 12944, 12917, 12890, 12863, 12834, 12799, 12763, 12728, 12693, 
  12661, 12625, 12598, 12564, 12520, 12468, 12416, 12353, 12289, 12231, 12184, 12140, 12105, 12068, 12034, 12005, 11981, 11954, 11920, 11880, 11837, 11795, 11750, 11699, 11658, 11624, 11588, 11541, 
  11501, 11456, 11412, 11369, 11332, 11298, 11270, 11245, 11222, 11199, 11178, 11151, 11123, 11091, 11063, 11019, 10958, 10925, 10894, 10865, 10836, 10808, 10783, 10758, 10734, 10707, 10679, 10651, 
  10621, 10590, 10556, 10520, 10481, 10440, 10398, 10353, 10306, 10261, 10212, 10163, 10115, 10068, 10020, 9970, 9919, 9867, 9816, 9767, 9717, 9669, 9621, 9578, 9538, 9501, 9465, 9429, 9391, 9350, 9308, 
  9266, 9225, 9190, 9155, 9126, 9102, 9080, 9063, 9048, 9033, 9018, 8997, 8978, 8956, 8934, 8911, 8887, 8857, 8827, 8789, 8750, 8715, 8685, 8656, 8625, 8601, 8582, 8563, 8545, 8525, 8506, 8493, 8479, 
  8467, 8455, 8444, 8431, 8418, 8403, 8382, 8357, 8328, 8295, 8263, 8232, 8204, 8174, 8145, 8110, 8081, 8056, 8025, 7990, 7956, 7922, 7891, 7868, 7846, 7823, 7805, 7789, 7773, 7756, 7735, 7709, 7688, 
  7667, 7640, 7614, 7588, 7561, 7533, 7506, 7474, 7435, 7391, 7342, 7293, 7245, 7204, 7157, 7104, 7056, 6997, 6941, 6896, 6852, 6801, 6737, 6632, 6510, 6378, 6228, 6077, 5950, 5795, 5663, 5512, 5432, 
  5341, 5236, 5107, 5030, 4934, 4883, 4794, 4761, 4640, 4526, 4397, 4044, 3522, 2385}

到此ngram信息构建就完成了,最终也就是初始化了一个freq_codes_数组,此数组在预测逻辑中会使用,ngram这块单独拿出来分析没什么意义,还是要结合在预测输入的过程才能体现其价值所在,本片文章在分析latinIME输入预测等整体流程的过程中将会持续更新,欢迎批评指正!
 

N元语言模型的训练方法 <br />------------------------------------------------------------------<br />大家好,我是Bright,微软拼音的开发工程师。我之前介绍了语言模型的基本概念,本文介绍一下N-gram语言模型的训练方法。<br />------------------------------------------------------------------ <br />模型的训练也称为模型的参数估计,参数可以用下式估计:<br />      阅读详情

相关推荐

自然语言处理中的N-Gram模型详解

N-Gram(有时也称为N元模型)是自然语言处理中一个非常重要的概念,通常在NLP中,人们基于一定的语料库,可以利用N-Gram来预计或者评估一个句子是否合理。另外一方面,N-Gram的另外一个作用是用来评估两个字符串之间的差异程度。这是模糊匹配中常用的一种手段。本文将从此开始,进而向读者展示N-Gram在自然语言处理中的各种powerful的应用。

白马负金羁 15万+

Google原生输入法LatinIME词库构建流程分析--相关数据结构分析

其实输入法词库相关数据结构的定义基本上都在头文件dictdef.h文件中,进入到代码目录cpp下. 初始化字库,首先读取txt文件内容到数据结构lemma_arr和valid_hzs中,lemma_arr是一个数组类型为LemmaEntry,下面来看下LemmaEntry定义(cpp/include/dictdef.h): //rawdict_utf16_65105_freq.txt每一行是...

camel@Y blog 2236

从零构建个性化AI助手:基于Mem0与本地大模型的记忆化实践

本文详细介绍了如何利用Mem0与本地大模型构建个性化AI助手,实现记忆化应用结构的实践方法。从开发环境搭建、记忆存储机制到个性化交互实现,提供了完整的解决方案和代码示例,帮助开发者在本地环境中创建能记住用户习惯和偏好的智能助手。

weixin_29214335的博客 464

Google原生输入法LatinIME词库构建流程分析(一)

进入到cpp目录下(pwd=.../cpp/),在command目录中有个pinyinime_dictbuilder.cpp文件,源码中可以看到main函数,这里就是词库构建的入口,接下来看下main函数源码: 25 /** 26 * Build binary dictionary model. Make sure that ___BUILD_MODEL___ is defined 2...

camel@Y blog 3855

告别串口助手!手把手教你用Matlab直接读取STM32的传感器数据(附完整代码)

本文详细介绍了如何利用Matlab直接与STM32进行串口通信,实现传感器数据的实时采集与分析。通过完整的代码示例和系统架构设计,帮助开发者告别传统的串口助手工具链,打造高效、自动化的数据采集系统。文章涵盖了从硬件配置、通信协议设计到Matlab数据处理与可视化的全流程,特别适合嵌入式开发与数据分析结合的实践场景。

weixin_42629671的博客 428

汽车电子开发必看:AUTOSAR MCAL层SPI驱动配置全解析(基于EB tresos)

本文深入解析了AUTOSAR MCAL层SPI驱动的核心配置,基于EB tresos工具详细阐述了通道、外部设备、作业与序列等关键概念。重点剖析了多设备共享总线时的资源管理与实时性调优策略,特别是SpiJobPriority参数的决定性影响,并提供了常见配置陷阱的实战排查指南,旨在帮助汽车电子工程师高效完成SPI驱动配置。

weixin_29188043的博客 292

Google原生输入法LatinIME词库扩容(Windows10环境)

去年在Linux(ubuntu)环境下针对LatinIME进行词库扩容处理,针对LatinIME的词库构建进行了一些列分析,大家可以查阅历史文章。词库扩容最近试了一下是可以的,具体流程大致如下(windows10环境): 1、安装MinGw以及gcc、g++、gdb等,下载地址:e795, 安装完成配置环境变量到path(..\mingw\bin) 2、进入到..\cpp\command目录进行make windows下没有make命令的,需要到MinGw\bin目录下重命名mingw32-mak

camel@Y blog 2385

最新Mamba环境配置教程:从CUDA到causal-conv1d的完整安装流程

本文提供最新Mamba环境配置教程,涵盖从CUDA到causal-conv1d的完整安装流程。针对深度学习领域的长序列处理需求,详细指导如何正确配置CUDA工具链、安装PyTorch及关键依赖causal-conv1d,解决常见报错问题,并验证mamba-ssm集成效果。

bush的博客 416

Google原生输入法LatinIME引擎初始化流程分析(二)

引擎初始化首先是在Java层调用native的初始化方法,Java层调用如下: private void initPinyinEngine() { byte usr_dict[]; usr_dict = new byte[MAX_PATH_FILE_LENGTH]; // Here is how we open a built-in d...

camel@Y blog 2367

HWSD全球土壤数据下载、处理与提取完整指南

全球尺度的科学研究与工程项目中,土壤数据是必不可少的基础底图,而HWSD(和谐世界土壤数据库)凭借其统一的分辨率与属性标准,成为农业区划、生态模型、土地利用变化和水资源评估等领域的通用数据源。深入理解其“栅格存编号、数据库存属性”的核心原理,是高效使用这套数据的关键。通过掌握MDB数据库结构、属性字段含义以及栅格与属性表的关联方法,研究者可以将原始数据转化为可用的研究底图。无论你是需要提取特定区域的土壤属性,还是进行面积统计与点位采样,合理的处理流程都能显著提升工作效率。本文从下载注册开始,一步步梳理数据清

weixin_29056781的博客 313

GD32F303 ADC+DMA实战:用硬件过采样搞定多通道数据采集(附完整代码)

本文详细介绍了GD32F303系列MCU通过ADC+DMA结合硬件过采样技术实现多通道数据采集的实战方案。从硬件设计要点到软件配置全解析,包括时钟树配置、ADC模块初始化和DMA传输设置,提供了完整的代码示例和优化技巧,帮助工程师构建高精度、低功耗的数据采集系统。

weixin_30466039的博客 318

通过训练NLP制作一个自己的简易输入法

最近开始研究NLP,然后根据手写CV UP主的视频,写了一个N Gram的NLP模型,算是该领域里的hello world吧。然后我又添加了几行代码实现了一个。项目说明:数据集可以自创,导入txt文件即可;单词联想功能:输入前两个单词,预测(联想)第三个单词【也就是输入法中的提升功能】本人有关NLP学习记录可以参考下面的博客【会持续更新】

z240626191s的博客 2637

四足机器人如何用对抗运动先验(AMP)实现复杂地形行走?Unitree Go1实战解析

本文深入解析了四足机器人Unitree Go1如何通过对抗运动先验(AMP)算法实现复杂地形行走。AMP结合模仿学习与对抗训练,使机器人仅凭本体感知就能适应未知地形。文章详细介绍了AMP的核心架构、仿真训练工程实践以及在Unitree Go1上的部署优化方案,展示了其在极端地形下的卓越性能表现。

weixin_29050513的博客 327

Google原生输入法LatinIME词库构建流程分析(二)

在Google原生输入法LatinIME词库构建流程分析(一) 中分析LatinIME构建流程进行到了dict_trie->dict_list_->init_list这一步,然后就是构建N-gram信息了,N-gram构建过程在Google原生输入法LatinIME词库构建流程分析(三)--N-gram信息构建中进行了分析,那么接下来继续: bool DictBuilder::bu...

camel@Y blog 1161

华为MetaERP PTP采购到应付全流程解析

摘要:本文系统解析华为MetaERP中的PTP(采购到应付)全流程管理方案,涵盖从采购申请到付款执行的完整业务流程。文章详细分解了PR、PO、GR、IV、AP等关键环节的财务核算规则,并提供了预算校验、库存更新等Python代码示例。同时阐述了IT落地架构设计,包括会计引擎配置、系统集成方案及银企直连支付接口实现。该方案通过三单匹配自动化和智能会计引擎,将处理效率提升10倍(200笔/人天→2000笔/人天),实现98%的自动化率,为集团企业提供了高效的数字化财务管理样板。文中所有技术方案均需根据实际场景调

金牌架构师 1742

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

第五章语言模型:n-gram

文章目录基本概念语句s=w1w2...wms=w_1w_2...w_ms=w1​w2​...wm​的先验概率历史基元*问题解决方法如何划分等价类*题型十二:根据n-gram划分句子*n-gram的应用音字转换问题汉语分词问题*参数估计*题型十三:给定训练语料根据n-gram求取句子的概率*数据平滑基本思想*加1法*题型十四:加1法实操减值法/折扣法*Good-Turing(古德图灵)估计法Back-off方法/后退方法/Katz后退法绝对减值法线性减值法四种减值法的比较删除插值法语言模型的自适应*问题基于缓

weixin_46365033的博客 2750

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

【亲测免费】 探索 Google Books Ngram 数据集的 Python 库 econpy/google-ngrams

探索 Google Books Ngram 数据集的 Python 库 econpy/google-ngrams 本文将向您介绍一个名为 google-ngrams 的 Python 库,它可以让您轻松地探索和分析 Google Books Ngram 数据集。Google Books Ngram 数据集是一个庞大的语料库,包含了数百万本书籍中的文字信息。通过使用 google-ngrams ...

gitblog_00055的博客 2055

lwip-2.0.3

lwip是瑞典计算机科学院(SICS)的Adam Dunkels 开发的一个小型开源的TCP/IP协议栈。实现的重点是在保持TCP协议主要功能的基础上减少对RAM 的占用。

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Android* System-Level Java*/C++ Code Debugging

原文来自:http://software.intel.com/en-us/articles/android-system-level-javac-code-debugging 1 Introduction Currently, the Android* SDK allows application developers to create Android application pro

草帽的后花园 2492

google n-grams 怎么玩

玩法多多: 1.先看一下这篇知乎文章 - “一个玩得停不下来的Google神器:Ngram”,了解一下背景: https://zhuanlan.zhihu.com/p/20165483 2. 在线玩 - Google Books N-gram Viewer (请自备梯子):https://books.google.com/ngrams 3. 跟着这篇英文博文玩:https://yarlett.github.io/efficient-querying-of-google-books-ngram-da..

forindo的博客 3639

Google原生LatinIME输入法spl_buf_数据内容

"A\000\000\000\000\000\000a AI\000\000\000\000\000\\ AN\000\000\000\000\000V ANG\000\000\000\000\222 AO\000\000\000\000\000q BA\000\000\000\000\000J BAI\000\000\000\000] BAN\000\000\000\000Q BANG\000...

camel@Y blog 1034

Error Code: 1055. sql_mode=only_full_group_by

问题描述 在写Controller里发现不能返回查询结果,然后把DAO的sql查询语句放进mysql里面查一下,语句本身没有错但是出现下面的报错语句: Error Code: 1055. Expression #1 of SELECT list is not in GROUP BY clause and contains nonaggregated column ‘tt.from_id’ whic...

Netooo的博客 727

盘点76个当下全球免费、优质机器学习数据集获取资源

盘点76个当下全球免费、优质机器学习数据集获取资源

weixin_54626591的博客 2624

ngram模型中文语料实验step by step(3)-ngram模型的光滑处理

由于语料不可能覆盖掉所有的情况,比如语料中有“小明读了一本书”, 那么“小李读了一本书”没有在语料中出现按照MLE最大似然估计其概率就是0,这显然是不合常理的。所以我们需要对模型进行光滑处理,就是要分一部分概率给语料中没有出现的部分。 问题是如何分配,应该分配多少呢。(下面的课件来自nhu的NLP课程)   这种情况看上去我们分给未知部分的概率太多了24/29 更多的观察更好的数据更小的...

weixin_34309543的博客 325
上一篇: 关于中文--Unicode之间互相转换流程的说明
下一篇: 操作系统概念——CPU调度
杨鑫校
博客等级 码龄11年 24粉丝 113原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值