自然语言
自然语言处理( Natural Language Processing, NLP)简称NLP,属于人工智能的一个分支,让计算机能够理解并处理人类语言,从中提取出有用的信息,帮助人类更高效地处理各种任务。
- 最早的自然语言处理是机器翻译
2.随着互联网的兴起,大量文本数据的出现推动了统计学习方法在自然语言的应用
3.神经网络自然语言处理直接通过深度学习建模,用神经网络进行端对端的训练。
自然语⾔处理通俗来说就是把人类的语言符号转化为机器能够进行计算的数字,因为普通的文本语言机器是看不懂的,必须通过转化来表征对应文本。在这套系统中,词是表义的基本单元,把词映射为实数域向量的技术也叫词嵌⼊(word embedding),近年来,词嵌⼊已逐渐成为⾃然语⾔处理的基础知识。
One-hot Encoding
One-hot Encoding 简称独热向量编码,也是特征工程中最常用的方法,如字典词表
"去","买","水果店","手机店", "苹果" ,"电子类","水果类" \], 词表大小是7,那么读热向量编码的维度是7
```cpp
"去" : [1,0,0,0,0,0,0]
"买" : [0,1,0,0,0,0,0]
"水果店" : [0,0,1,0,0,0,0]
"手机店" : [0,0,0,1,0,0,0]
"苹果" : [0,0,0,0,1,0,0]
"电子类" : [0,0,0,0,0,1,0]
"水果类" : [0,0,0,0,0,0,1]
```
独热编码仅仅将词转换成向量,类别对应的索引位置设为 1,其余位置设为 0。
## 词嵌⼊
"去手机店买苹果" 这里的"**苹果** "指的是 **电子类,**使用独热编码无法建立 "手机店"、"苹果"、"电子类"之间的关系 因为对应的索引位置设为 1,其余位置设为 0,如果语料增加维度也要增加。针对以上问题 1.向量维度数据取一个范围的数据(0.0 \~ 1.0),
2.维度设置成不大不小数值如256维度
3. 建立模型 如 "手机店" \* "苹果" = "电子类", "水果店" \* "苹果" = "水果类" ,用向量可以建立理解单词之间的关系。
4 单词维度数值通过训练得到。
这样的编码方式叫**词嵌⼊**
## Embedding 例子
使用LibTorch中Embedding做个**词嵌⼊**的训练例子,字典词表大小: 10个单词,单词维度: 4,
用torch::nn::Embedding建立模型,定义目标数据, 经过训练,得到 词嵌⼊向量编码,代码
```cpp
void EmbeddingMain()
{
const int64_t num_embeddings = 10; /// 字典词表大小 10个单词
const int64_t embedding_dim = 4; /// 单词维度 4
const int64_t batch_size = 2;
const int64_t seq_len = 3;
const int64_t epochs = 50;
const float lr = 0.1;
auto model = torch::nn::Embedding(torch::nn::EmbeddingOptions(num_embeddings, embedding_dim));
torch::nn::MSELoss loss_fn;
torch::optim::SGD optimizer(model->parameters(), torch::optim::SGDOptions(lr));
/// 1, 3, 5, 2, 4, 6 字典词表 索引位置
torch::Tensor input_indices = torch::tensor({{1, 3, 5},{2, 4, 6}}, torch::kLong);
torch::Tensor target_embeddings = torch::tensor({
{{0.1, 0.2, 0.3, 0.4}, {0.3, 0.4, 0.5, 0.6}, {0.5, 0.6, 0.7, 0.8}}, /// 目标 词向量
{{0.2, 0.3, 0.4, 0.5}, {0.4, 0.5, 0.6, 0.7}, {0.6, 0.7, 0.8, 0.9}} /// 目标 词向量
}, torch::kFloat);
std::cout << "=== 训练前嵌入矩阵 ===" << std::endl;
auto init_embedding = model->weight.data();
std::cout << init_embedding << std::endl;
std::cout << "\n=== 开始训练 ===" << std::endl;
model->train();
for (int64_t epoch = 0; epoch < epochs; ++epoch)
{
optimizer.zero_grad();
torch::Tensor output = model->forward(input_indices);
torch::Tensor loss = loss_fn(output, target_embeddings);
loss.backward();
optimizer.step();
if ((epoch + 1) % 5 == 0)
{
std::cout << "Epoch: " << std::setw(3) << (epoch + 1)
<< " | Loss: " << std::fixed << std::setprecision(6) << loss.item