教程:从存储在 Power BI 中的文本中提取关键短语

Power BI Desktop 是免费的应用程序,可让你连接、转换和可视化你的数据。 关键短语提取是 Azure AI 语言的功能之一,它提供自然语言处理。 给定原始的非结构化文本,它可以提取最重要的短语、分析情绪和确定已知实体(例如品牌)。 可以综合使用这些工具快速了解客户谈论的内容和客户的感受。

本教程介绍以下操作:

  • 使用 Power BI Desktop 导入和转换数据
  • 在 Power BI Desktop 中创建自定义函数
  • 将 Power BI Desktop 与 Azure AI 语言的关键短语提取功能集成
  • 使用关键短语提取功能从客户反馈中获取最重要的短语
  • 从客户反馈创建词云

先决条件

加载客户数据

打开 Power BI Desktop 并加载你在先决条件中下载的逗号分隔值 (CSV) 文件即可开始。 此文件代表某个虚构小公司的支持论坛中一天的虚构活动。

注意

Power BI 可以使用各种基于 Web 的源(例如 SQL 数据库)提供的数据。 有关详细信息,请参阅 Power Query 文档

在 Power BI Desktop 主窗口中,选择“开始”功能区。 在功能区的“外部数据”组中,打开“获取数据”下拉菜单,然后选择“文本/CSV”。

The Get Data button

此时会显示“打开”对话框。 导航到“下载”文件夹,或你下载 CSV 文件的文件夹。 选择该文件的名称,然后单击“打开”按钮。 此时会显示 CSV 导入对话框。

The CSV Import dialog

CSV 导入对话框用于验证 Power BI Desktop 是否已正确检测到字符集、分隔符、标头行和列类型。 这些信息全都正确,所以选择“加载”。

若要查看加载的数据,请单击 Power BI 工作区左侧的“数据视图”按钮。 将会打开一个包含数据的表,就像在 Microsoft Excel 中一样。

The initial view of the imported data

准备数据

在将数据提供给关键短语提取功能进行处理之前,可能需要先在 Power BI Desktop 中对数据进行转换。

示例数据包含一个 subject 列和一个 comment 列。 使用 Power BI Desktop 中的“合并列”功能,你可以从这两个列(而非仅仅 comment 列)的数据中提取关键短语。

在 Power BI Desktop 中,选择“开始”功能区。 在“外部数据”组中,选择“编辑查询”。

The External Data group in Home ribbon

选择窗口左侧“查询”列表中的 FabrikamComments(如果尚未选择)。

现在请选择表中的 subjectcomment 列。 可能需要进行水平滚动才能看到这些列。 首先单击 subject 列标题,然后在按住 Ctrl 键的同时单击 comment 列标题。

Selecting fields to be merged

选择“转换”功能区。 在功能区的“文本列”组中,选择“合并列”。 此时会显示“合并列”对话框。

Merging fields using the Merge Columns dialog

在“合并列”对话框中,选择 Tab 作为分隔符,然后选择“确定”。

也可考虑使用“删除空白”筛选器筛选掉空白消息,或者使用“洁净转换”删除无法打印的字符。 如果数据包含的一个列类似于示例文件中的 spamscore 列,则可使用“数字筛选器”跳过“垃圾”评论。

了解 API

对于每个 HTTP 请求,关键短语提取最多可以处理一千个文本文档。 Power BI 偏好一次处理一个记录,因此在本教程中,对 API 的每次调用将只包含一个文档。 对于每个要处理的文档,关键短语 API 要求提供以下字段。

字段 说明
id 请求中此文档的唯一标识符。 响应也包含此字段。 这样,在处理多个文档时,就可以轻松地将提取的关键短语与所在文档相关联。 在本教程中,由于每个请求只处理一个文档,你可以将 id 值硬编码为针对每个请求均相同。
text 要处理的文本。 此字段的值来自于你在先前部分中创建的 Merged 列,其包含合并的主题行和评论文本。 关键短语 API 要求该数据不得超出 5,120 个字符。
language 表示撰写文档时所采用的自然语言的代码。 示例数据中的所有消息均为英语,因此你可以为此字段硬编码 en 值。

创建自定义函数

现在你可以创建会集成 Power BI 与关键短语提取功能的自定义函数了。 此函数将要处理的文本作为参数接收。 它将数据转换为所需的 JSON 格式或从该格式进行转换,并对关键短语 API 发出 HTTP 请求。 然后该函数会分析来自 API 的响应,并返回包含所提取关键短语的逗号分隔列表的字符串。

注意

Power BI Desktop 自定义函数是以 Power Query M 公式语言(简称“M”)编写的。 M 是基于 F# 的函数编程语言。 不过,完成本教程不需要你是程序员;所需代码已在下面提供。

在 Power BI Desktop 中,确保你仍处于“查询编辑器”窗口。 如果并非如此,请选择“主页”功能区,然后在“外部数据”组中,选择“编辑查询”。

现在,在“开始”功能区的“新建查询”组中,打开“新建源”下拉菜单并选择“空白查询”。

