[ad_1]
在之前的文章中,我们学习了如何执行由BERT支持的高级, 自动意图分类 在Python中。
我们还学习了如何自动 填充Google表格 在Python中。
如果我们可以直接在Google表格中执行意图分类,那会很酷吗?
这正是我们在这里要做的!
Google Apps脚本简介
Google表格中内置功能的局限性之一是它限制了您使用预定义的行为。
好消息是,如果您可以自己编写代码,则可以使用新行为定义自定义函数 Google Apps脚本。
Google Apps脚本基于JavaScript,并添加了有助于与表格,文档和其他Google Apps进行交互的其他功能。
我们将定义一个名为fetchPrediction的新自定义函数,该函数将在Google Sheet单元格中使用关键字,并通过BERT支持的预测模型运行它们,以获取搜索用户的意图。
这是我们的行动计划:
- 通过Apps脚本了解如何查看和更新Google表格中的值。
- 练习从API提取结果,并使用检索到的值填充工作表。
- 使用Uber的训练我们的BERT支持的预测模型 路德维希。
- 使用Ludwig增强我们可以从Apps脚本调用的API的功能。
- 了解一些新工具和概念,以帮助我们将两种服务连接在一起。
让我们开始吧!
从Google表格检索关键字数据
这是一 空的Google工作表 以及一些我们从SEMrush中提取的与条形码相关的关键字。
在第一个练习中,我们将读取并打印A列中的前10个关键字。
转到工具>脚本编辑器开始使用。
这是Google表格的内置IDE(集成开发环境)。
我们将编写一个名为logKeywords的简单JavaScript函数,该函数将读取工作表中的所有关键字并将它们记录到控制台中。
请参考官方文档 这里。
函数logKeywords(){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange()。getValues();
for(var i = 0; i
我们首先获得对活动工作表的引用,在本例中为Sheet1。
如果您将此代码与 我们用Python写的,您将看到一些优点。
- 我们不需要进行身份验证。
- 我们不需要打开电子表格。
转到查看> Stackdriver日志记录。在那里,您将获得指向Apps脚本仪表板的链接。单击该按钮以查看控制台日志。
最好将此页面保留在另一个选项卡中,因为您经常将其称为代码,并希望查看所做的更改是否有效。
您将在列表顶部看到最新的日志条目。单击它,您将看到上面的屏幕截图。
现在,我们打印了100多行,这花了一些时间。在编写和测试代码时,最好使用较小的列表。
我们可以在循环中进行简单的更改以解决此问题。
函数logKeywords(){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getDataRange()。getValues();
// for(var i = 0; i
我更喜欢注释掉代码更改,而不是删除它们,因为当我准备发布供生产使用时,它会更容易恢复。
当您运行此命令时,它不仅运行速度更快,而且检查日志的速度也快得多。
添加带有关键字ID的列
接下来,让我们学习将数据添加到表格中。
我们将编写一个名为addIDtoKeywords的新函数。它创建一个带有每个关键字一个数字ID的列。
这样做没有太大的价值,但是它应该可以帮助您以超简单的方式测试这项技术。
这是执行此操作的代码。
函数addIDtoKeywords(){
var sheet = SpreadsheetApp.getActiveSheet();
var data = sheet.getRange(“ B1”);
//建立值清单
var值= [];
//关键字数
长度= 100;
对于(var i = 1; i <= length + 1; i ++){
values.push([i]);
}
console.log(values.length);
//使用计算值更新工作表列
var column = sheet.getRange(“ B2:B102”);
column.setValues(values);
}
在下拉菜单中选择此功能,然后单击播放按钮以运行。
您应该在工作表中获得一个新列,其编号按升序排列。
我们还可以使用以下代码以粗体显示名为Keyword ID的列标题。
data.setValue(“关键字ID”);
data.setFontWeight(“ bold”);
这就是更新后的输出。
这是一个非常相似的代码。让我们回顾一下更改。
我添加了一个名为value的JavaScript数组来保存关键字ID。
在循环期间,我添加了一行以将循环内生成的每个ID添加到数组。
values.push([i]);
我在循环末尾打印了值数组的长度,以确保生成了正确数量的ID。
最后,我需要将值保存到工作表中。
var column = sheet.getRange(“ B2:B102”);
此代码选择要填充的正确单元格,然后我可以使用生成的列表简单地设置它们的值。
column.setValues(values);
没有比这更简单的了!
从Apps脚本中获取API结果
在下一个练习中,我们将学习如何从Apps脚本执行API请求。
我建议你跟随 这个代码实验室 从Google那里来熟悉一些更高级的概念。
我们将改编来自 步骤11 它从Books API中提取数据。
除了获取图书,我们还将使用 Google翻译API。
现在,我们开始编写更有用的代码!
这是一个新的名为fetchTranslation的函数,它基于从步骤11改编的代码。
函数fetchTranslation(TEXT){
API_KEY =“输入您的API密钥”;
TEXT = encodeURI(TEXT); //“我的名字叫史蒂夫”->“我的%20name%20is%20Steve”;
var url =`https://translation.googleapis.com/language/translate/v2?target=es&key=$ {API_KEY}&q = $ {TEXT}`;
//console.log(url);
var response = UrlFetchApp.fetch(url,{‘muteHttpExceptions’:true});
var json = response.getContentText();
//console.log(json);
翻译= JSON.parse(json);
返回翻译[“data”][“translations”][0][“translatedText”];
}
此函数接受输入文本,对其进行编码,然后将其插入API URL中以调用Google翻译服务。
我们需要获取一个API密钥,并且还需要启用翻译服务。我还建议将API限制为在开发过程中用于测试的IP。
一旦有了要调用的API URL,就和调用此代码一样简单。
var response = UrlFetchApp.fetch(url,{‘muteHttpExceptions’:true});
接下来的几行使我们获得JSON格式的响应,并在JSON树下进行了一些导航之后,我们获得了翻译后的文本。
正如您在我的代码中看到的那样,我喜欢将代码中的几乎每个步骤都记录到控制台中,以确认它正在按我的预期进行。
这是一个示例,说明了如何找出正确的JSON路径序列。
//console.log(翻译[“data”]);
//console.log(翻译[“data”][“translations”]);
//console.log(翻译[“data”][“translations”][0]);
//console.log(翻译[“data”][“translations”][0][“translatedText”]);
您可以在此处的日志中查看进度,包括最终输出。
翻译关键词
在测试该函数并使其起作用时,我们可以继续创建另一个函数以从工作表中获取并翻译关键字。
我们将以到目前为止的经验为基础。
我们将这个函数称为超级原始名称TranslateKeywords!
函数TranslateKeywords(){
var sheet = SpreadsheetApp.getActiveSheet();
var header = sheet.getRange(“ B1”);
//添加一个名为Translation的新标题列
header.setValue(“ Translation”);
header.setFontWeight(“ bold”);
// var关键字=“条形码生成器”;
var关键字= sheet.getRange(“ A2”)。getValue();
console.log(关键字);
translation_keyword = fetchTranslation(keyword);
console.log(translated_keyword);
var data = sheet.getRange(“ B2”);
data.setValue(translated_keyword);
}
此功能中的代码与我们用来设置关键字ID的代码非常相似。
主要区别在于我们将关键字传递给新的fetchTranslation函数,并使用结果更新单个单元格。
这是示例关键字的外观。
您可能会看到,没有for循环,因此这只会更新单个行/关键字。第一个。
请完成for循环以完成所有关键字的翻译,作为一项家庭作业。
建立意图分类模型
让我们开始构建意图分类服务,我们将调用该服务来填充关键字意图。
在之前的深度学习文章中,我介绍了 Uber的AI工具箱Ludwig。
我非常喜欢它,因为它使您无需编写任何代码即可构建最新的深度学习模型。
在Google Colab中运行也非常方便。
我们将遵循与我在其中描述的相同步骤 本文, 这将为我们提供由BERT支持的强大的意图预测模型。
这是您需要粘贴到的步骤的快速摘要 Google Colab (确保选择GPU运行时!)。
请参阅 我的文章 对于上下文:
%tensorflow_version 1.x
将tensorflow导入为tf;打印(tf .__ version__)
!pip安装路德维希
#upload Question_Classification_Dataset.csv和“问题Report_Page 1_Table.csv”
从google.colab导入文件
files.upload()
将熊猫作为pd导入
df = pd.read_csv(“ Question_Classification_Dataset.csv”,index_col = 0)
!wget https://storage.googleapis.com/bert_models/2018_10_18/uncased_L-12_H-768_A-12.zip
!unzip uncased_L-12_H-768_A-12.zip
#创建用于BERT支持的分类的路德维希配置文件
template =“”“
input_features:
—
名称:问题
类型:文字
编码器:伯特
config_path:uncased_L-12_H-768_A-12 / bert_config.json
checkpoint_path:uncased_L-12_H-768_A-12 / bert_model.ckpt
预处理:
word_tokenizer:伯特
word_vocab_file:uncased_L-12_H-768_A-12 / vocab.txt
padding_symbol:“[PAD]’
unknown_symbol:“[UNK]’
output_features:
—
名称:Category0
类型:类别
—
名称:Category2
类型:类别
文本:
word_sequence_length_limit:128
训练:
batch_size:32
学习率:0.00002
“”
使用open(“ model_definition.yaml”,“ w”)为f:
f.write(模板)
!pip安装bert-tensorflow
!路德维希实验
–data_csv Question_Classification_Dataset.csv
–model_definition_file model_definition.yaml
在Google Colab中完成这些步骤之后,我们应该获得用于搜索意图的高精度预测模型。
我们可以使用此代码验证预测。
test_df = pd.read_csv(“问题Report_Page 1_Table.csv”)
#我们将查询重命名为问题以匹配模型的期望
预测= model.predict(test_df.rename(columns = {‘Query’:’Questions’}))
test_df.join(预测)[[“Query”, “Category2_predictions”]]
我们得到一个像这样的数据帧。
预测的意图不是您通常期望的意图:导航,事务性,信息性,但它们足以说明该概念。
请检查一篇很棒的文章 克里斯汀·廷斯基 解释了如何扩展这个概念 获得真正的搜索意图。
将模型转化为API服务
路德维希(Ludwig)具有一项超酷的功能,可让您直接将模型作为API服务提供。
该命令是 路德维希发球。
我试图沿着一条超级复杂的道路完成同样的事情,因为我没有检查类似的东西是否已经存在。 ?
默认情况下未安装它,我们需要使用此命令进行安装。
!pip安装路德维希[serve]
我们可以使用以下命令检查命令行选项:
!ludwig服务-帮助
从我们的模型创建API就像运行此命令一样简单。
!ludwig serve -m结果/实验_运行/模型
INFO:开始的服务器进程 [5604]
INFO:等待应用程序启动。
INFO:应用程序启动完成。
信息:在http://0.0.0.0:8000上运行的Uvicorn(按CTRL + C退出)
INFO:关闭
INFO:服务器进程完成 [5604]
当我们在笔记本中运行此代码时,我们需要使用一些技巧将此过程推向后台(一个单独的线程)。
%% bash –bg
nohup ludwig服务-m结果/实验运行/模型> debug.log 2>&1
神奇的命令%% bash –bg在单独的线程中运行shellcode,将控制权返回给笔记本,因此我们可以运行可以与服务交互的代码。
我发现这是一个非常酷且有价值的技巧。我还将介绍很多年前学到的shell技巧。
的 nohup命令 防止该进程在父母死亡时被杀死。这是可选的。
代码2>&1重定向 标准误差 到标准输入,然后两者都发送到文件debug.log。您可以在此处了解有关此技术的更多信息。
我们可以使用此命令跟踪后台进程的进度。
!tail debug.log
看到此消息后,您可以继续执行下一步。
信息:在http://0.0.0.0:8000上运行的Uvicorn(按CTRL + C退出)
让我们使用curl发送一个测试API请求,以查看该服务是否有效。
!curl http://0.0.0.0:8000/predict -X POST -F’问题=谁是老板?’
您应该返回此响应。
{ “Category0_predictions”: “人”, “Category0_probabilities _”:0.00021219381596893072, “Category0_probabilities_ENTITY”:7.17515722499229e-05, “Category0_probabilities_HUMAN”:0.9988889098167419 “Category0_probabilities_DESCRIPTION”:0.000423480843892321, “Category0_probabilities_NUMERIC”:2.7793401386588812e-05, “Category0_probabilities_LOCATION”:0.0003020864969585091 “Category0_probabilities_ABBREVIATION”:7.374086999334395e-05, “Category0_probability”:0.9988889098167419, “Category2_predictions”: “IND”, “Category2_probabilities _”:8.839580550557002e-05, “Category2_probabilities_ind”:0.9759176969528198, “Category2_probabilities_other”:0.0013697665417566895, “Category2_probabilities_def”:3.929347076336853 E-05, “Category2_probabilities_count”:4.732362140202895e-05, “Category2_probabilities_desc”:0.014149238355457783, “Category2_probabilities_manner”:7.225596345961094e-05, “Category2_probabilities_date”:7.537546480307356e-05, “Category2_probabilities_cremat”:0.00012272763706278056,“Category2_probabilities_reason “:0.00042629052768461406,” Category2_probabilities_gr “:0.0025540771894156933,” Category2_probabilities_country “:0.0002626778441481292,” Category2_probabilities_city “:0.0004305317997932434,” Category2_probabilities_animal “:0.00024954770924523473,” Category2_probabilities_food “:8.139225974446163e-05,” Category2_probabilities_dismed “:7.852958515286446e-05,” Category2_probabilities_termeq“: 0.00023714809503871948, “Category2_probabilities_period”:4.197505040792748e-05, “Category2_probabilities_money”:3.626687248470262e-05, “Category2_probabilities_exp”:5.991378566250205e-05, “Category2_probabilities_state”:0.00010361814202042297, “Category2_probabilities_sport”:8.741072088014334e-05, “Category2_probabilities_event”:0.00013374585250858217, “ Category2_probabilities_product”:5.6306344049517065e-05,“ Category2_probabilities_substance”:0.00016623239207547158,“ Category2_probabilities_color”:1.9601659005274996e-05,“ Category2_probabilities_techmeth”:4.74867774755694ry-2“ 3491e-05, “Category2_probabilities_perc”:3.87108520953916e-05, “Category2_probabilities_veh”:0.00011915313370991498, “Category2_probabilities_word”:0.00016430433606728911, “Category2_probabilities_title”:0.0010781479068100452, “Category2_probabilities_mount”:0.00024070330255199224, “Category2_probabilities_body”:0.0001515906333224848, “Category2_probabilities_abb”:8.521509153069928e- 05, “Category2_probabilities_lang”:0.00022924368386156857, “Category2_probabilities_plant”:4.893113509751856e-05, “Category2_probabilities_volsize”:0.0001462997024646029, “Category2_probabilities_symbol”:9.98345494735986e-05, “Category2_probabilities_weight”:8.899033855414018e-05, “Category2_probabilities_instru”:2.636547105794307e-05, “ Category2_probabilities_letter”:3.7610192521242425e-05,“ Category2_probabilities_speed”:4.142118996242061e-05,“ Category2_probabilities_code”:5.926147059653886e-05,“ Category2_probabilities_temp”:3.687662319862284e-05,“ Category6.7”“ 2ate s_religion”:0.00012743560364469886,“ Category2_probabilities_currency”:5.8569487009663135ee-05,“ Category2_probability”:0.9759176969528198}
使用Ngrok公开我们的服务
因此,我们有一个可以进行意图预测的新API,但是一个大问题是只能从我们的Colab笔记本中访问它。
让我介绍我经常使用的另一项很酷的服务, 恩格罗克。
Ngrok可帮助您创建可公开访问的URL,这些URL连接到本地服务(例如我们刚刚创建的服务)。
我不建议将其用于生产,但是在开发和测试过程中非常方便。
您不需要创建帐户,但我个人这样做是因为我可以设置一个经常使用的自定义子域。
以下是为我们的API提供公共URL以便从App Script调用的步骤。
!wget https://bin.equinox.io/c/4VmDzA7iaHb/ngrok-stable-linux-amd64.zip &&解压缩ngrok-stable-linux-amd64.zip
我们首先下载并解压缩ngrok。
%% bash –bg
./ngrok http -hostname = api.yourdomain.com 8000 2> ngrok.log
上面的代码告诉ngrok在端口8000上连接到本地服务。这就是我们需要做的。
!curl http://api.yourdomain.com/predict -X POST -F’问题=老板是谁?’
您可以通过重复curl调用,但调用公共URL来确认它是否有效。您应该得到相同的结果。
如果您不想设置自定义域,则可以改用此代码。
%% bash –bg
./ngrok http 8000 2> ngrok.log
这将生成一个随机的公共URL,您可以使用此代码进行检索。
!curl -s http:// localhost:4040 / api / tunnels | python3 -c
“ import sys,json; print(json.load(sys.stdin)[‘tunnels’][0][‘public_url’])”
现在,我们回到最后的步骤。
获取意图预测
我们将调整用于发出Google Translate API请求的代码,以便发出意图预测请求。
两种API服务之间的一大区别是,我们需要发出HTTP POST请求,而不是简单的HTTP GET请求。
让我们看看这如何改变我们的代码, 在此过程中进一步了解HTTP。
函数fetchPrediction(question =“谁是老板?”){
TEXT = encodeURI(TEXT);
console.log(TEXT);
var url =“ http://api.yourdomain.com/predict”;
var options = {
“ method”:“ POST”,
“ contentType”:“ application / x-www-form-urlencoded”,
“有效载荷”:TEXT,
‘muteHttpExceptions’:是
};
var response = UrlFetchApp.fetch(url,options);
var json = response.getContentText();
//console.log(json);
预测= JSON.parse(json);
//console.log(预测);
console.log(预测[“Category0_predictions”]);
回报预测[“Category0_predictions”];
}
函数fetchPrediction调用我们创建的API服务,并返回预测的意图。基本上,它重现了与我们进行Colab的curl调用等效的操作,但使用的是Apps Script。
我强调了代码中的一些关键更改。让我们回顾一下。
GET和POST请求之间的主要区别在于,在GET请求中,数据作为参数在URL中传递。
在POST请求中,数据在请求主体内传递。
我们需要先对数据进行格式化,然后再将其传递到正文中,并且需要设置正确的内容类型,以便服务器知道如何对其进行解码。
该行编码了我们正在传递的问题。
TEXT = encodeURI(TEXT);
这是编码后的TEXT外观的一个示例。
Questions = label%20generator
此编码的正确内容类型是application / x-www-form-urlencoded。建议对HTML表单数据进行编码。
我们创建一个options数据结构,在其中指定这些设置和正确的请求类型,然后开始运行。
从下拉菜单中选择函数fetchPrediction,然后单击运行按钮。
您应该在日志中看到编码的输入和预测的意图。
我们如何获得工作表中所有关键字的意图?
您可能以为我们将创建另一个函数,该函数将循环读取关键字并填充意图。一点也不!
我们可以直接从工作表中直接按名称调用此函数!多么酷啊?
了解更多的资源
将简单的App Script函数与功能强大的API后端结合在一起,您可以使用任何语言进行编码,这为无限的生产力黑客打开了大门。
这是我在整理这些内容时阅读的一些资源。
最后,让我强调一个非常重要和有价值的项目, JR橡树 开始。
它是一个 很棒的仓库 用于来自SEO社区的编码人员的Python和JavaScript项目。我计划抽出时间上传我的代码段,请确保 贡献你的。
由于某种原因,这个非问题会在我的Twitter feed中不断弹出。我将在这里留下此推文,以提醒您。 ✌️
只是一个善意的提醒。 #SEO 该代码绝非非编码器“更好”。最聪明 #SEO 我知道??与编码人员进行了出色的合作。有效的沟通是非常宝贵的,并且很难获得技能。我们应该欢迎社区中的各种技能。 ?? https://t.co/wvYqxc2sNI
-哈姆雷特(@hamletbatista) 2020年3月10日
图片积分
由作者拍摄的所有屏幕截图,2020年3月