深度神经网络语言识别

「AI秘籍」系列课程:

  • 人工智能应用数学基础
  • 人工智能Python基础
  • 人工智能基础核心知识
  • 人工智能BI核心知识
  • 人工智能CV核心知识

使用 DNN 和字符 n-gram 对一段文本的语言进行分类(附 Python 代码)

在这里插入图片描述

资料来源,flaticon:https://www.flaticon.com/premium-icon/cyborg_901032

语言识别是自然语言处理 (NLP) 问题中的一个重要步骤。它涉及尝试预测一段文本的自然语言。在采取其他操作(即翻译/情感分析)之前,了解文本的语言非常重要。例如,如果你使用谷歌翻译,你输入的框会显示“检测语言”。这是因为谷歌首先尝试识别你的句子的语言,然后才能翻译它。

在这里插入图片描述

语言识别有几种不同的方法,在本文中,我们将详细探讨其中一种方法。即使用神经网络和字符 n-gram 作为特征。最后,我们表明这种方法可以实现超过 98% 的准确率。在此过程中,我们将讨论关键代码,你可以在GitHub1找到完整的项目。首先,我们将讨论用于训练神经网络的数据集。

数据集

数据集2由 Tatoeba 提供。 完整数据集包含 328 种独特语言的 6,872,356 个句子。为了简化我们的问题,我们将考虑:

  • 6 种拉丁语言:英语、德语、西班牙语、法语、葡萄牙语和意大利语。
  • 长度在 20 到 200 个字符之间的句子。

我们可以在表 1 中看到每种语言的一个句子示例。我们的目标是创建一个可以使用提供的文本预测目标变量的模型。

在这里插入图片描述

我们在下面的代码中加载数据集并进行一些初始处理。我们首先过滤数据集以获取所需长度和语言的句子。我们从每种语言中随机选择 50,000 个句子,这样我们总共有 300,000 行。然后将这些句子分成训练集(70%)、验证集(20%)和测试集(10%)。

# read in full dataset
data = pd.read_csv(data_path + '/public_articles/sentences.csv', sep='\t', encoding='utf8', index_col=0,names=['lang','text'])# Filter by text length
data = data[data['text'].str.len().between(20, 200)]# Filter by text language
lang = ['deu', 'eng', 'fra', 'ita', 'por', 'spa']
data = data[data['lang'].isin(lang)]# Select 50000 rows for each language
data_trim_list = [data[data['lang'] == l].sample(50000, random_state=100) for l in lang]# Concatenate all the samples
data_trim = pd.concat(data_trim_list)# Create a random train, valid, test split
data_shuffle = data_trim.sample(frac=1, random_state=100)train = data_shuffle[:210000]
valid = data_shuffle[210000:270000]
test = data_shuffle[270000:300000]# Check the shapes to ensure everything is correct
print(f"Train set shape: {train.shape}")
print(f"Validation set shape: {valid.shape}")
print(f"Test set shape: {test.shape}")

特征工程

在拟合模型之前,我们必须将数据集转换为神经网络可以理解的形式。换句话说,我们需要从句子列表中提取特征来创建特征矩阵。我们使用字符 n-gram(n 个连续字符的集合)来实现这一点。这是一种类似于词袋模型的方法,只不过我们使用的是字符而不是单词。

对于我们的语言识别问题,我们将使用字符 3-grams/ trigrams (即 3 个连续字符的集合)。在图 2 中,我们看到了如何使用 trigrams 对句子进行矢量化的示例。首先,我们从句子中获取所有 trigrams 。为了减少特征空间,我们取这些 trigrams 的子集。我们使用这个子集对句子进行矢量化。第一个句子的向量是 [2,0,1,0,0],因为 trigrams “is_”在句子中出现两次,“his”出现一次。

在这里插入图片描述

创建三元特征矩阵的过程类似,但稍微复杂一些。在下一节中,我们将深入研究用于创建矩阵的代码。在此之前,有必要对如何创建特征矩阵进行总体概述。所采取的步骤如下:

  1. 使用训练集,我们从每种语言中选择了 200 个最常见的三字母组
  2. 根据这些 trigrams 创建一个唯一 trigrams 列表。这些语言共享一些共同的 trigrams ,因此我们最终得到了 661 个唯一 trigrams
  3. 通过计算每个句子中每个 trigrams 出现的次数来创建特征矩阵