此时会在“查询”列表中显示新查询(初始名称为 Query1)。 双击此条目,将其命名为 KeyPhrases

现在,在“主页”功能区的“查询”组中,选择“高级编辑器”以打开高级编辑器窗口。 删除该窗口中的现有代码,将以下代码粘贴到其中。

注意

将下面的示例终结点(包含 <your-custom-subdomain>)替换为为语言资源生成的终结点。 可以通过登录到 Azure 门户,导航到你的资源并选择“密钥和终结点”来找到此终结点。

// Returns key phrases from the text in a comma-separated list
(text) => let
    apikey      = "YOUR_API_KEY_HERE",
    endpoint    = "https://<your-custom-subdomain>.cognitiveservices.azure.cn/text/analytics" & "/v3.0/keyPhrases",
    jsontext    = Text.FromBinary(Json.FromValue(Text.Start(Text.Trim(text), 5000))),
    jsonbody    = "{ documents: [ { language: ""en"", id: ""0"", text: " & jsontext & " } ] }",
    bytesbody   = Text.ToBinary(jsonbody),
    headers     = [#"Ocp-Apim-Subscription-Key" = apikey],
    bytesresp   = Web.Contents(endpoint, [Headers=headers, Content=bytesbody]),
    jsonresp    = Json.Document(bytesresp),
    keyphrases  = Text.Lower(Text.Combine(jsonresp[documents]{0}[keyPhrases], ", "))
in  keyphrases

YOUR_API_KEY_HERE 替换为你的语言资源密钥。 还可以通过登录到 Azure 门户,导航到你的语言资源并选择“密钥和终结点”页来找到此密钥。 请务必保留密钥前后的引号。 然后选择“完成”。

使用自定义函数

现在可以使用自定义函数从每个客户评论中提取关键短语并将其存储在表的新列中。

在 Power BI Desktop 的查询编辑器窗口中,切换回 FabrikamComments 查询。 选择“添加列”功能区。 在“常规”组中,选择“调用自定义函数”。

Invoke Custom Function button

将出现“调用自定义函数”对话框。 在“新列名”中,输入 keyphrases。 在“函数查询”中,选择你创建的自定义函数 KeyPhrases

对话框中将出现新字段“文本(可选)”。 此字段会询问我们希望使用哪一列来提供关键短语 API 的 text 参数的值。 (请记住,你已经硬编码了 languageid 参数的值。)从下拉菜单中选择 Merged此前通过合并主题和消息字段所创建的列)。

Invoking a custom function

最后选择“确定”。

如果一切准备就绪,Power BI 将针对表中的每一行调用自定义函数一次。 它将查询发送到关键短语 API,并为表添加一个新列来存储结果。 但在这些操作开始之前,可能需要指定身份验证和隐私设置。

身份验证和隐私

在关闭“调用自定义函数”对话框之后,可能会出现一个横幅,要求你指定如何连接到关键短语 API。

credentials banner

选择“编辑凭据”,确保选中对话框中的 Anonymous,然后选择“连接”。

注意

你选择 Anonymous 是因为关键短语提取功能使用你的访问密钥对请求进行验证,这样 Power BI 便不需要为 HTTP 请求自身提供凭据。

setting authentication to anonymous

如果在选择匿名访问后仍看到“编辑凭据”横幅,则可能是忘记将语言资源密钥粘贴到 KeyPhrases自定义函数的代码中。

接下来可能会出现一个横幅,要求你提供有关数据源隐私的信息。

privacy banner

对于对话框中的每个数据源,请选择“继续”,然后选择 Public。 再选择“保存”。

setting data source privacy

创建词云

处理完显示的横幅以后,请选择“主页”功能区中的“关闭并应用”,关闭查询编辑器

Power BI Desktop 需要时间来发出必需的 HTTP 请求。 对于表中的每一行,新的 keyphrases 列都包含关键短语 API 在文本中检测到的关键短语。

现在将使用此列生成一个词云。 首先,单击工作区左侧 Power BI Desktop 主窗口中的“报表”按钮。

注意

为何使用提取的关键短语而不是每个评论的完整文本来生成词云? 关键短语提供的是客户评论中的重要词汇,而不仅仅是最常见词汇。 另外,生成的云中的单词大小调整不会因某个词在相对少数评论中的频繁使用而扭曲。

如果尚未安装词云自定义视觉对象,请安装它。 在工作区右侧的“可视化效果”面板中,单击三点形式的省略号 ( ... ),然后选择从市场导入。 如果“云”这个词不在列表中显示的可视化效果工具中,则可以搜索“云”,并单击词云视觉对象旁边的添加按钮。 Power BI 会安装词云视觉对象并会让你知道它已成功安装。

adding a custom visual

首先,单击“可视化效果”面板中的“词云”图标。

Word Cloud icon in visualizations panel

此时会在工作区中显示新的报表。 将 keyphrases 字段从“字段”面板拖至“可视化效果”面板中的“类别”字段。 词云会显示在报表中。

现在,请切换到“可视化效果”面板的“格式”页面。 在“非索引字”类别中启用“默认非索引字”,以便从云中消除短的常用词,例如“of”。 不过,由于我们要可视化关键短语,因此它们可能不包含非索引字。

