不到1美元!1小时内训练自己的中文词向量
自然语言处理NLP是人工智能非常热门的一个领域,采用NLP技术构建的语言模型可以帮助业务系统提供更丰富的语言洞察和交互能力,譬如构建自己的智能客服、对于用户评价进行情感分析、舆情分析等。客户想要构建出自己的语言模型面临着诸多挑战,其中之一就是训练自己语言模型的词向量,因为词向量是构建各种业务语言模型的基础,但是面对海量的语料库,需要海量训练计算资源的时候,往往需要很大的技术、资源、时间的投入,代价很大。
Amazon SageMaker是AWS上一个托管的机器学习平台服务,能够帮助客户高效的自动标注数据、训练和部署机器学习模型。Amazon SageMaker内置了二十多种AWS优化过的机器学习高性能算法,包括常见的线性回归、神经网络、时间序列等,并且还支持MXNet、TensorFlow、PyTorch等主流深度学习框架。今天我们将介绍如何使用Amazon SageMaker服务的BlazingText在一小时内快速训练wiki中文的词向量。
Amazon SageMaker BlazingText 算法提供了 Word2vec 和文本分类算法的高度优化的实现。利用 BlazingText 算法,您可以轻松扩展到大型语言数据集。与 Word2vec 类似,它提供了 Skip-gram 和持续单词袋 (CBOW) 两种训练架构来训练词向量,称之为(WordEmbedding),并且还实现了监督学习的fastText文本分类器,您可以使用多台CPU服务器器 或 GPU 服务器在几分钟内对超过 10 亿个单词的模型进行训练。
2. 首先我们加载相应的Python库,并将我们之前创建的S3存储桶用于存放wiki中文训练数据的S3存储桶
importsagemaker fromsagemaker import get_execution_role importboto3 importjson sess = sagemaker.Session() role = get_execution_role() print(role) # This is the role that SageMaker would use to leverage AWS resources (S3, CloudWatch) on your behalf bucket = '421710401846-sagemaker-us-west-2'# Replace with your own bucket name if needed prefix = 'nlp-handson'#Replace with the prefix under which you want to store the data if needed
3. 接下来我们下载wiki中文的中文数据集,原始数据是一个 xml压缩包,经过了简单的预处理后并被转换为简体中文,总大小 1.3G,包含约447万行,4.5亿个中文字。
!wget https://421710401846-sagemaker-us-west-2.s3-us-west-2.amazonaws.com/nlp-handson/zh-train/wiki_zh_full
4. 下载后的中文数据集合需要进行清洗,主要两个清洗步骤
- 原始数据包含许多英文单词,阿拉伯数字和标点符号,删除这些噪音信息
- 使用 Jieba分词工具解析中文单词,以空格分开。因为在解析单词时,我们会遇到很多毫无意义的中文词,如 “的、有然、因为”,我们称这些单词停止词(Stopwords),也需要删除
# Install jieba tool !pip install jieba # Download stopwords !wget https://421710401846-sagemaker-us-west-2.s3-us-west-2.amazonaws.com/nlp-handson/zhstopwords.txt importlogging,jieba,os,re defget_stopwords(): basicConfig(format='%(asctime)s:%(levelname)s:%(message)s',level=logging.INFO) #加载停用词表 stopword_set = set() with open("zhstopwords.txt",'r',encoding="utf-8") as stopwords: for stopword in stopwords: add(stopword.strip("\n")) return stopword_set
5. 这里我们定义一个分词方法parse_zh_words,对原始wiki中文数据进行分词,以空格隔开,并把分词结果存到本地文件。我们使用的是8 vCPU,16G RAM的C5 notebook实例,整个清洗过程大约20分钟左右,清洗完后的wiki中文语料库大约966MB,这就是我们需要的的训练数据。
defparse_zh_words(read_file_path,save_file_path): file = open(read_file_path,"r",encoding="utf-8") #过滤掉英文和数字等特殊字符 r1 = '[^\u4e00-\u9fa5]' #写文件 output = open(save_file_path,"w+",encoding="utf-8") content_line = file.readline() #获取停用词表 stopwords = get_stopwords() #定义一个字符串变量,表示一篇文章的分词结果 article_contents = "" while content_line: content_line = content_line.strip("\n") if len(content_line) > 0: #去除数字和英文等特殊字符 zh_content_line = re.sub(r1, '', content_line) #使用jieba进行分词 words = jieba.cut(zh_content_line,cut_all=False) …… input_file = './data/wiki_zh_full' output_file = './data/wiki_zh_corpus' parse_zh_words(input_file, output_file)
7. 我们将清洗好的wiki中文语料库上传到S3的存储桶中,并定义BlazingText训练任务的S3 数据通道和模型输出位置。
train_channel = prefix + '/zh-train' upload_data(path='data/wiki_zh_corpus', bucket=bucket, key_prefix=train_channel) s3_train_data = 's3://{}/{}'.format(bucket, train_channel) s3_output_location = 's3://{}/{}/zh-output'.format(bucket, prefix)
9. 我们定义一个模型训练器(Estimator),其中BlazingText算法AWS已经封装在一个Docker容器中,容器存放在一个固定的ECR镜像仓库中,我们可以直接使用。在模型训练器中我们指定了需要什么样的机器配置,以及用于训练机器数量等参数。在这里我们选择了拥有最新的Nvida V100 GPU的P3实例。值得一提的是红色参数部分,Amazon SageMaker现在支持使用AWS Spot实例进行训练,Spot实例只有按需实例30%左右的价格,能够极大节约您的训练成本。
container = sagemaker.amazon.amazon_estimator.get_image_uri(region_name, "blazingtext", "latest") bt_model = sagemaker.estimator.Estimator(container, role, train_instance_count=1, train_instance_type='ml.p3.2xlarge', train_use_spot_instances = True, train_volume_size = 10, train_max_run = 3600, train_max_wait = 3600, input_mode= 'File', output_path=s3_output_location, sagemaker_session=sess)
10. 之后继续配置训练过程中的超参数,我们使用skipgram模式,学习因子设置为0.05、负采样率为5等,将词向量目标维度vector_dim设置成300维,然后定义训练数据通道data_channel,这个将指向我们之前创建的S3存储桶。
set_hyperparameters(mode= "skipgram", #"batch_skipgram", epochs=10, min_count=5, sampling_threshold=0.0001, learning_rate=0.05, window_size=5, vector_dim=300, negative_samples=5, batch_size=11, evaluation=False subwords=False) train_data = sagemaker.session.s3_input(s3_train_data, distribution='FullyReplicated', content_type='text/plain', s3_data_type='S3Prefix') data_channels = {'train': train_data}
11. 以上设置完成之后,只需要调用fit方法,就可以自动进行模型训练了。在这个fit方法背后,SageMaker会根据之前的配置自动下载BlazingText算法的容器,自动启动运行算法的GPU服务器,自动训练并打印出训练信息,最后自动吧训练好的wiki中文词向量模型存储到S3中,所有的一切都是自动化完成。
fit(inputs=data_channels, logs=True)
1. 首先我们把模型文件下载下来并解压缩,得到一个vectors.txt文件,大约1.5G,这个文件就是wiki中文的词向量文件,包含了大约56.7万个词向量。我们把vectors.txt的前400个中文词向量进行二维可视化,我们使用TSNE降维方式。
frommanifold importTSNE frommatplotlib import pylab frompylab import mpl tsne = TSNE(perplexity=40, n_components=2, init='pca', n_iter=10000) two_d_embeddings = tsne.fit_transform(word_vecs[:num_points]) labels = index_to_word[:num_points] rcParams['font.sans-serif'] = ['SimHei'] # 指定默认字体 rcParams['axes.unicode_minus'] = False # 解决保存图像是负号'-'显示为方块的问题 %matplotlib inline defplot(embeddings, labels): figure(figsize=(20,20)) fori, label in enumerate(labels): x, y = embeddings[i,:] scatter(x, y) annotate(label, xy=(x, y), xytext=(5, 2), textcoords='offset points',ha='right', va='bottom') #pylab.savefig('tsne-ch.png') show() plot(two_d_embeddings, labels)
3. 训练出来的vectors.txt是一个词向量文件,可以与 Gensim 和 Spacy 等其他工具存储格式兼容。因此我们使用另一个Python工具Gensim来验证。Gensim是一个用于从文档中自动提取语义主题的Python库。看看中文单词的类比性和相似性。可以看到,[女人,国王]对应了[男人,王后]的类比性比较,和牛肉不属于[天才,傻瓜,疯子]范畴相似性比较。或者也可以使用wordsim-240、wordsim-297中文数据集进行相似度评测,CA8 数据集进行类比度评测。
!pip install gensim frommodels importKeyedVectors word_vectors = KeyedVectors.load_word2vec_format('vectors.txt', binary=False) result1 = word_vectors.most_similar(positive=['女人', '国王'], negative=['男人']) print("{}: {:.4f}".format(*result1[0])) print(word_vectors.doesnt_match("天才傻瓜 疯子 牛肉".split()))
4. 我们还可以用wordcloud绘制一个中文词相似度云,把和某个中文单词相似的前100个词语都绘制在一个圆形的词云中。
!pip install wordcloud importpyplot as plt fromwordcloud import WordCloud ... #输入一个词找出相似的前100个词 one_corpus = ["美丽"] result = word_vectors.most_similar(one_corpus[0],topn=100) #将返回的结果转换为字典,便于绘制词云 word_cloud = dict() forsim inresult: word_cloud[sim[0]] = sim[1] #绘制词云 draw_word_cloud(word_cloud)
6. 最后看一下成本,我们在notebook中我们不到一个小时内基于wiki中文上亿数量级的中文文本训练出了自己56.7万个中文单词的词向量,并且验证效果还不错。现在我们以美西俄勒冈区域为例:
notebook实例C5 2xlarge $0.538/小时,计费使用一小时;
GPU训练实例 P3 2xlarge $4.284/小时,计费使用292秒;
S3 存储成本 $0.023 每GB/月,存储大约3GB;
总成本Cost = 0.538*1 + (4.284/3600)*292 + (0.023*3)/30 = 0.88778,
连1美元都不到!出乎意料的实现了我们的目标!
总结一下,利用Amazon SageMaker内置的BlazingText算法,可以帮助客户多快好省的训练自己的语言模型词向量。不需要自己写算法,不用担心算力、不用担心成本,只要准备好您的数据,SageMaker都将自动化的构建各种业务的语言模型,为系统提供简单、高效的NLP AI能力集成。