我们可以在表 2 中看到此类特征矩阵的示例。顶行给出了 661 个 trigrams 中的每一个。然后,每个编号行给出了我们数据集中的一个句子。矩阵中的数字给出了该 trigrams 在句子中出现的次数。例如,“eux”在句子 2 中出现了一次。

表 2:训练特征矩阵

创建特征

在本节中,我们将介绍用于创建表 2 中的训练特征矩阵和验证/测试特征矩阵的代码。我们大量使用了SciKit Learn 提供的CountVectorizer包。此包允许我们根据一些词汇表(即单词/字符列表)对文本进行矢量化。在我们的例子中,词汇表是一组 661 个 trigrams 。

首先,我们必须创建这个词汇表。我们首先从每种语言中获取 200 个最常见的 trigrams 。这是使用下面代码中的*get_trigrams*函数完成的。此函数获取一个句子列表,并将从这些句子中返回 200 个最常见的 trigrams 的列表。

from sklearn.feature_extraction.text import CountVectorizerdef get_trigrams(corpus, n_feat=200):"""Returns a list of the N most common character trigrams from a list of sentencesparams------------corpus: list of stringsn_feat: integer"""# fit the n-gram modelvectorizer = CountVectorizer(analyzer='char', ngram_range=(3, 3), max_features=n_feat)X = vectorizer.fit_transform(corpus)# Get model feature namesfeature_names = vectorizer.get_feature_names_out()return feature_names

在下面的代码中,我们循环遍历这 6 种语言。对于每种语言,我们从训练集中获取相关句子。然后我们使用get_trigrams函数获取 200 个最常见的 trigrams 并将它们添加到集合中。最后,由于这些语言共享一些共同的 trigrams ,我们得到了一组 661 个独特的 trigrams 。我们用它们来创建一个词汇表。

# obtain trigrams from each language
features = {}
features_set = set()for l in lang:# get corpus filtered by languagecorpus = train[train.lang==l]['text']# get 200 most frequent trigramstrigrams = get_trigrams(corpus)# add to dict and setfeatures[l] = trigrams features_set.update(trigrams)# create vocabulary list using feature set
vocab = dict()
for i,f in enumerate(features_set):vocab[f]=i

然后,CountVectorisor 包使用词汇表对训练集中的每个句子进行矢量化。结果就是我们之前看到的表 2 中的特征矩阵。

# train count vectoriser using vocabulary
vectorizer = CountVectorizer(analyzer='char',ngram_range=(3, 3),vocabulary=vocab)# create feature matrix for training set
corpus = train['text']   
X = vectorizer.fit_transform(corpus)
feature_names = vectorizer.get_feature_names_out()train_feat = pd.DataFrame(data=X.toarray(),columns=feature_names)

在训练模型之前,最后一步是缩放特征矩阵。这将有助于我们的神经网络收敛到最佳参数权重。在下面的代码中,我们使用最小-最大缩放来缩放训练矩阵。

# Scale feature matrix 
train_min = train_feat.min()
train_max = train_feat.max()
train_feat = (train_feat - train_min)/(train_max-train_min)# Add target variable 
train_feat['lang'] = list(train['lang'])

我们还需要获取验证和测试数据集的特征矩阵。在下面的代码中,我们像对训练集所做的那样对 2 个集合进行矢量化和缩放。值得注意的是,我们使用了词汇表以及从训练集中获得的最小/最大值。这是为了避免任何数据泄露。

# create feature matrix for validation set
corpus = valid['text']   
X = vectorizer.fit_transform(corpus)valid_feat = pd.DataFrame(data=X.toarray(),columns=feature_names)
valid_feat = (valid_feat - train_min)/(train_max-train_min)
valid_feat['lang'] = list(valid['lang'])# create feature matrix for test set
corpus = test['text']   
X = vectorizer.fit_transform(corpus)test_feat = pd.DataFrame(data=X.toarray(),columns=feature_names)
test_feat = (test_feat - train_min)/(train_max-train_min)
test_feat['lang'] = list(test['lang'])

探索 trigrams

现在,我们已经准备好了可用于训练神经网络的数据集。在此之前,探索数据集并建立一些直觉来了解这些特征在预测语言方面的表现会很有用。图 2 给出了每种语言与其他语言共有的 trigrams 数量。例如,英语和德语有 56 个最常见的 trigrams 是共同的。