activating default stop words

在此面板中再往下稍微移动一点,禁用“旋转文本”和“标题”。

activate focus mode

选择报表中的“焦点模式”工具可以更好地查看词云。 此工具可将词云展开,使之填充整个工作区,如下所示。

A Word Cloud

使用其他功能

Azure AI 语言还提供情绪分析和语言检测功能。 语言检测尤其适用于客户反馈不完全是英语的情况。

这两个其他的 API 类似于关键短语 API。 这意味着可以使用与你在本教程中所创建的近乎相同的自定义函数,将它们与 Power BI Desktop 集成。 直接创建一个空白查询,然后将下面的相应代码粘贴到高级编辑器中,就像此前的操作那样。 (请勿忘记访问密钥!)然后,像以前那样,使用函数向表添加新列。

下面的情绪分析函数返回一个标签,指示文本中表达的情绪的正面程度。

// Returns the sentiment label of the text, for example, positive, negative or mixed.
(text) => let
    apikey = "YOUR_API_KEY_HERE",
    endpoint = "<your-custom-subdomain>.cognitiveservices.azure.cn" & "/text/analytics/v3.1/sentiment",
    jsontext = Text.FromBinary(Json.FromValue(Text.Start(Text.Trim(text), 5000))),
    jsonbody = "{ documents: [ { language: ""en"", id: ""0"", text: " & jsontext & " } ] }",
    bytesbody = Text.ToBinary(jsonbody),
    headers = [#"Ocp-Apim-Subscription-Key" = apikey],
    bytesresp = Web.Contents(endpoint, [Headers=headers, Content=bytesbody]),
    jsonresp = Json.Document(bytesresp),
    sentiment   = jsonresp[documents]{0}[sentiment] 
    in sentiment

下面是两个版本的语言检测函数。 第一个返回 ISO 语言代码(例如,表示英语的 en),而第二个则返回“友好”名称(例如 English)。 可以看到,这两个版本仅正文的最后一行有差异。

// Returns the two-letter language code (for example, 'en' for English) of the text
(text) => let
    apikey      = "YOUR_API_KEY_HERE",
    endpoint    = "https://<your-custom-subdomain>.cognitiveservices.azure.cn" & "/text/analytics/v3.1/languages",
    jsontext    = Text.FromBinary(Json.FromValue(Text.Start(Text.Trim(text), 5000))),
    jsonbody    = "{ documents: [ { id: ""0"", text: " & jsontext & " } ] }",
    bytesbody   = Text.ToBinary(jsonbody),
    headers     = [#"Ocp-Apim-Subscription-Key" = apikey],
    bytesresp   = Web.Contents(endpoint, [Headers=headers, Content=bytesbody]),
    jsonresp    = Json.Document(bytesresp),
    language    = jsonresp [documents]{0}[detectedLanguage] [name] in language 
// Returns the name (for example, 'English') of the language in which the text is written
(text) => let
    apikey      = "YOUR_API_KEY_HERE",
    endpoint    = "https://<your-custom-subdomain>.cognitiveservices.azure.cn" & "/text/analytics/v3.1/languages",
    jsontext    = Text.FromBinary(Json.FromValue(Text.Start(Text.Trim(text), 5000))),
    jsonbody    = "{ documents: [ { id: ""0"", text: " & jsontext & " } ] }",
    bytesbody   = Text.ToBinary(jsonbody),
    headers     = [#"Ocp-Apim-Subscription-Key" = apikey],
    bytesresp   = Web.Contents(endpoint, [Headers=headers, Content=bytesbody]),
    jsonresp    = Json.Document(bytesresp),
    language    =jsonresp [documents]{0}[detectedLanguage] [name] in language 

最后,下面是此前已提供的关键短语函数的变体,它返回的短语是列表对象,而不是单个字符串(包含逗号分隔的短语)。

注意

返回单个字符串简化了词云示例。 而列表则是更灵活的格式,可以与 Power BI 中返回的短语配合使用。 可以使用查询编辑器的“转换”功能区中的“结构化列”组来操作 Power BI Desktop 中的列表对象。

// Returns key phrases from the text as a list object
(text) => let
    apikey      = "YOUR_API_KEY_HERE",
    endpoint    = "https://<your-custom-subdomain>.cognitiveservices.azure.cn" & "/text/analytics/v3.1/keyPhrases",
    jsontext    = Text.FromBinary(Json.FromValue(Text.Start(Text.Trim(text), 5000))),
    jsonbody    = "{ documents: [ { language: ""en"", id: ""0"", text: " & jsontext & " } ] }",
    bytesbody   = Text.ToBinary(jsonbody),
    headers     = [#"Ocp-Apim-Subscription-Key" = apikey],
    bytesresp   = Web.Contents(endpoint, [Headers=headers, Content=bytesbody]),
    jsonresp    = Json.Document(bytesresp),
    keyphrases  = jsonresp[documents]{0}[keyPhrases]
in  keyphrases

后续步骤

详细了解 Azure AI 语言、Power Query M 公式语言或 Power BI。