词格原先的整句打分是一份没校准过的启发式 unigram,质量很差。这里内嵌 libime 在用的 kenlm 查询子集,改由它的三元模型 sc.lm 来打路径分。 - engine/ngram 只编 kenlm 的 query / trie-build 路径。不定义 WITH_THREADS, parallel_read.cc 因此退化成串行实现,整个子集零 Boost 依赖。 KENLM_MAX_ORDER=3 必须与建模阶数一致,改它等于读不懂已发布的模型文件。 - ngram::LanguageModel 是唯一 include kenlm 头文件的地方,对外只给出一个纯 std 的头,_HAS_AUTO_PTR_ETC 和 kenlm 的 include 目录都保持 PRIVATE。 - shared_language_model 按资源路径共享一份 mmap。kenlm 的查询是只读的且把 上下文放在调用方的 State 里,所以并发会话不需要额外加锁。 - 模型缺失时 valid() 为假,词格退回原来的启发式打分:整句候选只是变差,不会 停止工作。测试覆盖了缺模型降级与按路径共享。 - 出货的 ARPA 不带 <s>/</s>,所以解码从 null_state() 起算而非 begin_state()。 kenlm 是上游副本,不重排版、不进 clang-format,其 LGPL-2.1+ 与 BSD 例外清单 已补进 THIRD_PARTY_NOTICES.txt。googlepinyinime 那条 Fallback 整句路径不变。
159 lines
3.8 KiB
C++
159 lines
3.8 KiB
C++
#ifndef LM_VALUE_H
|
|
#define LM_VALUE_H
|
|
|
|
#include "config.hh"
|
|
#include "model_type.hh"
|
|
#include "value_build.hh"
|
|
#include "weights.hh"
|
|
#include "../util/bit_packing.hh"
|
|
|
|
#include <stdint.h>
|
|
|
|
namespace lm {
|
|
namespace ngram {
|
|
|
|
// Template proxy for probing unigrams and middle.
|
|
template <class Weights> class GenericProbingProxy {
|
|
public:
|
|
explicit GenericProbingProxy(const Weights &to) : to_(&to) {}
|
|
|
|
GenericProbingProxy() : to_(0) {}
|
|
|
|
bool Found() const { return to_ != 0; }
|
|
|
|
float Prob() const {
|
|
util::FloatEnc enc;
|
|
enc.f = to_->prob;
|
|
enc.i |= util::kSignBit;
|
|
return enc.f;
|
|
}
|
|
|
|
float Backoff() const { return to_->backoff; }
|
|
|
|
bool IndependentLeft() const {
|
|
util::FloatEnc enc;
|
|
enc.f = to_->prob;
|
|
return enc.i & util::kSignBit;
|
|
}
|
|
|
|
protected:
|
|
const Weights *to_;
|
|
};
|
|
|
|
// Basic proxy for trie unigrams.
|
|
template <class Weights> class GenericTrieUnigramProxy {
|
|
public:
|
|
explicit GenericTrieUnigramProxy(const Weights &to) : to_(&to) {}
|
|
|
|
GenericTrieUnigramProxy() : to_(0) {}
|
|
|
|
bool Found() const { return to_ != 0; }
|
|
float Prob() const { return to_->prob; }
|
|
float Backoff() const { return to_->backoff; }
|
|
float Rest() const { return Prob(); }
|
|
|
|
protected:
|
|
const Weights *to_;
|
|
};
|
|
|
|
struct BackoffValue {
|
|
typedef ProbBackoff Weights;
|
|
static const ModelType kProbingModelType = PROBING;
|
|
|
|
class ProbingProxy : public GenericProbingProxy<Weights> {
|
|
public:
|
|
explicit ProbingProxy(const Weights &to) : GenericProbingProxy<Weights>(to) {}
|
|
ProbingProxy() {}
|
|
float Rest() const { return Prob(); }
|
|
};
|
|
|
|
class TrieUnigramProxy : public GenericTrieUnigramProxy<Weights> {
|
|
public:
|
|
explicit TrieUnigramProxy(const Weights &to) : GenericTrieUnigramProxy<Weights>(to) {}
|
|
TrieUnigramProxy() {}
|
|
float Rest() const { return Prob(); }
|
|
};
|
|
|
|
struct ProbingEntry {
|
|
typedef uint64_t Key;
|
|
typedef Weights Value;
|
|
uint64_t key;
|
|
ProbBackoff value;
|
|
uint64_t GetKey() const { return key; }
|
|
};
|
|
|
|
struct TrieUnigramValue {
|
|
Weights weights;
|
|
uint64_t next;
|
|
uint64_t Next() const { return next; }
|
|
};
|
|
|
|
const static bool kDifferentRest = false;
|
|
|
|
template <class Model, class C> void Callback(const Config &, unsigned int, typename Model::Vocabulary &, C &callback) {
|
|
NoRestBuild build;
|
|
callback(build);
|
|
}
|
|
};
|
|
|
|
struct RestValue {
|
|
typedef RestWeights Weights;
|
|
static const ModelType kProbingModelType = REST_PROBING;
|
|
|
|
class ProbingProxy : public GenericProbingProxy<RestWeights> {
|
|
public:
|
|
explicit ProbingProxy(const Weights &to) : GenericProbingProxy<RestWeights>(to) {}
|
|
ProbingProxy() {}
|
|
float Rest() const { return to_->rest; }
|
|
};
|
|
|
|
class TrieUnigramProxy : public GenericTrieUnigramProxy<Weights> {
|
|
public:
|
|
explicit TrieUnigramProxy(const Weights &to) : GenericTrieUnigramProxy<Weights>(to) {}
|
|
TrieUnigramProxy() {}
|
|
float Rest() const { return to_->rest; }
|
|
};
|
|
|
|
// gcc 4.1 doesn't properly back dependent types :-(.
|
|
#pragma pack(push)
|
|
#pragma pack(4)
|
|
struct ProbingEntry {
|
|
typedef uint64_t Key;
|
|
typedef Weights Value;
|
|
Key key;
|
|
Value value;
|
|
Key GetKey() const { return key; }
|
|
};
|
|
|
|
struct TrieUnigramValue {
|
|
Weights weights;
|
|
uint64_t next;
|
|
uint64_t Next() const { return next; }
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
const static bool kDifferentRest = true;
|
|
|
|
template <class Model, class C> void Callback(const Config &config, unsigned int order, typename Model::Vocabulary &vocab, C &callback) {
|
|
switch (config.rest_function) {
|
|
case Config::REST_MAX:
|
|
{
|
|
MaxRestBuild build;
|
|
callback(build);
|
|
}
|
|
break;
|
|
case Config::REST_LOWER:
|
|
{
|
|
LowerRestBuild<Model> build(config, order, vocab);
|
|
callback(build);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
};
|
|
|
|
} // namespace ngram
|
|
} // namespace lm
|
|
|
|
#endif // LM_VALUE_H
|