我们发现西班牙语和葡萄牙语的共同 trigrams 最多,有 128 个共同的 trigrams。这是有道理的,因为在所有语言中,这两种语言在词汇上最相似。这意味着,使用这些特征,我们的模型可能很难区分西班牙语和葡萄牙语,反之亦然。同样,葡萄牙语和德语的共同 trigrams 最少,我们可以预期我们的模型在区分这些语言方面会更好。

图 2: trigrams 特征相似度图

建模

我们使用keras包来训练 DNN。模型的输出层使用 softmax 激活函数。这意味着我们必须将目标变量列表转换为 one-hot 编码列表。这可以通过下面的编码函数来实现。 该函数接收目标变量列表,并返回单次编码向量列表。 例如,[eng,por,por, fra,…] 将变为[[0,1,0,0,0,0],[0,0,0,0,1,0],[0,0,0,0,1,0],[0,0,1,0,0,0],…]。

from sklearn.preprocessing import LabelEncoder
from keras.utils import np_utils# Fit encoder
encoder = LabelEncoder()
encoder.fit(['deu', 'eng', 'fra', 'ita', 'por', 'spa'])def encode(y):"""Returns a list of one hot encodings Params---------y: list of language labels"""y_encoded = encoder.transform(y)y_dummy = np_utils.to_categorical(y_encoded)return y_dummy

在选择最终模型结构之前,我进行了一些超参数调整。我改变了隐藏层中的节点数、epoch 数和批处理大小。最终模型选择了在验证集上实现最高准确率的超参数组合。

最终模型有 3 个隐藏层,分别有 500、500 和 250 个节点。输出层有 6 个节点,每个语言一个。隐藏层都具有 ReLU 激活函数,并且如上所述,输出层具有 softmax 激活函数。我们使用 4 个 epoch 和 100 的批处理大小来训练此模型。使用我们的训练集和独热编码目标变量列表,我们在以下代码中训练此 DDN。最终,我们实现了 99.57% 的训练准确率。

from keras.models import Sequential
from keras.layers import Dense#Get training data
x = train_feat.drop('lang',axis=1)
y = encode(train_feat['lang'])#Define model
model = Sequential()
model.add(Dense(500, input_dim=661, activation='relu'))
model.add(Dense(500, activation='relu'))
model.add(Dense(250, activation='relu'))
model.add(Dense(6, activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])#Train model
model.fit(x, y, epochs=4, batch_size=100)

模型评估

在模型训练过程中,模型可能会偏向训练集和验证集。因此,最好在未见过的测试集上确定模型准确率。测试集的最终准确率为 98.60%。这低于训练准确率 99.57%,表明发生了一些对训练集的过度拟合。

通过查看图 3 中的混淆矩阵,我们可以更好地了解模型对每种语言的表现。红色对角线表示每种语言的正确预测数。非对角线数字表示一种语言被错误预测为另一种语言的次数。例如,德语被错误预测为英语 5 次。我们发现,该模型最常将葡萄牙语混淆为西班牙语(78 次)或将西班牙语混淆为葡萄牙语(88 次)。这是我们在探索特征时看到的结果。

图 3:困惑热图

创建此混淆矩阵的代码如下所示。首先,我们使用上面训练的模型对测试集进行预测。使用这些预测语言和实际语言,我们创建一个混淆矩阵并使用 seaborn 热图对其进行可视化。

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import accuracy_score, confusion_matrix
import numpy as np# x_test 和 y_test 已经定义,并且 model 是一个已训练好的 Keras 模型
x_test = test_feat.drop('lang', axis=1)
y_test = test_feat['lang']# Use model.predict to get probabilities
predictions_prob = model.predict(x_test)
# Find the index of the highest probability for each sample
labels = np.argmax(predictions_prob, axis=1)
predictions = encoder.inverse_transform(labels)# Ensure y_test is a 1D array
if y_test.ndim > 1:y_test = np.argmax(y_test, axis=1)# Accuracy on test set
accuracy = accuracy_score(y_test, predictions)
print(f"Accuracy: {accuracy}")# Create confusion matrix
lang = ['deu', 'eng', 'fra', 'ita', 'por', 'spa']
conf_matrix = confusion_matrix(y_test, predictions)
conf_matrix_df = pd.DataFrame(conf_matrix, columns=lang, index=lang)# Plot confusion matrix heatmap
plt.figure(figsize=(10, 10), facecolor='w', edgecolor='k')
sns.set(font_scale=1.5)
sns.heatmap(conf_matrix_df, cmap='coolwarm', annot=True, fmt='.5g', cbar=False)
plt.xlabel('Predicted', fontsize=22)
plt.ylabel('Actual', fontsize=22)plt.savefig('../figures/model_eval.png', format='png', dpi=150)
plt.show()

最后,98.60% 的测试准确率仍有提升空间。在特征选择方面,我们保持简单,只为每种语言选择了 200 个最常见的 trigrams 。更复杂的方法可以帮助我们区分更相似的语言。例如,我们可以选择在西班牙语中很常见但在葡萄牙语中不太常见的 trigrams ,反之亦然。我们还可以尝试不同的模型。希望这对你的语言识别实验来说是一个良好的起点。

参考


  1. 茶桁的公开文章项目文件 https://github.com/hivandu/public_articles ↩︎

  2. Tatoeba 数据集 https://downloads.tatoeba.org/exports/ ↩︎

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/40234.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

AI绘画如何变现赚取副业收入?保姆级AI绘画SD和MJ副业实操教程建议收藏!

hi~大家好,我是向阳。 今天给大家分享一下我是如何通过AI绘画赚到一点小钱的! 副业做个人IP,某书,专注Midjourney ,深入 AI头像制作,小某书做了500头像,变现了差不多一万元,每日短…

鸿蒙开发:Universal Keystore Kit(密钥管理服务)【生成密钥(C/C++)】

生成密钥(C/C) 以生成ECC密钥为例,生成随机密钥。具体的场景介绍及支持的算法规格。 注意: 密钥别名中禁止包含个人数据等敏感信息。 开发前请熟悉鸿蒙开发指导文档:gitee.com/li-shizhen-skin/harmony-os/blob/master/README.md点击或者复…

【C语言】五子棋(c语言实现)

这里写目录标题 最终效果菜单打印函数棋盘的初始化和打印人人对战落子判空函数悔棋函数判胜负函数人人对战 人机对战一是将直接调用rand生成随机值,这就不可控二是根据棋子赢面来判断哪里落子最好 如果选择退出程序直接exit就行主函数调用逻辑源代码 最终效果 五子棋…

‘艾’公益——微笑行动「广安站」为艾祝福,让笑起舞

艾多美“微笑行动”广安站拉开帷幕 此次爱心帮助7名唇腭裂患儿 重新绽放微笑 艾多美“微笑行动”广安站拉开帷幕 此次爱心帮助7名唇腭裂患儿 重新绽放微笑 不让笑容留有缺憾 每个孩子都有微笑的权利 艾多美向唇腭裂儿童伸出援手 绽放笑容,拥抱全新的未来 2…

进程、程序、应用程序之间的关系

文章目录 进程和程序进程和应用程序总结参考资料 进程和程序 程序:程序是存放在硬盘中的可执行文件,主要包括代码指令和数据。程序本身是一个静态的文件,只有在被操作系统加载到内存中并执行时才会变成进程。 进程:进程是程序在…

卫星轨道平面简单认识

目录 一、轨道平面 1.1 轨道根数 1.2 应用考虑 二、分类 2.1 根据运行高度 2.2 根据运行轨迹偏心率 2.3 根据倾角大小 三、卫星星座中的轨道平面 四、设计轨道平面的考虑因素 一、轨道平面 1.1 轨道根数 轨道平面是定义卫星或其他天体绕行另一天体运动的平面。这个平…

第十六章 Qt的文件处理操作详解

目录 一、基本文件操作 二、二进制文件读写 三、文本文件读写 四、操作例子 1、QTextStream的流操作符 一、基本文件操作 文件操作是应用程序必不可少的部分。Qt 作为一个通用开发库,提供了跨平台的文件操作能力。在所有的 I/O 设备中,文件 I/O 是最重要的部分之…

TF-IDF和BM25原理和区别

TF-IDF TF-IDF是TF(词频,Term Frequency)和IDF(逆文档频率,Inverse Document Frequency)的乘积。我们先来看他们分别是怎么计算的: TF的计算有多种方式,常见的是 除以文章总词数是…

从CPU的视角看C++的构造函数和this指针

从汇编角度,清晰的去看构造函数和this指针到底是个什么东西呢?也许可以解决你的一点小疑问 首先写一个很简单的代码demo: class A{ public:int a;A(){;}void seta(int _a){a_a;}A* getA(){return this;} };int fun1(int px){return px; }in…

【FreeRTOS】同步互斥与通信 有缺陷的同步示例

目录 1 同步互斥与通信1.1 同步互斥与通信概述1.2 同步与互斥的概念1.3 同步的例子:有缺陷1.4 freertos.c源码3. 互斥的例子:有缺陷4. 通信的例子:有缺陷5. FreeRTOS的解决方案 1 同步互斥与通信 1.1 同步互斥与通信概述 参考《FreeRTOS入门…

搞钱四步:干活、出名、破圈、整合

搞钱这事儿,说起来有四步:干活、出名、破圈、整合。 咱们现在这个时代,谁要是能把自尊心放一边,勇敢站到舞台上展示才华,变现那是分钟的事儿。 只要你敢承认自己想要财富,并且不停地使用正确的方法论&…

python语句前面有一个$是什么意思

“$”是汇编语言中的一个预定义符号,等价于当前正汇编到的段的当前偏移值。例如:指令“jmp $3”中的“$”表示当前这条指令在代码段中的偏移量。 代表当前指令的地址,如: data segment str1 db a,b,c,d leng equ $-str 就是当前地…

JVM专题之性能优化

运行时优化 方法内联 > 方法内联,是指 **JVM在运行时将调用次数达到一定阈值的方法调用替换为方法体本身** ,从而消除调用成本,并为接下来进一步的代码性能优化提供基础,是JVM的一个重要优化手段之一。 > > **注:** > > * **C++的inline属于编译后内联,…

知名品牌因商标痛失市场:114家直营店山寨店7000多家!

奶茶知名品牌“鹿角巷”当年红遍大江南北,是最早的新茶饮品牌,但是当年商标注册存在问题,被同行奶茶品牌抢占了先机,发声明“对大陆商标注册细则不详,在商标注册过程中让假店钻了法律空档”,最夸张的时候全…

如何用Python向PPT中批量插入图片

办公自动化办公中,Python最大的优势是可以批量操作,省去了用户粘贴、复制、插入等繁琐的操作。经常做PPT的朋友都知道,把图片插入到PPT当中的固定位置是一个非常繁琐的操作,往往调整图片时耗费大量的时间和精力。如何能省时省力插…

windows启动Docker闪退Docker desktop stopped

Windows启动Docker闪退-Docker desktop stopped 电脑上很早就安装有Docker了,但是有一段时间都没有启动了,今天想启动启动不起来了,打开没几秒就闪退,记录一下解决方案。仅供参考 首先,参照其他解决方案,本…

【刷题汇总--游游的you、腐烂的苹果、孩子们的游戏(圆圈中最后剩下的数)】

C日常刷题积累 今日刷题汇总 - day0051、游游的you1.1、题目1.2、思路1.3、程序实现 - 蛮力法1.4、程序实现 - 贪心(优化) 2、腐烂的苹果2.1、题目2.2、思路2.3、程序实现 - bfs 3、孩子们的游戏(圆圈中最后剩下的数)3.1、题目3.2、思路3.3、程序实现 -- 环形链表3.4、程序实现…

2个方法教你轻松移除pdf文件编辑限制

PDF是一种常见的办公文档格式,常用于文件共享和保护。然而,有时候我们需要编辑PDF文件中的内容,但受到了编辑限制。本文将介绍一些有效的方法,帮助您解除PDF的编辑限制,轻松进行编辑和修改。 一、通过密码取消PDF“限制…

雷电模拟器报错remount of the / superblock failed: Permission denied remount failed

报错截图 解决方法 打开设置 设置配置system.vmdk可写入 解决

Transformer和Mamba强强结合!最新混合架构全面开源,推理速度狂飙8倍

最近发现,将Mamba和Transformer模块混合使用,效果会比单独使用好很多,这是因为该方法结合了Mamba的长序列处理能力和Transformer的建模能力,可以显著提升计算效率和模型性能。 典型案例如大名鼎鼎的Jamba:Jamba利用Tr…