分析生命周期管理
行业笔记
从问题形成到解决方案日落的 7 个阶段
现在,将机器智能添加到我们的业务工作流中已经成为常态,越来越多的数据驱动预测分析正在开发并集成到现有的业务运营中,以帮助决策、提高效率、降低风险和增强员工体验。
然而,随着分析和人工智能模型的激增,我们面临着有效管理分析生命周期的挑战,以确保这些模型产生可靠的业务洞察力,从而做出最佳决策,确定机会和合理的行动。这是一项多方面的复杂任务。
下面是我对管理分析的整个生命周期的看法,它提供了一步一步的指导,通过制定业务问题,开发和部署分析,并最终淘汰分析的过程。请注意,虽然该过程是以顺序方式呈现的,但它本质上是一个迭代过程,可用于产生可重复且可靠的预测结果。
A .问题提法
任何分析或人工智能解决方案都始于业务问题或业务用例。只有清楚地了解了业务需求,才能设计和开发具有预期业务成果的分析解决方案。在这一阶段,还需要确保业务发起人承诺在提议的用例中使用开发的分析,以满足最初的设计目标。一个项目经常会陷入一个陷阱,那就是它的分析输出没有被任何潜在用户采用,从而浪费了所有的努力。因此,在项目的早期阶段,让业务发起人参与进来并与他们共同创造解决方案是非常重要的。
阐明问题的另外两个方面包括项目范围和成功度量的定义。这是询问关键问题的时候,例如:这个项目的范围是什么?它是包括所有员工,还是仅包括特定的业务部门、地区、国家和部门?我们如何定义成功?衡量成功的标准是什么?现在是什么状态,未来又会是什么状态?目标用户在未来状态下会是怎样的体验?澄清这些问题对于解决方案设计阶段至关重要。
B .方案设计
一旦问题得到很好的表述,下一步就是设计解决方案,包括
- 了解该领域的当前形势或现有工作,尤其是公司内部的工作,以避免任何重复工作,并有可能建立在现有解决方案的基础上。如果在外部市场发现类似的解决方案,那么“购买还是建造”的问题可能需要与业务利益相关者讨论。此步骤还应包括可行性研究以及工作规模(如果业务发起人要求的话)
- 确定解决方案所需的数据,并探索其可用性。这一步可能需要与数据工程师、数据科学家、赞助用户和业务利益相关者进行头脑风暴。在这里,让具有业务领域知识的人参与讨论是非常宝贵的。另一方面,数据收集往往是最耗时的步骤,尤其是当数据来自许多不同的来源,混合了数据库表、电子表格、平面文件和其他异构格式时。当大部分数据可以从一个集中的数据仓库中自动提取出来时,开发周期可以大大缩短
- 清理、整合和探索数据。在这一步,团队将使用各种工具来搜索关系、趋势和模式,以更深入地了解数据,并确定有助于从分析角度解决业务问题的显著特征。在检查数据时,团队可能会发现需要添加、删除或组合特征来创建更精确的模型
- 理解应用附加业务规则的需要。如果确实有这样的需要,那么在设计阶段就应该考虑到它们
C .解决方案开发
在此阶段,将对数据应用大量分析和机器学习建模算法,以找到数据中关系的最佳表示,这将有助于回答业务问题或解决第一阶段中确定的业务需求。将相应地进行广泛的模型构建、测试、验证和校准。此开发阶段的另一个关键领域是数据质量保证,它根据业务和分析要求,确保不同开发阶段的数据质量。
对于任何基于机器学习的解决方案来说,人工智能信任已经成为一个越来越重要的方面。在一天结束时,如果最终用户不信任人工智能解决方案产生的见解、预测或建议,他们就会忽略这些数据。因此,如何增加数据透明度,展示人工智能输出的公平性和健壮性,以及使人工智能决策可以解释,对于推动解决方案的采用变得非常关键。IBM Research 开发了一些工具来培养 AI 信任,包括 AI Factsheet 360(https://aifs360.mybluemix.net/)、AI Fairness 360(【http://aif360.mybluemix.net】T2)和 AI explability 360(http://aix360-dev.mybluemix.net)。在那里可以找到很多有用的信息。
这个阶段的最后一步是在业务环境中解释见解,与业务涉众分享和验证它们。从 AI 信任评估中收集的信息将在此类审查中非常有用。
D .解决方案部署
在这个阶段,我们采用开发的解决方案和衍生的见解,并使用可重复的自动化流程将它们付诸实施。针对目标用户群的活动和支持会议是提高解决方案认知度的好方法,最终推动解决方案的采用。另一方面,将解决方案集成到现有的运营流程中是另一个很好的、事实上也是更好的方法,可以推动其使用并实现业务成果。有时,一定程度的变更管理对于将分析结果纳入之前的流程是必要的,来自业务发起人和利益相关者的有力支持和认可将使该流程变得更容易和更快。
请注意,在开发之后可能需要一个解决方案试验阶段,以便在扩大规模之前在相对较小的范围内验证解决方案。一旦团队确认试点结果确实符合预定义的成功标准,并获得业务利益相关方的批准,就可以进入解决方案部署阶段。
解决方案部署并投入使用后,需要监控其性能、跟踪使用情况并收集反馈,以便支持未来任何潜在的解决方案调整和增强。另一方面,如果确实发现了严重的缺陷或严重的性能问题,那么团队可能需要回到解决方案开发阶段。
E .成功测量
一旦解决方案成功部署并持续跟踪其使用情况,就到了衡量成功的时候了。在问题形成阶段定义的成功标准将在这一阶段进行测量和报告。其他指标可能包括成本节约或收入产生方面的 ROI,以及基于反馈的 NPS。
F .解决方案维护&增强
一旦溶液处于稳定状态,就可以转换到 BAU 模式。这也是尽可能简化/自动化流程,以最少的维护或人工干预提高效率的时候了。在此阶段,还会定期刷新模型。
此外,通过基于标准化度量标准的模型性能的持续监控和测量,团队应该持续评估解决方案的有效性,以检查它是否仍然满足当前的业务需求。如果发现了差距,那么模型需要改进和重新校准。如果业务需求随着时间的推移发生了变化,现有数据源不再有效,或者有了新的数据,这可能会将周期带回到解决方案开发,甚至是解决方案设计。这最终使得生命周期管理成为一个迭代的过程。
G .解日落
如果最初的业务需求不再有效,新的解决方案已经开发出来并具有增强的功能,或者客户已经离开,那么现有的解决方案将不再需要,是时候淘汰该模型了。
回顾完端到端分析生命周期后,我想指出一些可能会使整个过程复杂化、变慢甚至脱轨的事情。
- 所需的数据源可能分散在整个组织中,需要非常手动的收集和整合,或者由于其隐私和敏感性而具有非常严格的访问权限,甚至是机密的,因此无法共享
- 人工智能信任在数据洞察中的建立滞后,目标用户对洞察的有效性和道德性有所担忧
- 企业可能很难利用目标业务用例中的洞察力,或者目标用户不重视这样的洞察力,并选择在任何决策中忽略它们
- 将分析集成到现有工作流中可能需要大量涉及不同用户角色的变更管理
为了避免或减轻上述一些陷阱,以下是一些建议:
- 构建一个非常清晰的用例,并估算投资回报率
- 获得业务发起人和利益相关者的大力支持
- 通过设计思考会议与赞助用户共同创建解决方案,并在整个分析生命周期中让他们参与进来
- 以敏捷的方式开发解决方案
祝您好运,并享受分析生命周期的管理!
使用 Python 和 Tableau 分析和绘制照片位置
Python、数据分析、地理、摄影
使用 Python 从数字照片文件和 Tableau 中提取 GPS 坐标和其他元数据来绘制它们
"元数据解放了我们,解放了知识"大卫·温伯格
介绍
当胶片摄影卷土重来时,数码摄影提供了许多好处。首先,在相机、镜头、存储和附件的初始投资之后,没有胶片或处理的费用,除非进行打印。此外,摄影师可以在相机和现场预览图像。此外,各种元数据,包括曝光和镜头设置,日期和时间,有时甚至是 GPS 位置,都存储在每张照片的文件中。
本文描述了一个 Python 程序,它从图像文件中获取 GPS 坐标和其他元数据,并将它们写入 CSV 文件。然后,它会在一个 Tableau 公共仪表板中呈现元数据,该仪表板跟踪相机的使用和图像位置。介绍使用 Python 从图像文件中提取元数据,参见 如何使用 Python 和 Tableau 分析照片元数据 。
演示总结
以下是本文中描述的处理和可视化影像 GPS 和其他元数据的任务:
- 使用 Adobe Lightroom 或您喜欢的照片编辑器将小图像文件导出到文件夹中。确保导出设置包含 EXIF 数据。就我而言,我选择了 2021 年用 Z50、D750 和 iPhone 12 拍摄的所有照片。或者,您可以将从一台或多台相机导入的未经编辑的图像文件存储在电脑上的单个文件夹中。
- 运行 Python 图像元数据提取程序,将图像文件夹作为其输入。该程序创建一个 CSV 文件,每个图像包含一个元数据行。
- 将包含图像元数据的 CSV 文件导入 Tableau Public。
- 建立一个 Tableau 仪表板,按月显示相机使用情况和照片位置地图。
"摄影从时间中抽出一瞬间,通过静止不动来改变生活."多萝西娅·兰格
关于图像元数据
数码相机将有关图像的元数据存储在一个文件中,该文件还包含所捕获图像的表示。他们以一种叫做 EXIF 的标准格式保存数据。以下是 EXIF 定义的一些字段示例:
- 图像制作 —相机制作
- 图像模式 l —相机型号
- EXIF 日期时间原件 —相机拍摄图像的日期和时间
- EXIF 焦距 —镜头的焦距
- EXIF 快门速度 —以秒为单位的快门速度
- EXIF 光圈数—F 档
- EXIF 曝光偏差值 —曝光偏差(低于或高于基准曝光时停止)
- EXIF 白平衡 —相机的白平衡设置
- EXIF ISO speedrating—ISO 传感器灵敏度设置
- GPS 纬度 —以度、分、秒为单位的地理纬度
- GPS 全球定位系统经度 —以度、分、秒为单位的地理经度
TsuruZoh Tachibanaya 描述了 EXIF 文件格式标准。此外,ExifTool 还记录了其相关的 GPS 标签。
Python ExifRead 模块
以下部分展示并描述了从影像中提取 EXIF 数据的 Python 程序。该程序利用了 ExifRead 模块。要使用该模块,请使用 Python pip 实用程序安装它。下面是一个 pip 使用示例:
$ pip 安装退出读取
Python 程序从图像文件中提取元数据
从图像文件中提取元数据并将值存储在 CSV 文件中的程序包括两个模块:一个作为程序入口点的控制器和一个从每个图像文件中读取元数据并将其写入 CSV 文件以供以后分析和可视化的类。下面介绍和描述了这些模块。
photo _ EXIF _ controller . py—该文件是程序的控制器模块和入口点。它只是打印一个开始消息,并用一组参数调用 c_photo_exif 类的构造函数。处理完成后,它会打印已处理的图像文件数量和完成消息。
控制器模块 photo_exif_controller.py .作者创建。
c_photo_exif.py —该文件中定义的 c_photo_exif 类执行以下步骤:
- 调用模块使用这些参数调用构造函数(init()):输入图像文件夹、输出 CSV 文件命名、程序将获取日出和日落时间的城市以及该城市的日落。
- init 函数在调用 init_csv_file()函数时格式化输出 CSV 文件的文件头。然后,它调用 process_photos()函数,逐个读取每个图像 JPEG 文件。
- 对于每个图像文件,process_photos()函数调用 process_photo()函数,从文件中提取元数据的子集。process_photo()函数又调用 calculate_coordinate()辅助函数将纬度和经度的 GPS 度数、分钟和秒钟值转换为单个数值十进制度数。
- 接下来,process_photos()函数调用 write_csv_file_row()将一个图像的元数据写入 csv 文件。
- 最后,控制器模块打印已处理图像文件的数量,并显示一条消息,说明已完成处理。
c_photo_exif.py 文件中的 c_photo_exif 类。由作者创作。
示例输出 CSV 文件
下面的截图显示了尼康 Z 50 和 iPhone 12 Pro Max 相机的两个元数据记录。如果图像文件包含 GPS 位置坐标,则程序会将经纬度(整数)、分钟和秒坐标值转换为小数。
CSV 文件中的 EXIF 元数据。图片由作者提供。
关于图像文件中相机和 GPS 元数据的注释
即使在今天,许多 DSLR 和无反光镜相机也不能直接捕捉照片位置的 GPS 坐标并存储在其图像文件中。然而,大多数(如果不是全部的话)当代智能手机都捕捉 GPS 坐标。
在这里显示的例子中,尼康 D750 没有捕捉 GPS 坐标。然而,尼康 Z50 只有在现场与 iPhone 上安装的尼康 SnapBridge 应用程序配对,并且 iPhone 获得 GPS 信号时,才会存储 GPS 坐标。另一方面,iPhone 12 只要接收到 GPS 信号,就会捕获 GPS 坐标。
可视化相机使用和照片位置与 Tableau 公共
为了分析相机使用和照片位置,我将 Tableau Public 连接到 Python 程序创建的 photo_exif.csv 文件。然后,我构建了一个可视化仪表板,其中包含两个工作表:一个按月记录相机使用情况,另一个在地图上显示我拍摄照片的位置。
Tableau 是领先的数据可视化和商业智能应用程序。其免费版本 Tableau Public 包含商业软件包的许多功能,但至少有两个明显的限制:
- Tableau Public 可以连接到有限数量的数据类型。例如,虽然它可以连接到 Excel 和文本文件,但它不能像商业产品那样直接链接到关系数据库。
- Tableau Public 仅将项目保存到 Tableau Public 服务器,供全世界查看。因此,如果您的 Tableau 可视化显示机密数据或不想与他人共享数据,Tableau Public 并不是一个很好的选择。相反,您可能希望选择另一种可视化产品,如 Tableau 或 Microsoft Power BI 的商业版本。
安装 Tableau Public
要在 Windows 或 Mac 电脑上安装 Tableau 公共桌面应用程序,请导航至https://public.tableau.com。然后,输入您的电子邮件地址,点击[下载应用程序],并按照安装提示进行操作。
Tableau 公共主页和安装表单。图片由作者提供。
创建相机使用和地图面板
下面列出的说明仅提供了构建相机使用和地图仪表板的基本步骤。要了解更多关于在 Tableau 中构建可视化工作表和仪表板的信息,请参见这些免费学习资源。
在您学习了如何使用 Tableau Public 之后,请按照以下步骤构建仪表板:
1 —打开 Tableau 公共应用程序。
2 —在连接窗口中,单击[文本文件]。然后,导航并选择包含 EXIF 数据的 CSV 文件。最后点击【打开】连接数据。
连接到影像 EXIF 元数据 CSV 文件。图片由作者提供。
3-在“数据源”窗口中查看影像 EXIF 记录。
数据源窗口中的示例图像 EXIF 数据。图片由作者提供。
4-构建一个“按月显示相机”工作表,其中包含一个条形图,显示按月显示的相机使用情况。
Tableau 公共桌面应用程序中的相机使用工作表。图片由作者提供。
5 —建立一个“照片地图”工作表。添加要应用于此工作表和相机使用工作表的过滤器。
Tableau 公共桌面应用程序中的照片地图工作表。图片由作者提供。
6-将“按月照相机”和“照片地图”工作表组合成“照相机使用”仪表板。
Tableau 公共桌面应用程序中的相机使用仪表板。图片由作者提供。
7-最后,如果你还没有创建一个免费的 Tableau 公共帐户,现在就创建一个。然后,将仪表板发布到 Tableau 公共网站。
Tableau 公共服务器上的摄像机使用仪表板。图片由作者提供。
你可以在这里查看仪表盘。
摘要
本文演示了如何使用 Python 从图像文件中访问关于数码照片的元数据。它还展示了如何转换数据,以便为可视化和分析做准备。最后,它演示了如何构建一个 Tableau Public,该 Tableau 使用图像元数据来可视化相机使用和图像捕获位置。
胶片相机仍然是捕捉我们周围世界图像的绝佳工具。但是现在,你可能会同意数码相机提供了额外的好处,以提高摄影过程和理解照片和模式。
“对我来说,相机是一本速写本,是直觉和自发性的工具.”— 亨利·卡蒂埃·布列松
使用差异中差异模型分析因果关系
对于真实世界的应用程序
作者图片
进行随机 AB 实验并不总是可行的,但如果我们有一个随时间产生观察数据(即面板数据)的近似实验,我们仍然可以恢复治疗的因果效应。我们可以使用的一个模型是差异中的差异(Diff-in-Diff,或 DiD)来估计观察数据的因果关系。
差异中的差异模型
当我们有两个现有的组(例如,两个区域 A 和 B)而不是像在随机 AB 试验中那样由我们随机分配,并且治疗发生在其中一个组时(例如,只有区域 A 发起促销),我们可以在治疗和控制之前对组间的差异建模,用于预先存在的差异,并且当我们假设治疗后的差异不是由于仅打击其中一个组的任何其他外部冲击而是由于治疗本身。
让我们用潜在结果模型的框架来研究一下数学。如果你需要快速回顾一下那是什么,你可以阅读我以前的文章。补充的是,现在我们使用具有时间维度的数据,因此将下标 t 添加到等式中。
设 yᵢₜ 为个体受试者在时间tI的潜在结果;y₀ᵢₜ 和 y₁ᵢₜ 为观察结果(我们只能观察其中一个,不能同时观察两个); Dᵢₜ 为治疗状态变量。DiD 的一个关键假设是,潜在结果 y₀ᵢₜ 可以建模为个体单位和时间固定效应的线性加法方程:
上面的第二个等式表明 Dᵢₜ 与协变量上的随机分配一样好。我们还假设因果效应是可加的和恒定的,我们推导出 y₁ᵢₜ为:
鉴于 yᵢₜ = (1-Dᵢₜ)y₀ᵢₜ + y₁ᵢₜ ,我们有:
这个等式表明,潜在的结果是由时间不变的个体固定效应和时间固定效应的总和决定的,时间固定效应在个体之间是常见的,并且是因果效应。
假设我们有面板数据,允许我们对治疗前后的组间差异进行建模。让我们将 t =0 表示为预处理周期,将 t =1 表示为后处理周期。只有当 D ᵢ=1(治疗组)和 t =1 时, Dᵢₜ =1。我们推导出差分中的差分如下:
对照组治疗前后的差异:
治疗组治疗前后的差异:
因此,治疗组和对照组之间的差异中的差异是平均治疗效果:
我们用回归的形式来写吧:
从回归中,我们得到:
一份申请
Card 和 Krueger (1994 年)估计了国家最低工资增加对就业的因果影响。1992 年 4 月 1 日,新泽西州将州最低工资从 4.25 美元提高到 5.05 美元,而宾夕法尼亚州的最低工资保持在 4.25 美元。卡德和克鲁格分别于 1992 年 2 月和 1992 年 11 月调查了新泽西州的快餐店。他们还从邻近的东宾夕法尼亚的快餐店收集了数据。
我从麻省理工学院经济学网站下载了 Card 和 Krueger (1994)使用的数据文件 public.dat。我用 Python 计算了新泽西州最低工资增长影响的简单 DiD 估计。本质上,我比较了从 2 月到 11 月期间新泽西州的就业变化和宾夕法尼亚州的就业变化。以下是代码:
以下是回归结果的摘要:
它说就业变化的差异是 2.76 个 FTE 雇员。似乎更高的最低工资并没有减少就业。然而,我的结果显示这种差异在统计学上并不显著。
提醒
Diff-in-Diff 估计有效的关键假设是共同趋势,这意味着,在上面的例子中,处理前两个州的就业趋势应该相同。治疗使治疗组的趋势偏离共同趋势。治疗组和对照组可以不同,因为这种差异意味着被未观察到的个体固定效应所捕获,但是它们需要共享一个共同的趋势。
为了检验这一共同趋势,我从 BLS 下载了 1991 年至 1993 年费城、宾夕法尼亚大都会区和新泽西“食品服务和饮料场所”行业的月度就业时间序列数据。我将 1992 年 4 月和 1992 年 11 月作为垂直虚线绘制在下面。就业价值指数是 1991 年 1 月确定的。下载的系列没有季节性调整。我看到很多波动。即使我们放大到 1992 年 1 月至 1992 年 4 月期间(治疗前),我也不确定 PA 是否与 NJ 相当。因此,在没有最低工资变化的情况下,PA 就业可能不是 NJ 就业的一个好的反事实测量。
使用 RStudio 分析医疗保险数据
了解如何使用 RStudio 分析医疗保险数据
欧文·比尔德在 Unsplash 上的照片
数据分析在商业中很重要,可以了解任何领域的当前状态,以做出准确的决策,推动业务步入正轨。在这里,我们涵盖了一个实用的领域,可以帮助个人在他们选择的任何领域进行数据分析。让我们从健康保险领域开始。
假设您收到了一个样本数据集( medExpense.csv ),其中包含了 1340 个当前参加健康保险计划的受益人的示例,这些示例显示了被保险人的特征以及该日历年的医疗费用总额。假设您被赋予了分析、讨论和解释这些数据的任务。我们将指导您如何使用 RStudio 处理这种情况。我们将使用 RStudio 来执行我们的数据分析。
加载数据集
**Code Snippet****## Importing the dataset**
dataset <- read.csv(‘medExpense.csv’, stringsAsFactors = TRUE)
Image_1:在 Rstudio 中加载数据集
让我们从在 RStudio 中加载数据集开始。我们可以使用 read.csv 函数(Image_1)从 CSV 文件加载数据集。我们设置 stringsAsFactors = TRUE 来自动将字符数据转换成因子,因为我们不能在机器学习算法中直接使用字符数据。加载的数据集如 Image_2 所示。
image _ 2:r studio 中加载的数据集
数据探索
**Code Snippet****## Returns the first parts of the data frame**
head(dataset)**## Returns the latter parts of the data frame**
tail(dataset)**## Compactly display the internal structure of the data frame**
str(dataset)**## Summarize medical expenses**
summary(dataset$expenses)**## Histogram of medical expenses**
hist(dataset$expenses)**## Table of region**
table(dataset$region)
图 Rstudio 中的数据浏览
现在让我们探索一下我们的数据集(Image_1)。使用 head & str 函数对数据集进行初步探索。头函数返回数据帧的第一部分(Image_4)。 tail 函数返回数据帧的后面部分(Image_5)。 str 函数简洁地显示了数据帧(Image_6)的内部结构。这里我们可以观察数据帧的结构。它包括 1340 行和 7 列。年龄列是 int 类型,性别列是具有两个级别“女性”&“男性”的因子,bmi 列是 num 类型,儿童列是 int 类型,吸烟者列是具有两个级别“否”、“是”的因子,地区列是具有四个级别“东北”、“西北”、“东南”、“西南”的因子,费用是 num 类型(Image_6)。从 CSV 文件中读取数据时,使用 stringsAsFactors = TRUE 将分类变量转换为因子。我们会用多元线性回归,机器学习算法不能直接对字符数据起作用。我们必须检测特征矩阵和因变量向量。由于我们对医疗费用感兴趣,所以我们选择费用列作为因变量,并对其进行更多的探索。汇总函数汇总医疗费用列的最小值、最大值、第 1 个&第 3 个四分位数、中值和平均值(Image_7)。医疗费用的频率分布通过直方图使用 hist 函数可视化(Image_8)。它表明大多数病例低于 10000。table 函数用于获取 region 列的每个因子级别组合的计数。它说 325 排落在东北地区,326 排在西北地区,364 排在东南地区,325 排在西南地区。
Image_4:数据帧的第一部分
图 5:数据帧的后半部分
Image_6:显示数据框的内部结构
图片 _7:医疗费用汇总
图片 _8:医疗费用柱状图
图 9:地区表
检查功能之间的关系
**Code Snippet****## Correlation**
cor(dataset$age, dataset$expenses)
cor(dataset$bmi, dataset$expenses)
cor(dataset$children, dataset$expenses)**## Correlation matrix**
cor(dataset[c(“age”, “bmi”, “children”, “expenses”)])
Image_10:检查 Rstudio 中各功能之间的关系
现在我们需要检查特性之间是否存在任何关系。我们可以使用 cor 函数(Image_10)检查特征之间的关系。在这里,我们试图解释有用的特征,这将有助于预测医疗费用。相关值为 1 表示这两个变量完全相关。在这里,我们分别比较了每个变量年龄、bmi、儿童栏与费用的相关性。然后,我们已经在一个函数调用中实现了所有这些。我们可以看到,年龄字段与医疗费用高度相关,相关值为 0.3009237 &儿童字段是最不相关的列,相关值为 0.0684989。Bmi 与 0.1934809 的值合理相关。我们已经在一个函数调用中比较了所有这些变量之间的相关性,如 Image_12 所示。
图 11:各变量年龄、bmi、子女栏与费用相关性的个别比较
Image_12:年龄、体重指数、子女、费用等所有变量的相关性比较
可视化特征之间的关系
**Code Snippet****## Scatterplot matrix**
pairs(dataset[c(“age”, “bmi”, “children”, “expenses”)])**## More informative Scatterplot matrix using psych package**
## install.packages(‘psych’)
library(psych)
pairs.panels(dataset[c(“age”, “bmi”, “children”, “expenses”)])
Image_13:在 Rstudio 中可视化功能之间的关系
我们使用 pairs 函数来可视化年龄、bmi、儿童特征的散点图矩阵(Image_14)。使用 psych package "**pairs . panels "**函数提供丰富的图表(Image_15)。在对角线上,我们可以看到每个特征的分布,无论是正态分布、右偏还是左偏等。年龄和 bmi 特征似乎呈正态分布(Image_15)。孩子和费用是右偏的,所以平均值正好落在峰值上。上半部分显示了这些特征之间的相关性(图 15)。年龄与费用高度相关,与其他特征的相关性较低。所以年龄是一个重要的特征。体重指数与其他特征的相关性较小,与费用的相关性也较小。儿童与其他特征的关联度较低,与费用的关联度也较低。下半部分显示了这些特征之间的相关椭圆(Image_15)。它被拉伸得越多,相关性就越强。如果是正圆,那就没有关联。似乎 bmi &儿童的相关性最小,因为它接近于圆形。由于椭圆拉伸,年龄和儿童是相关的。年龄和费用之间的椭圆最长,因此年龄在预测费用时很重要-用红色突出显示的黄土曲线表明年龄与费用呈线性关系(Image_15)。
图 14:将年龄、体重指数、儿童等特征的散点图矩阵可视化
图 15:使用“心理”软件包,用丰富的图表可视化年龄、体重指数、儿童的散点图矩阵
将数据集分成训练集和测试集
**Code snippet****# Splitting the dataset into training set and test set**
## install.packages(‘caTools’)
library(caTools)
set.seed(123)**## Obtain the training index**
training_index <- sample(seq_len(nrow(dataset)), size = floor(0.75 * nrow(dataset)))**## Partition the data**
training_set <- dataset[training_index, ]
test_set <- dataset[-training_index, ]
Image_16:在 Rstudio 中将数据集分为训练集和测试集
我们必须在数据集上构建模型,并在一个完全不同的新数据集上进行测试。所以我们需要两套。我们在其中建立机器学习模型的训练集和我们在其中测试机器学习模型的性能的测试集。测试集的性能不应该与训练集相差太多。这意味着机器学习模型已经很好地学习了相关性,因此它可以适应新的情况。我们使用 seed 设置一个随机状态来获得相同的结果。使用 sample 函数,我们从数据集中的所有行中随机抽取一个指定大小的样本(Image_16)。这里,我们从数据集中的所有行中获取 75%的训练索引。然后,我们使用整个数据集中的这些索引将数据集划分为 75%的训练集(Image_17)和 25%的测试集(Image_18)。
Image_17:分区后 75%的训练集
Image_18:分区后 25%的测试集
在训练集上训练数据(将多元线性回归拟合到训练集)
**Code Snippet****# Training the data on the training set****## Fit Multiple Linear Regression to the training set**
initial_model <- lm(expenses ~ ., data = training_set)
Image_19:在 Rstudio 的训练集上训练数据
这里,我们使用 lm 函数(Image_19)对训练集进行多元线性回归拟合。我们把医疗费用表示为所有自变量的线性组合,用“费用~ 表示。”在函数中。使用这个函数,我们在训练集上训练我们的初始模型。生成的模型如 Image_20 所示。
Image_20:训练后的初始模型
根据训练数据评估模型性能
**Code Snippet****# Evaluate the model performance on training data** summary(initial_model)**# Interpret on residuals, coefficients, statistical significance of predictors
# & overall model performance — Adjusted R-squared**
Image_21:评估 Rstudio 中训练数据的模型性能
这里我们已经使用 summary 函数获得了初始模型的概要。总结包括四个重要元素残差、系数、预测值的统计显著性&整体模型性能调整的 R 平方(Image_22)。
残差是误差。在低估的情况下,最大误差是 30029。这意味着实际费用高于预测费用。在高估的情况下,最高误差是 11439。这意味着我们收取的费用超过了实际费用。第一个四分位数代表第一个 25%分界点,第三个四分位数代表 75%分界点。第一个四分位数是高估 3060,第三个四分位数是低估 1445,这是可以接受的范围。
当我们查看系数部分时,我们看到 R 确实创建了伪变量&没有落入伪变量陷阱。它自动删除一个虚拟变量,以避免一些冗余的依赖关系。对于每个系数,我们有不同的信息—来自线性回归方程的系数、标准误差、t 值、p 值、显著性水平。对于模型,我们需要看看我们是否有足够的统计上的强变量。这是基于阈值的。一般来说,一个好的阈值是 5%。如果 P 值低于 5%,则自变量在统计上非常显著。它就越会大于 5%。它在统计学上不太重要。带星号的最后一列是解释系数的一种更快速的方法。在所有的独立变量中,年龄、体重指数、孩子和吸烟者是费用的强有力的统计预测因素。一些地区也是强有力的预测者。
调整后的 R 平方告诉我们因变量(医疗费用)的总可变性中有多少可以用模型(选定的自变量)来解释。这里我们得到了 0.7352,这是一个强模型。我们可以通过使用这个值来查看模型是否有所改进。
Image_22:训练数据的初始模型性能摘要
进一步改进和重新评估模型性能
**Code Snippet****## Add a higher order age term**
dataset$age2 <- dataset$age^2**## summary of the BMI column**
summary(dataset$bmi)**## Add an indicator for BMI**
dataset$bmi30 <- ifelse(dataset$bmi >= 30, 1, 0)**## Partition the data again with the additional columns but using the same index**
training_set_new <- dataset[training_index, ]
test_set_new <- dataset[-training_index, ]**## Create the final model**
final_model <- lm(expenses ~ sex + bmi + children + region + age2 + bmi30*smoker,data = training_set_new)**# Evaluate the model performance on the new training data**
summary(final_model)**# Interpret on residuals, coefficients, statistical significance of predictors
# & overall model performance — Adjusted R-squared**
Image_23:使用 Rstudio 中的附加 age^2 列评估训练数据的模型性能
Image_24:使用 Rstudio 中附加的 age^2 列和 bmi 指标列来评估模型在训练数据上的性能
图 25:使用 Rstudio 中的附加 age^2 列以及 bmi 指标列和吸烟者列的组合来评估模型在训练数据上的性能
为了优化我们的初始模型,我们可以做一些操作。引入互动栏目或特色是一种可能。当我们修改我们的初始模型及其性能时,我们用这些额外的列呈现新的训练数据。具有线性关系的年龄通过引入类似 age^新协议的附加列而被视为非线性关系。随着这一新列的添加,调整后的 R 平方值增加到 0.7389,从而提高了模型性能(Image_23 & 26)。此外,对于 Bmi,我们不是将其作为一个连续的值,而是将其作为一个健康与否的因素。我们用一个接近均值的值 30 来区分 bmi 值健康与否。随着这一新列的添加,调整后的 R 平方值增加到 0.7435,从而提高了模型性能(Image_24 & 28)。然后将具有最小 P 值的两列合并,这意味着具有高度的统计显著性。随着这一新列的添加,调整后的 R 平方值增加到 0.8565,从而提高了模型性能&,为我们提供了最佳模型(Image_25 & 29)。
这里我们已经使用 summary 函数获得了最终模型的概要。总结包括三个重要元素残差、系数、预测值的统计显著性和整体模型性能—调整后的 R 平方(Image_29)。
当考虑残差时,在低估的情况下,最高误差为 24059.4。这意味着实际费用高于预测费用。在高估的情况下,最高误差为 4567.1。这意味着我们收取的费用超过了实际费用。第一个四分位数是高估 1768.5,第三个四分位数是高估 747.6,这是可以接受的范围。
对于模型,我们需要看看我们是否有足够的统计上的强变量。这是基于阈值的。一般来说,一个好的阈值是 5%。如果 P 值低于 5%,则自变量在统计上非常显著。它就越会大于 5%。它在统计学上不太重要。带星号的最后一列是解释系数的一种更快速的方法。在所有的自变量中,统计上最强的预测因子是 bmi 指标&吸烟者的乘积,它具有最低的 P 值。高阶年龄&一些区域也是强有力的预测因子。性别和 bmi 列在费用预测中各自具有一定的意义。
调整后的 R 平方告诉我们因变量(医疗费用)的总可变性中有多少可以用模型(选定的自变量)来解释。这里我们得到了 0.8565,这是迄今为止我们得到的最高性能模型。该值比初始模型高得多。
Image_26:带有附加 age^2 列的训练数据的模型性能摘要
Image_27:身体质量指数专栏摘要
Image_28:具有附加 age^2 列和 bmi 指示列的训练数据的模型性能摘要
图 29:具有额外的 age^2 列以及 bmi 指标列和吸烟者列的组合的训练数据的最终模型性能摘要
用改进的模型预测测试集结果
**Code Snippet****# Predicting the test set results with the improved** modelmedicalExpensesPredicted = predict(final_model, newdata = test_set_new)cor(medicalExpensesPredicted, test_set_new$expenses)
plot(medicalExpensesPredicted, test_set_new$expenses)
abline(a = 0, b = 1, col = “red”, lwd = 3, lty = 2)
Image_30:使用 Rstudio 中的改进模型预测测试集结果
这里,我们使用预测函数(Image_30)通过改进的模型对新的测试数据(test_set_new)进行预测。我们使用 cor 函数比较测试集中预测医疗费用和实际医疗费用的相关性,得到的值为 0.9432327,这意味着它们高度相关,具有良好的准确性(Image_31)。这里我们绘制了预测与实际医疗费用的对比图(图 32)。很少有异常值,但该图表明在大多数情况下,实际结果和预期结果是一致的。你可以在这里下载上面例子的 R 脚本。
Image_31:改进模型的预测测试集结果
Image_32:绘制预测与实际医疗费用的对比图
现在你可能已经意识到,当你使用 RStudio 这样的工具时,数据分析并不是一个非常困难的过程。您可以将在本指南中获得的知识应用到任何其他感兴趣的领域。
使用 Julia 分析您的健康和健身数据
一个简单的数据科学项目,为您的编码周末增添趣味
我几乎每天都戴手表。我的习惯性合作伙伴是三星 Gear S3 Frontier,这是我在 2018 年生日时买的。除了手表的常见功能外,它还有一系列传感器来记录各种活动,如步数、距离、爬过的楼层和心率(通过光电容积描记图)。较新的银河系列手表还具有记录血氧和 EKG 的传感器。作为一个技术呆子,这自然让我兴奋!
这些传感器记录的数据被传递到三星健康应用程序,该应用程序已经很好地将它们总结成漂亮的视觉效果。然而,作为一名程序员,我一直渴望用它做更多的事情。幸运的是,三星允许我们下载原始数据。csv 文件)直接从应用程序。如果您是三星手表/手机用户,您可以按照本文文章中的说明下载您的健康数据。我想对于 Fitbit 和 Garmin 用户来说也有这样做的方法。如果你发现一些有用的东西,请在评论中告诉我。
在本指南中,我们将利用 Julia 生态系统中的各种软件包。我使用 Pluto.jl 做了这个练习,它允许我们创建交互式代码笔记本(此处可用)。也可以选择自己的编辑器比如 VS Code。
设置冥王星
如果你是 Julia 的新手,你首先需要从这里安装适合你的系统的二进制文件。一装好,打开朱丽亚·REPL。按“]”进入 Pkg (Julia 的内置包管理器)提示符。然后输入add Pluto
。这将下载 Pluto 包并为您编译它。按 backspace 键返回 Julia 提示符。然后键入using Pluto
,后面跟着Pluto.run()
。应该会打开一个新的浏览器窗口,显示 Pluto 主页。您可以继续创建新笔记本。
如果你熟悉 Jupyter,你已经知道如何使用冥王星。但是,请记住以下特性:
- 冥王星是一个反应式笔记本,这意味着细胞之间是相互联系的。当您更新一个单元格时,依赖于它的所有其他单元格也会更新。这也意味着你不能在两个地方使用相同的变量名,除非它们的作用域是局部的(比如在函数中)。
- 当在一个代码单元中写多行时,需要在 begin-end 块中换行。当执行(shift + enter)这样一个程序块时,您将得到一个选项来自动完成这个操作。
要在您的工作环境中导入所有相关的包,请执行以下命令:
using PlutoUI, DataFrames, CSV, Query, VegaLite, Dates, HTTP, Statistics
获取输入数据
我们将使用 CSV.jl 直接从我的 GitHub 存储库中读取数据,并以数据帧的形式存储它们。为了可视化,我们将使用优秀的 VegaLite.jl 包。来自三星健康应用程序的数据以各种 csv 文件的形式提供,但是,我们将只使用以下三种文件:
- com . Samsung . shea lth . tracker . pedometer _ day _ summary。。战斗支援车
- com . Samsung . shea lth . tracker . heart _ rate。。战斗支援车
- com . Samsung . health . floors _ clipped。。战斗支援车
文件名是不言自明的。我们可以将数据直接读入数据帧,如下所示。我们设置 header = 2,这样第二行用于命名列。
将 CSV 文件读入各自的数据帧
清洁和一些组织
让我们探索一下我们的数据帧实际包含了什么。
您也可以尝试以下方法:
create_time 列表示记录数据条目的时间,类型为“字符串”。我们需要将它转换成一个“DateTime”对象,这样以后就可以进行排序和更容易的绘图。此外,我们还可以将距离列转换为 km(从 m 开始),将活动时间转换为分钟。最后,我们通过删除重复条目来清理数据帧,并对 w.r.t. time 进行排序。
清洁和分类操作
我们计算累积距离,并将其添加到单独的列 cumul_distance 。为了以后的使用,将日子分类为“工作日”或“周末”,并将它们添加到单独的 day_type 列也很方便。对于新的日和月列也是如此。
添加新列
基于时间的过滤
使用 PlutoUI.jl 包,我们可以通过添加按钮、滑块等来进一步增强交互体验。例如,要将日期时间值绑定到变量 **start_date,**执行以下操作。
插入交互式日期选择器
根据上面选择的时间范围过滤数据帧。 @filter 是 Query.jl 包提供的强大宏。我们筛选出创建时间位于开始日期和结束日期之间的行,如下所示:
使用 Query.jl 进行过滤
现在我们准备开始可视化数据。
每日步骤
我们过滤后的数据帧 df_pedometer_filter 可以直接传递给 VegaLite.jl 包提供的 @vlplot 宏。其余的参数是特定于绘图类型的。查看 VegaLite.jl 教程了解更多信息。
用线梯度绘制每日步数
很明显,2020 年我走的步数少了很多。这可能是由于电晕爆发期间实施的封锁。很高兴看到我在 2021 年加快了步伐。相同的数据也可以可视化为堆叠直方图。
绘制每日步数的堆积直方图
每天的默认目标设置为 6000 步。我总是试图至少达到那里,因此三年的峰值都在那个值附近。对于 2020 年,有很多天我的活动量如预期的那样低。
每日距离
我喜欢每天去散步。除了步数,看看我通常走多远也是很有趣的。在我们的 DataFrame 中将色标设置为 distance 列,以与每个数据点的大小成比例的渐变来呈现条形。看起来相当酷!
将每日距离绘制成带颜色渐变的条形
累积距离
有趣的是,我还可以检查到目前为止我已经跑了多少公里。我猜达到 10,000 公里会是一个不错的目标。
将累积距离绘制成面积
有效时间
这是在任何活动(行走、跑步等)中花费的时间。)如手表所检测到的。如果您还记得的话,我们之前已经根据是工作日还是周末添加了一个 day_type 列。现在,我们可以利用它来相应地对我们的活动时间进行分组。
使用日类型分组的绘图活动时间
我们还可以简单地通过将参数列表中的color = :day
参数更改为 @vlplot 宏来对每天的活动时间进行细分。
似乎我在周二和周三很活跃,周六最不活跃。这有意义吗?
步数和卡路里之间的相关性
绘制 2D 直方图,显示步数与卡路里的关系
您可以在 Pluto 中创建一个滑块(需要 PlutoUI.jl 包),并将其值绑定到 select_year 变量,如下所示:
正如所料,步数和消耗的总热量有直接的关系。该 2D 直方图散点图还显示了大小与总计数成比例的标记。步数越多,数据点越少。今年我应该试着更加积极。
步数与活动时间的热图
绘制步数与卡路里的热图
可视化心率数据
心率数据也可以使用类似的策略进行清理,如前所示。
使用圆形标记和与数值成比例的尺寸绘制心率数据
我的手表每隔 10 分钟测量一次心率。我几乎每天都穿。这意味着大多数数据点是在我坐在办公桌前工作时收集的。让我们看看分布是什么样的。
绘制心率分布图,色标设置为数值的大小
大多数数据似乎集中在每分钟 60-100 次(bpm)的静息心率范围,平均值约为 78-79 BPM。那就放心了!相当高的值可能是在运行会话期间测量的。
攀爬的楼层数
爬过的楼层数
这里没有什么太令人兴奋的,除了 2019 年 11 月的大幅飙升。在印度奈尼塔尔市的一次短途徒步旅行中,我戴着这只手表。9 英尺的高度变化被记录为一次楼层爬升。所以,65 层楼表明我在那段时间里一定爬了 585 英尺~ 178 米。唷!
结论
朱莉娅的生态系统正在迅速发展,有许多令人惊叹的绘图包,而 VegaLite.jl 恰好是其中之一。图形风格的优雅语法和与 DataFrames 的紧密集成使其成为任何类型的数据科学/分析项目的理想选择。我希望您喜欢阅读本指南。完整代码(冥王星笔记本)可以在这里找到。感谢您的宝贵时间!如果你想联系,这是我的 LinkedIn。
注来自《走向数据科学》的编辑: 虽然我们允许独立作者根据我们的 规则和指导方针 发表文章,但我们不认可每个作者的贡献。你不应该在没有寻求专业建议的情况下依赖一个作者的作品。详见我们的 读者术语 。
参考
用 SQL 分析 120 年奥运历史
SQL 实践教程
马特·李在 Unsplash 上的照片
我在 Kaggle 上发现了一个很棒的数据集。它是在知识共享许可下共享的,所以我们可以公开使用和共享它。我认为了解奥运会的历史将是令人兴奋的。
有许多替代工具可用于对此数据集执行分析。我选择 SQL 没有特别的原因。在本文中,我们将在练习 SQL 的同时了解奥运会。
注意: SQL 被很多关系数据库管理系统使用,比如 MySQL、SQL Server、PostgreSQL 等等。尽管它们大多采用相同的 SQL 语法,但可能会有一些细微的差别。在本文中,我们将使用 PostgreSQL。
我选择了一些列,并将数据上传到一个 SQL 表中。让我们先来看看奥运表。
SELECT * FROM olympics LIMIT 5
(图片由作者提供)
我们有运动员的名字、性别、年龄和他们参加的运动。该表还包含游戏的详细信息。原始数据集包含 271116 行,但是我只上传了 200000 行到 olympics 表。如果对整个数据集进行相同的分析,结果可能会略有不同。
我想看看有多少不同的运动员参加了奥运会。我们可以数出不同的名字。
SELECT COUNT(DISTINCT(name)) FROM olympics99875
这张桌子上有近 10 万名不同的运动员。我想知道他们中有多少人获得了奖牌。
SELECT COUNT(DISTINCT(name)) FROM olympics
WHERE medal IS NOT NULL20560
我们刚刚使用 where 语句添加了一个条件。
让我们找出奖牌总数前 3 名的国家。
SELECT team, COUNT(medal) AS medal_won
FROM olympics
WHERE medal IS NOT NULL
GROUP BY team
ORDER BY medal_won DESC
LIMIT 3
(图片由作者提供)
上面的查询过滤了 medal 列没有空值的行。然后,根据团队列对行进行分组,并对行进行计数,这就给出了获得的奖牌数。最后,结果集按奖牌数降序排序,选择前三个。
了解获得奖牌的男女运动员的平均年龄是很有趣的。
SELECT sex, AVG(age) AS avg_age
FROM olympics
WHERE medal IS NOT NULL
GROUP BY sex
(图片由作者提供)
女运动员比男运动员小两岁。
我们还可以查看女运动员获得奖牌最多的前 5 项运动。
SELECT sport, COUNT(medal) AS medal_count
FROM olympics
WHERE sex = 'F'
GROUP BY sport
ORDER BY medal_count DESC
LIMIT 5
(图片由作者提供)
考虑到我们对比赛年份感兴趣。该表没有单独的年份列,但可以从游戏列中提取。
SELECT LEFT(games, 4) AS year, games
FROM olympics
LIMIT 5
(图片由作者提供)
左边的函数允许从字符串中选择部分。它接受列名和要选择的字符数。right 函数做同样的事情,但是从右边开始计数。
下一个示例与其说是探索数据集,不如说是 SQL 实践。考虑到我们只需要 1950 年以后的数据。我们可以删除属于 1950 年或之前的游戏的行,或者用我们感兴趣的数据创建一个新表。
以下查询使用 olympics 表中的数据创建一个新表。
CREATE TABLE olympics_after_1950 AS
SELECT * FROM olympics
WHERE CAST(LEFT(games, 4) AS INTEGER) > 1950
让我们检查一下查询是否工作正常。
SELECT MIN(LEFT(games, 4)) FROM olympics_after_19501952
令人惊讶的是,create table 语句用于创建表😃。我们可以通过使用 select 语句和 create table 语句从不同的表中选择数据来填充新表。
我们还可以通过删除属于 1950 年或之前的奥运会的行来更新奥林匹克表。我想保持原来的桌子不变。我们可以在新表上练习 update 语句。
让我们删除新表中 1970 年之前的行,然后检查最小日期。
DELETE FROM olympics_after_1950
WHERE CAST(LEFT(games, 4) AS INTEGER) < 1970SELECT MIN(LEFT(games, 4)) FROM olympics_after_19501972
我们做了几个例子来深入了解奥林匹克的历史。我们还练习了基本的 SQL 语句和函数。
感谢您的阅读。如果您有任何反馈,请告诉我。
分析和解释评分表中的数据
使用学生/客户满意度调查数据的两部分指导性案例研究
注:本帖代码可在 这里 找到
仔细查看评分标准(图片由作者提供)
等级量表是衡量态度和观点的一种有效且受欢迎的方式。它们易于实现,广泛用于调查、反馈表和绩效评估。然而,误用和错误经常发生在这个看似直观的工具的实现和分析中。理解和综合评定等级信息的能力使我们能够在不断变化的环境中做出决策。这个由两部分组成的系列的目标是展示有效利用评定等级数据所需的基本概念以及关于常见陷阱的警告。在第一部分中,我们从定性考虑开始,这对于第二部分中讨论的定量分析的适当性具有重要意义。****
数据集介绍
在我们的案例研究中,我们将使用我从数据分析课上收集的每周调查结果。这些匿名调查要求所有学生每周在进行。这些说明要求学生对以下每个因素进行 1(差)到 5(好)的评分,从“总体满意度**”的总体评分开始。我们的目标是深入了解学生对整个课程的感受。**
反馈形式问题
了解评定等级
每个评定等级都作为一个封闭式问题来实施,以获取信息。它要求回答者根据说明给被评对象赋值。正确使用时,等级量表可作为非物理属性的测量工具。不同于我们用来测量物理属性的科学仪器(例如测量温度的温度计和测量长度的尺子),等级量表可以用来测量本质上是认知的属性。因为它们是抽象的、无形的和复杂的,所以通常不能用一个问题来概括。相反,我们可以问一系列涉及主题不同方面(或因素)的相关问题,我们称之为“兴趣结构”。对这些个别但相关问题的回答更多的是基础和陈述性。****
评级标准的类型
有 4 个基本级别的测量尺度用于采集数据。每个秤都是一个级增量级测量,即每个秤都实现前一个秤的功能。在分析数据时,首先理解变量代表什么是很重要的。
4 种测量尺度
附注:评级尺度分析的一个常见缺陷是假设选择之间的距离相等。
可用于名义秤的分析类型非常有限,因为它缺乏数字属性。它们很容易实现,但只对分类数据有用。更常见的评级尺度是序数或区间,其中的选择带有等级顺序属性。两者之间的差异可以是细微的**,但是从分析的角度来看的含义是相当显著的。在决定实施/应该实施哪一项时,我们会考虑受访者是否认为(所有)选项是等距的。这种不足使使用参数统计数据进行序数标度的能力受到质疑,但有时可能是首选,因为它们相对容易使用。另一方面, Interval Scales 将选项设计为均匀间隔(即,不同选项之间的差异幅度相同),这可以通过将单词锚与序列号相关联来实现。这种方法利用了人们对数字线的直觉,支持使用均值、标准差以及其他统计方法。我们正在分析的数据来自区间尺度;因此,受访者选择的幅度和差异是有意义的,尽管这并不意味着选择#4 的强度是选择#2 的两倍(对于比率等级来说是这样的)。**
测量仪器具有可靠性和有效性
评级尺度衡量难以定义的和缺乏验证标准的**;因此很难知道他们什么时候按计划工作。评定量表的有效性可以通过可靠性和有效性进行评估,定义如下:**
- 可靠性(意味着稳定性和一致性** ) —如果重复使用,仪器会产生相同的结果。**
- 有效性(意味着准确性** ) —仪器准确测量它应该测量的东西。**
Fido 教授可靠性和有效性
我们打个比方来强调信度和效度的重要性。假设我们相信一只叫 Fido 的狗已经被训练来警告危险的血糖事件。他们通过检测与这些血糖水平下的生物化学相关的气味来做到这一点。Fido 在许多方面起着测量工具的作用。在它们被认证为官方糖尿病警戒犬之前,我们必须首先评估它们的可靠性和有效性。出于可靠性考虑,我们希望确保它们能够持续向人类同伴发出警告信号。他们应该表现出对周围环境干扰的抵抗力,并且警告信号不是不稳定的。为了有效性,我们希望确保他们的警告信号是异常血糖事件的真实指示。他们的警告信号应该伴随着来自患者佩戴的 BGM(血糖监测器)的过高或过低的读数。
测量可靠性和有效性
对信度和效度进行定性评估和定量评估**。为了获得对可靠性和有效性估计的信心,我们的数据应该有足够的样本量和一定的可变性(如下直方图所示)。重要的是要记住,我们计算的估计值主要用于评估研究方法的质量,而不一定对结果做出推断**。********
调查中各因素的评分分布
可靠性
可靠性是指如果在相同的条件下再次使用评定量表,评定量表会给出相同结果的程度,即其稳定性 y 或一致性 c y。没有可靠性,我们就不能确定来自评定量表的数据是有意义的且不是(部分)随机的。我们可以通过观察两组(或更多组)测量值之间的相似性来量化可靠性,即一致度 e。实际上,有 4 种类型的可靠性可以比较来自相同等级量表的不同结果组,如下散点图所示:
不同类型的一致性
对于区间数据,使用相关性来估计可靠性是合适的,从广义上讲,它衡量两个变量之间的关系(而不是一致性)。可靠性可以显示一个评级尺度抵抗可能影响人们准确反应能力的外部因素的能力,例如不清楚的指示或选择标签**。很难给什么被认为是可靠的划定一个门槛;因此,检查 4 种可靠性类型中的每一种(视情况而定)来寻找和审查不可靠性的证据是合适的:**
- 重测信度考察的是同一受访者在一段时间内所取得结果的一致性。它用于评估评级尺度抵御外部因素(如受访者在调查时的情绪)的能力。它可以表示为在不同时间点进行的调查之间配对结果的相关性 ( 皮尔森),如图表 A) 和 B) 所示。这也被称为班内可靠性,它假设学生每周都会有类似的反应,因为他们对班级的看法不会有实质性的改变。增加测试和重新测试之间的时间(以减少记忆效应)会随着时间的推移引入真正变化的前景,使观察可靠性变得更加困难。
重测信度(评分者内部信度)
在 B1) 中,我们对结果本身进行绘图,以产生完美的相关性。这是为了模拟两个时间点的结果是否相同且高度可靠。在 B2) 和 B3) 中,数据被认为不太可靠,因为受访者选择了递增的不同评分,例如,第一次回答 4,第二次回答 3 或 5。这可能是由于对指令或选择的不同解释,导致了较低的相关性。我们数据的实际结果显示在 B4) 中,相关系数约为 0.65,这并不坏,因为我们确实期望观点会改变。值得注意的是,第 3 周和第 6 周之间的相关性下降(如 C) 所示),可能是由于寒假期间的时间差。
- 内部一致性顾名思义,寻求旨在测量相同结构的项目结果的一致性。换句话说,调查中相关问题的结果是一致的还是相互矛盾的。首先是每个评级尺度之间的成对相关性 ( 皮尔森),如附件 A) 和 B) 所示。
内部相容性
在 B) 中,我们用热图绘制了评级尺度之间的成对相关性。不出所料,所有个人因素都与全球“总体满意度”评级相关。这表明,这些因素中的高评级对应于“总体满意度”中的高评级,反之亦然。此外,与讲师相关的问题的结果(清晰度、知识和参与度)具有很高的相关性。相关性可以通过克朗巴赫的阿尔法来总结,对我们的数据来说是> 0.8。我们发现“课外应用学习”和“教师知识”之间的相关性较低,以及“课外应用学习”和“学术支持”之间的相关性较低,这是可以接受的,因为它们之间的相关性较小。
- 评分者间可靠性着眼于不同人的结果的一致性。它用于评估主观性对受访者选择的影响程度。可以使用回答者之间的成对相关性 ( Pearson )进行计算,如附件 A) 和 B) 所示。虽然单个受访者之间的相关性不太重要,但它们应该作为一个整体反映一些普遍的一致(如克朗巴赫的阿尔法等可靠性系数所总结的)。
评分者间信度
在 B) 中,我们用热图绘制了学生之间的两两关联。除了少数例外,大多数相关性都是> 0.6。只要大多数学生能够作出类似的回答,那么一小部分与他人相关性较低的受访者是可以接受的。
Pearson 相关性的使用仅适用于区间数据,在较小程度上适用于顺序数据,因为它保持了选择之间的顺序关系。对于名义数据,一致性可以用总体一致性百分比或 Fleiss/Cohen 的 Kappa 来衡量。
- ****平行(或等效)形式可靠性要求相同的回答者接受不同版本的调查,这些调查被设计为等效的。或者,这可以通过创建一大组问题并将它们随机分成两组来实现。遗憾的是,我们没有使用可替换的调查问题。
有效期
有效性是指评定量表的结果在多大程度上代表了其预期目的,即准确性。当测量具有可靠性时,我们更加有信心认为结果代表了它们应该代表的东西;因此,有效性是基于可靠性的,但是可靠性本身是不够的——等级量表可以非常可靠,但是无效。确定测量有效性的最明显的方法是将其与基准进行比较。与基准可比的度量更有可能是有效的,但不幸的是它们并不总是存在。在这里,我们将基准称为 1) 一种用于测量感兴趣的构建体的成熟方法,或者 2) 一种与感兴趣的构建体相关的群体统计。即使基准不完全匹配,比较也有助于验证评级尺度。有效性有三种类型:****
- 表面有效性着眼于评定等级与被测概念的现有理论和知识的一致性。另一方面,内容有效性关注调查在多大程度上覆盖了感兴趣的结构的所有方面。它们都是定性评估,最好通过征求双方 专家和参与者的反馈来实现。此外,对问题和选择的描述应该清晰、透彻、完整地阐述感兴趣的结构。根据我们的数据,我们咨询了教育领域的专家,以确保调查问题全面且与学生关心的问题密切相关。
- 标准有效性检验评级量表的结果与旨在衡量类似结构的不同方法的结果有多接近。我们比较的结果是标准,它通常来自一个已建立的或广泛使用的方法。这两者之间的高度相关性很好地表明,评级尺度是衡量什么是声称。我们希望在我们的调查中建立等级量表的有效性,因此我们寻找比较的方法。代替真正的“黄金标准”标准,我们可以使用开始时收集的全球“总体满意度”评级来评估其他因素的有效性。合理的假设是,个人因素的评级有所贡献,因此应该与满意度评级相关联。
并行有效性
综合指数(单个因素的总和)和加权综合指数都与总体满意度相关。这被称为并发有效性**,因为它的总体满意度与其他问题同时进行。**
预测效度
为了寻找更多有效性的证据,我们可以用学生每周作业中的数据来扩充我们的调查结果。我们发现“作业反馈评级”和评分者对学生作业提交的反馈中的字数有很高的相关性。此外,学业支持与作业成绩也有很高的相关性。这被称为预测有效性**,因为这些变量是在稍后的时间点收集的。**
准备信度和效度的方法
在调查进行之前,我们不会知道它有多可靠或有效。如果操作不当,即使是精心设计的评级标准也会遇到问题。以下是一些提高可靠性和有效性的技巧:
- 彻底设计并采纳他人的意见——从明确定义的目的、目标甚至收集方法开始,需要进行大量规划以确保调查成功。应对促成感兴趣的构建的因素进行映射,以确保包括所有相关方面。
- 考虑受访者的偏好/努力—容易回答的问题可确保高参与率。另一方面,难以使用或理解的评级标准会导致回答者变得沮丧和消极,从而降低他们回答的质量。
- 避免偏差来源——以下是评定等级中常见的偏差来源:
偏差的不同来源
摘要
在本文中,我们对来自学生/客户满意度调查的评级尺度数据进行了定性评估。我们期望数据的可靠性和有效性,但要做到这两点还需要大量的工作。为了最大限度地利用评分量表,我们应该在可靠性、有效性、辨别能力和受访者偏好之间进行权衡分析。随着计算技术的进步,数据收集方法变得比以往更加灵活、适应性更强、效率更高。我乐观地认为,这类研究中的巨大机会将继续帮助组织满足其成员的需求。
接下来,我们将对相同的数据进行定量分析。如果你喜欢这篇文章,我邀请你跟我来,这样你就可以在第二部分得到通知。
分析和预测消费者参与度
我们将使用来自 Kaggle 的互联网新闻和消费者参与数据集来分析消费者数据,预测热门文章和受欢迎程度评分。
介绍
在这个项目中,我们将使用来自 Kaggle 的互联网新闻和消费者参与数据集来预测热门文章和受欢迎程度评分。我们将探索我们的数据,以发现模式,如相关性,分布,均值和时间序列分析。我们将使用文本回归和文本分类模型来预测参与度得分和基于标题的热门文章。
文本分类在我们日常使用的应用程序中很常见。例如,电子邮件提供商使用文本分类来过滤掉收件箱中的垃圾邮件。文本分类的另一个最常见的用途是在客户服务中,他们使用情感分析来区分差评和好评 ADDI AI 2050 。我们将在标题上训练我们的模型,以便它可以预测文章是否在顶部。文本回归是类似的,其中我们采用文本矢量化数据并预测十进制值的流行度得分。
我们的重点将放在文章标题以及它如何影响其他功能上。
资料组
该数据集(源)受知识共享— CC0 1.0 通用许可,有关更多信息,请查看此处的元数据信息。该数据集是关于 2019 年 9 月 3 日至 2019 年 10 月 4 日收集的新闻文章。随后,脸书参与度数据(如分享数、评论和反应)丰富了这一数据。
- Source id 列值表示发布者的唯一标识符,通常表示为小写的 sourcename,空格替换为下划线符号。
- Source_name 列值表示发布者名称。
- 作者列值表示文章作者。一些出版商不共享他们的新闻作者的信息,在这种情况下,通常 source_name 会替换这些信息。
- 标题列值表示文章的标题。
- 描述列值表示通常在发布者网站的弹出窗口或推荐框中可见的短文描述。这个字段被缩短为几个句子的内容列。
- Url 列值指示位于发布者网站上的文章的 URL(统一资源定位符)。
- Url 到图像列值表示与文章相关联的主图像的 Url。
- Published_at 列值表示发布文章的确切日期和时间。日期和时间以 UTC (+000)时间格式显示。
- 内容列值表示文章的无格式内容。该字段被截断为 260 个字符。
- Top_article 列值表示文章在发布者网站上被列为热门文章。该字段只能有两个值,当文章包含在流行/热门文章组中时为 1,否则为 0。
安装所需的软件包
我们将安装用于情感分析的 vaderSentiment,显示最常用词的 wordcloud,用于机器学习模型的 lightgbm,以及用于不平衡分类的 imblearn。
加载所需的库
探索数据
在这一部分中,我们将探索我们的数据并可视化关键特征,以理解消费者参与度。
加载数据
经过初步审查的数据集包含 10437 条记录和 14 列。
我们将重点关注:
- 文章标题
- 来源名称
- 作者
- 热门文章
- 用户参与特征。
缺少值
使用.isna().sum()
我们可以检查每一列的缺失值。为了让它看起来更有趣,我们将我们的发现转换成一个带有NA percent
和颜色渐变背景的表格。正如我们可以观察到的,大多数内容和作者名称列都缺少值。
前十名作者和来源名称
使用 seaborn 条形图,我们显示了前 10 名作者和来源名称。我们可以看到有些作者的名字与 publication/sources 相似。前三大主要来源是路透社、BBC 新闻和爱尔兰时报。排名前三的作者分别是美联社、路透社和 CBS 新闻。
顶级文章
使用 matplotlib 饼图,我们可以看到有 12%的热门文章。
接合箱线图
很难分析参与度数据的分布,因为它们有极端的异常值。我们可以使用sns.kdeplot
和np.log1p
来分析每个参与列,但是有一个更好的方法是使用 boxplot,将 yscale 设置为Symlog
。
- 接合反应计数有 1 个中值,但它有多个平均值在 0–60 之间的异常值。
- 参与评论计数为 0 中等,但有多个平均值在 0-1 之间的异常值。
- 参与份额计数为 10 中等,但有多个平均值在 0-50 之间的异常值。
- 参与评论插件计数为 0 中等,但它有多个平均值为 0 的异常值。
评论插件
让我们看看评论插件,因为它有最奇怪的数据,平均值和中值都是 0。正如我们所看到的,99%的数据是零,其余的是 1-15 的异常值。
干净的标题
让我们清理标题,因为我们将在机器学习模型中使用它。我们的文本数据中有标点符号和大写单词,这将使我们的模型表现最差。
clean_title
函数将清除括号、超链接、标点和包含数字的单词。
添加包含干净标题的新列
创造情感极性
使用 Vader 情绪强度分析器,我们将从干净的标题中提取分数,并将其分为 3 类:积极、消极和中性。
应用复合分数
运用情感
正如我们所看到的,我们已经在数据集中添加了 2 列,分别是情绪得分和基于得分的情感。
情感类别计数图
新闻标题多有中性情绪和负面情绪看新闻。
词云
我们将使用单词云库来显示标题和描述中最常用的单词。
最常见的单词是 say、new、said、will 和 Trump 。我们使用英语停用词来删除每个句子中的常用词。
时间序列
我们将在 2019 年 9 月 3 日至 2019 年 10 月 3 日期间策划消费者互动。
分割日期时间
我们将把日期拆分成星期、月份和年份,然后将它们添加到数据帧中。
一个月的雇佣次数
使用 seaborn 折线图显示一个月内的消费者参与模式。十月一日,消费者参与度出现高峰。可能是因为某个重大事件。除此之外,在 9 月 3 日、7 日和 12 日还有较小的反应高峰。
关联热图
反应、评论和分享参与度之间存在高度正相关。喜欢帖子的消费者最有可能分享和评论。约定和顶级文章之间没有其他显著的相关性,很明显,顶级文章的选择纯粹基于质量。
预处理
- 替换丢失的标题
- 将标题转换成矢量
- 替换 top_article 中缺少的值
- 使用 SMOTE 进行过采样
- 创造人气 pcore
Tfidf 矢量器
我们的机器学习模型只理解数值,因此为了在文本数据上训练我们的模型,我们将把它转换成 TF-IDF 特征的矩阵。 SKlearn
过采样
我们的top_article
数据是不平衡的,因为我们只有 12%的 1。为了使我们的模型性能更好,我们将使用过采样方法 SMOTE(合成少数过采样技术)。我也尝试过其他过采样和欠采样方法,但 SMOTE 表现更好。
受欢迎程度得分
我们将添加所有四个参与列,然后采取类似于np.log(X+1)
的np.log1p(X)
。许多零约定将导致无穷大,因此将所有列加 1 将避免灾难。
我们可以清楚地看到大部分分布在 0-3 之间。
我们可以清楚地看到,最受欢迎的两家出版公司是《纽约时报》和 CNN。
测试分类器模型
让我们建立一个模型,该模型将获取标题并预测文章是否会成为热门。
- x:标题
- y:热门文章
建立模型
我们已经用 SGD 和随机森林分类器进行了实验,但是到目前为止,光照梯度增强模型表现得更好。在超参数调整之后,我们的模型就可以在数据集上训练了。
- 分为训练和测试。
- 将我们的置顶文章分层,使它们平均分布。
- 使用 LGBMClassifier
- 学习率=0.5,
- max_depth=20,
- num_leaves=50
- n _ 估计值=120,
- max_bin=2000
- 交互效度分析
- 培训和测试
- 混淆矩阵
交互效度分析
在对我们的模型进行交叉验证后,我们可以观察到我们的 f1 分数相当稳定。0.9 是我们能达到的最高值。
训练/测试模型
在训练数据集上拟合我们的模型后,我们可以看到f1
和accuracy_scores
在我们的测试数据集上都是+0.9。
保存模型
混淆矩阵
我们有一些假阳性和假阴性。总的来说,我们的 LGBM 模型表现得比预期的要好。
文本回归模型
- x:标题
- y:人气 _ 分数
我们将使用矢量化标题来预测受欢迎程度得分。我已经用逻辑回归和随机森林回归进行了实验,但是在我们的例子中,光梯度增强表现得很好。
- 用 1 填充缺失值。
- 训练和测试分割
- LGBMRegressor
- 学习率=0.01,
- max_depth=20,
- num_leaves=50
- n _ 估计值=150
- 交互效度分析
- 培训和测试
列车测试分离
建立模型
验证分数
该模型表现良好,因为没有超参数调整和逻辑回归,得分为 8+ RMSE。
培训和测试
在训练数据集上拟合模型之后,似乎我们的模型在测试数据集上也表现得很好。现在,我们将使用这两个模型来构建标题评分函数。
保存模型
标题评分
title_score
函数获取标题并输出流行度得分,对热门文章进行分类。全面参与,包括反应、分享和评论。我们可以使用这些功能为我们的博客创造最好的标题。
功能任务:
- 清理文本
- 将文本矢量化
- 预测热门文章和受欢迎程度
- 打印热门文章、受欢迎程度得分和总参与度。
测试
是时候测试我们的功能和预测模型了。我们将首先测试数据集内的随机值,然后使用今天新闻的标题来确定分数。
正如我们可以清楚地看到我们的功能和两个模型的工作。
最新消息
随机测试最新消息
热门新闻测试
正如我们所见,它得到了很高的受欢迎程度。
我们再次测试了新闻头条,正如我们所见,根据我们的模型,它是头条。
结论
我们在探索数据和玩不同的机器学习技术和模型中获得了乐趣。简而言之,我们探索了我们的数据,并提供了独特的信息,可以帮助新闻机构创造更好的内容,从消费者那里获得高牵引力。我们开发了机器学习模型,将帮助作家和博客写手写出更好的标题。我们还发现,高人气并不意味着这篇文章会成为头条。
对于未来的工作,我想探索数据中的多个聚类,并使用文章的图像创建一个模型来预测受欢迎程度得分。我已经试验了深度学习文本生成模型,但由于内存限制,我仅限于简单的表格模型。
为了学习更多关于数据分析、自然语言处理和机器学习的知识,我建议你参加一个令人惊叹的 DataCamp 课程,并自己练习。
密码
代码可从以下网址获得:
作者
阿比德·阿里·阿万 ( @1abidaliawan )是一名认证数据科学家专业人士,热爱构建机器学习模型和研究最新的人工智能技术。目前在 PEC-PITC 测试人工智能产品,他们的工作后来获得批准用于人体试验,如乳腺癌分类器。
分析和可视化来自非结构化数据的情感
使用 Microsoft Azure 文本分析和 Power BI 集成
梅森·琼斯在 Unsplash 上拍摄的照片
情感分析
微软 Azure 认知服务和 Power BI 集成
全球创建、捕获、复制和消费的数据总量预计将快速增长,在 2021 年达到 74 兆字节(来源:Statista)。想象一下,这 74 个 zettabytes 的数据中有多少将是非结构化的和不受控制的,留下一个巨大的空白💣世界各地的数据科学家将如何分析、建模和消费这些庞大的数据。例如,亚马逊等电子商务网站上的产品评论,或者脸书和 Twitter 等社交媒体巨头的言论自由。
非结构化数据面临的主要挑战之一是如何衡量公众意见,进行细致入微的市场研究,监控品牌和产品声誉,以及了解客户体验。通俗地说,如何理解和分类情绪,或者对于数据科学家来说,如何进行情绪分析。情感分析是确定一篇文章是正面、负面还是中性的过程。
我们将讨论什么?
在本案例中,我们将对一组样本数据进行情感分析,并使用:
- Microsoft Azure 文本分析(用于执行情感分析)
- Power BI(用于集成和可视化)
以下是我们将使用的示例数据的链接: 示例数据 。
所需资源
- Microsoft Azure 订阅(免费试用或付费)
- 微软商务智能桌面(专业版许可)
你准备好了吗??我们开始吧🏄
第一步:Azure 文本分析
登录 Azure 门户:https://portal.azure.com/#home,搜索“文本分析
Azure 门户主屏幕搜索栏
通过选择订阅、创建资源组(只是绑定资源的容器)、位置和定价层来创建文本分析服务。一个免费的网络容器每月允许5000 笔免费交易 。点击“**查看+创建”**后,Azure 可能需要几分钟来创建资源。
创建文本分析服务
创建文本分析资源后,导航至**“密钥和端点”**,将密钥和端点详细信息复制到记事本中。
⚠️请注意,密钥和端点不应透露给未经授权的人,因为它们可能会影响你的 azure 消费成本。如果您不小心泄露了密钥,请重新生成密钥。
现在,您已经完成了 Azure 门户部分,可以导航到 Power BI。
密钥和端点在 Power BI 集成中发挥着重要作用,确保它们的安全
步骤 2:电源 BI 集成
打开 Power BI desktop 的一个新实例>>从 Excel 导入数据>>浏览样本数据文件> >宾果! 您在 Power BI 中导入了数据集,离可视化世界又近了一步。
功率 BI 的新实例
使用步骤 1 中的 APIKey 和 Endpoint 链接,并替换下面 M 查询脚本中的占位符,这基本上有助于执行对 Azure 的 API 调用。这里需要知道的另一个重要参数是语言:“en”,它可以调整为包括 20 多种语言(印地语、汉语、德语、法语等等)。
电源 BI 集成的 m 查询代码
现在继续并选择 Get data>>Blank query(这将导航到 Power Query editor)> >粘贴 M 查询代码(包含替换的 API 键和端点链接)
在 Microsoft Power BI 中创建空白查询
在超级查询编辑器中粘贴您的 M 查询
这将是一个🔦将" Query1" 重命名为类似于**“情绪 API”**的有意义的东西是个好主意。通过右键单击左侧窗格或直接在右侧窗格的名称字段中进行编辑。
现在,在 power query 编辑器中导航到数据集,在 Add Column section > >下选择**“调用自定义函数”> >** 添加列名=情绪,从下拉列表中选择函数 query,并将文本作为带有反馈的列“答案”> >按 OK。
在超级查询编辑器中配置自定义函数
这将调用 Azure API 并创建一个新列,展开列“情绪”,并将 3 个新创建的列(正、中、负)的数据类型更改为**“整数”**。虽然您可以保持十进制格式,但我建议将它们改为整数,因为这有助于更好地显示它们。现在你可以点击“保存&关闭”,让力量 BI 发挥它的魔力!🎉
积极、中立和消极情绪栏
在您最终进入可视化之前,创建一个新的计算列将是有用的,该列可用于提供切片器以便于过滤。您可以使用下面的 DAX 公式将所有内容整理成一列。
**Overall Sentiment = IF(Responses[Sentiment.positive]=1,"Positive",IF(Responses[Sentiment.neutral]=1,"Neutral",IF(Responses[Sentiment.negative]=1,"Negative","NA")))**
步骤 3: Power BI 可视化
现在你准备好想象了📊信息。我建议使用以下方法:
- 一个水平切片器,通过正向、负向和中性 来过滤情绪。
- 按周、月或年表示情绪趋势的条形图。
- 一些表情符号代表观众的感觉和情绪。
- 一个表格,提供所有要关联的原始数据字段和*“导出到 Excel”*。
- 明确 AI 模型局限性的免责声明。
*作为一个预测性的人工智能模型,这可能不是 100%准确地表达情感,但它确实有助于提供可操作的见解和更快的决策,从而提供指示性的情感。#责任#透明度。
最后但同样重要的是,您还可以添加条件格式,以确保颜色模式与情感相匹配。
这里有一个 Power BI 模板示例,您可以将其用作起点。 情感分析 Azure + Power BI 集成 DEMO.pbix
Microsoft Power BI 中的情感分析可视化演示
输出
通过切分过滤器,你可以看到 Azure 文本分析资源在执行情感分析方面是多么有效。例如,类似于**【良好会话】** 和精彩事件】 的反馈被正确分类为正面😃类似的反馈如***【很多问题】*** 被正确归类为负面😞。**
正面情绪的 Azure 文本分析输出
针对负面情绪的 Azure 文本分析输出
结论
我们学到了📘如何使用 Microsoft Azure Text Analytics 进行情感分析,以及如何在 Microsoft Power BI 中集成分析以开发可视化。
您可以使用其他数据集并定制代码,看看什么最适合您的用例!
发现了一种不同的情感分析方法?请放在评论里!
参考
[3]数据来源:作者手工编制
深度学习在水产养殖中的应用分析
深度计算机视觉保护海洋,可持续地养活人类
通过追踪水中的物体来解释进食行为— 礼貌潮汐
为什么要花时间让水产养殖变得更聪明?🤯
对鱼作为肉类来源的需求平均每年增长 6%,这使得鱼成为肉类行业增长最快的食品。自 21 世纪初以来,这一需求已经翻了一番,如果目前的增长率保持不变,到 2050 年将再翻一番。
养鱼业一直在扩大,通过增加设施内的鱼的数量来满足这种需求。然而,随着鱼群越来越密集,它们的生活质量会下降。
保持高质量的生活需要满足以下需求:
- 低比率的海虱(鲑虱)感染
- 低水平的压力荷尔蒙皮质醇
- 食物的理想水平(以及定时送餐)
- 合适的生物量大小
- 维护良好的网状网将鱼围在里面(将捕食者挡在外面)
- 谨慎的水质平衡
- 低发病率
不幸的是,随着渔场枯竭,生活质量呈指数下降。这是因为这些因素与空间之间的关系(空间越小=越容易传播海虱、疾病等)。)
为什么这会使养鱼场受益?💰
- 饲养成本占渔业收入的 60%。不合理的喂养可能是收入的一个重要因素 de Verdal 等人,2017
- 手动选择特征是一种费力的启发式方法,其效果高度依赖于运气和经验(Mohanty 等人,2016 年)
- DL 模型在弱光和高噪声等挑战性条件下表现出很强的稳定性,并且比传统的人工特征提取方法表现更好(Sun 等人,2018)
我们如何执行?🤔
大多数养鱼场几乎没有技术支持,预算也很紧张。因此,任何解决方案都必须易于安装且成本低廉。
我们的深度学习解决方案只需要一件设备——一台集成了测量仪器的相机。养鱼场中心的一个井位仪器可以收集和汇总监测上述七个生活质量指标所需的所有数据。当这些指标组合在一起时,还可以产生一个养鱼场的整体健康值,代表一个整体的一览式健康评级。
使用上述聚合数据和计算机视觉,我们可以开发以下深度学习应用:
- 海虱检测
- 鱼类的行为分析
- 动态鱼食欲估计和递送
- 生物量测量
- 网格完整性监控
- 水质监测和控制
- 疾病识别和预防
深度学习流水线架构
为什么这种方法在✅行得通
在进入应用程序之前,让我们简要分析一下目前为止的所有情况:
- 我们可以在七个不同的应用中利用单个设备的汇总数据——每个应用都致力于鱼类生活质量的一个关键因素
- 每个应用程序都使用类似的深度学习技术,但会产生一个独特的报告值,养鱼者可以据此采取行动
- 七个输出可以组合在一个最终的深度学习应用中,该应用代表农场的整体健康状况
现在想象一下,这七个指标、相关测量值和整体健康评估通过一个漂亮的仪表板实时显示出来!📈
应用程序
1.海虱检测🐟
弗朗切斯科·温加罗在 Unsplash 上的照片
它解决的问题
全世界的渔场都遭受海虱的侵扰。这些寄生虫附着在鱼类宿主身上,以它们的皮肤/血液为食。渔场越密集,海虱就越容易传播。
它是如何解决问题的
苛刻的化学处理已经成为去除海虱最常见的方法。虽然化学处理能有效去除海虱,但对鱼有不良影响。它还可以防止鲑鱼在排毒的几周内被出售。
一种深度学习解决方案利用卷积神经网络(CNN)和计算机视觉在海虱传播到其他鱼类之前检测/识别它们,使农民能够采取行动,例如(什么,移动鱼群或暂时降低密度?)在海虱的临界种群水平引发一场彻底的化学冲刷之前。
摘要
海虱会对商业渔场造成灾难性的破坏。如果不加以控制,鱼会因寄生虫引起的病变而无法出售,在某些极端情况下,虱子也会导致鱼死亡。使用深度学习系统进行早期预防可以防止有害化学物质,并控制虱子数量。
2.鱼类的行为分析🦈
它解决的问题
微小的环境变化会迅速增加鱼类的压力水平,从而增加它们体内压力荷尔蒙皮质醇的数量。皮质醇会改变鱼的味道,并对消费者产生负面影响。
它是如何解决问题的
IdTracker.ai 模型利用两种不同的 CNN 来提供跟踪小型和大型群体中所有个体鱼类行为的能力——允许农民检测与皮质醇增加相关的行为异常。然而,挑战仍然是巨大的,因为跟踪单个鱼的行为涉及非刚性变形,低图像质量和频繁的遮挡。
赵等人(2018a)展示了另一种解决方案,该方案利用改进的运动影响图和递归神经网络(RNNs) 系统地检测、定位和识别鱼群中的异常行为。
摘要
鱼类对其环境中最小的变化,如溶解氧、藻类、浮游植物等,反应迅速。如果鱼类受到压力,它们会产生皮质醇,影响鱼肉质量。分析行为和鱼类游泳模式有助于农民做出更明智的决定。
相关引用: Saberioon 等人,2017 , Papadakis 等人,2012 , Romero-Ferrero 等人,2019 ,赵等人,2018a
3.鱼类食欲检测🐡
它解决的问题
没有任何指标比养鱼更能反映生产效率和养殖成本。喂养占一般养鱼场运营预算的 60%。
喂食不足会大幅降低鱼类繁殖/生物量增长率,而过度喂食会造成成本浪费和周围水环境污染。
它是如何解决问题的
确定最佳的喂食时间和喂食量是一项挑战。传统上,农民使用简单的计时器和直观的经验来做出决定——这没有考虑重要的环境和营养因素。
包含视觉信息、水测量和关于鱼对过去喂食的反应的历史数据的汇总数据可以与 3D-CNN 和 RNN 模型相结合,以适应时间/空间数据流,从而大大提高喂食效率。Maloy 等人利用这种双重网络方法来选择最佳喂食时间,以说明喂食和非喂食行为。
摘要
很多水产养殖场的投饵时间都是随机的。一些农民凭直觉使用饲料。当这种情况发生时,鱼可能会吃得过多或过少。过度使用饲料会导致成本浪费和环境污染,并且喂养不足会降低生长速度。通过检测食欲,农民可以控制何时喂鱼。
相关引用:mloy 等(2019) ,陈等,2017
4.生物量估计🐠
它解决的问题
估算生物量是可持续管理养鱼场的基础,因为它能让农民了解当前鱼的数量、大小和重量。这些至关重要的数据点也推动了与喂养和行为管理相关的决策。
在没有人类干预的情况下,测量生物量可能具有挑战性,因为鱼类在光照和能见度条件无法控制的环境中自由移动。根据鱼的深度,需要考虑不同程度的遮挡和光线变化。
它是如何解决问题的
两种可能的解决方案可以结合起来精确估计生物量:
- 训练深度学习算法,理解声纳和光学图像之间的映射
- 分割单个鱼的图像,随着时间的推移跟踪它们,并使用帧内对象的深度通过鱼的变化连续估计体积和重量。
摘要
估计生物量有助于农民对鱼的大小、质量和重量做出更好的决定。目前,这一过程是手动完成的,并且是劳动/成本密集型的。自动化这一过程将节省农民的时间和金钱。
相关引用:寺山等人,2019 ,摩恩等人,2018 ,张等人,2020
5.网格完整性检测🐙
网格检测—由 Petrov 等人提供。
它解决的问题
特别设计的网状网将养殖的鱼围在一个封闭的区域内,确保它们的安全/健康。逃离农场的养殖鱼对农场和附近的生态系统将是灾难性的。
它是如何解决问题的
目前,潜水员执行“网完整性检查”,他们戴着水肺在农场周围检查网的节点是否有磨损的迹象。雇用专业潜水员或拥有潜水设备可能是一个艰巨/昂贵的过程。
被训练来识别网中的节点的深度学习神经网络可以容易地创建用于网状网的放置和监控的规则。
摘要
目前的峡湾和其他水产养殖网可以打破。如果发生这种情况,成千上万的鱼将逃到附近的环境中,破坏生态系统。潜水员目前例行检查网状网,但自动检测网破将节省农场很多钱,并拯救海洋免受进一步的伤害。
6.预测水质🐋
它解决的问题
高水平的溶解氧(DO)和其他自然元素会降低压力和疾病水平,并提高繁殖水平。质量监测需要长期精确测量与水中元素相关的参数。
它是如何解决问题的
深度学习在短期和长期水质监测方面都取得了很大的成果,使用配备注意力的长短期记忆网络(LSTMs)和 RNNs 来捕获/预测与水元素相关的时间序列信息。
摘要
正如上面提到的那一段,鱼对最小的水质变化如溶解氧都会有反应。整个养殖场保持稳定的水质对于鱼类的长期健康至关重要。
7.缺陷鱼丸检测🐳
它解决的问题
事实证明,食品缺陷的检测、识别和定位在食品生产中极具挑战性。对于鱼片来说,血斑有损品质,降低市场价值。人工分类方法已经不能满足现代工业的需要。现代工业需要一种稳健、快速、有效、自动化、非侵入性和低成本的方法来分类正常和有缺陷的鱼片。
它是如何解决问题的
米西米等人使用预先训练的 CNN 和 SVM 模型对血斑进行精确分割和定位,并对有缺陷的鳕鱼片进行分类。本研究提出了一种新的数据扩充方法,该方法降低了 CNN 对形状的敏感性,并且只关注颜色特征来区分正常和有缺陷的鱼片。3D 信息用于定位血斑并计算相关的抓取向量,作为机器人处理的输入。
摘要
鱼丸中的缺陷可能对它们的健康有害,并降低它们的市场价值。自动检测有缺陷的鱼颗粒的过程对鱼来说是健康的。
其他研究领域
- 自动疾病识别和检测
- 浮游植物和藻类水华检测
- 温度预测
- 用于公海自主探测的水下机器人
- 叶绿素 A 含量预测
- 海洋生态系统中的障碍和闭塞避免
月球快照摘要🌒
海洋是人类的宝贵资源。它覆盖了 70%的土地,为地球上大部分地区提供食物、氧气和生计。水产养殖只是改善海洋健康的一个方面。如果我们作为研究人员仅仅用一台照相机就可以做这么多来改善海洋,想象一下当我们把我们的大脑和研究用于海洋面临的其他问题时,我们可以取得什么样的成就?
“人们可以下定决心实现看似不可能的神奇想法,并通过科学和技术将其变为现实,然后激发其他人去做其他看似不可能的事情。”—天文泰勒
使用 Twitter 分析抖音常用俚语
我们如何在 Python & Tableau 上使用情感分析和主题建模来发现俚语的含义和用法
图片由作者提供— Tableau 仪表板
近年来,抖音在全球范围内一直呈上升趋势,特别是在 1997 年至 2015 年出生的 Z 世代人口中。像 LOL (笑出声来) ROFL (笑得在地上打滚) FOMO (害怕错过)这些俚语是我们大多数人都知道的,但是抖音的崛起带来了另一套俚语吗?事实上,根据 TheSmartLocal (新加坡领先的旅游和生活方式门户网站),有 9 个抖音俚语被认为是 Z 世代孩子常用的。平台上正在使用的 bussin ,no cap&sheesh等词汇是指什么?像 bestie , fax *,*或者 slaps 这样的常见英文单词,意思还一样吗?
这篇文章解释了 9 个俚语的意思,以及如何在对话中使用它们。在本文中,我们将从数据科学的角度来分析这些俚语,我们将使用 Python 来进行一些自然语言处理(NLP)技术,如情感分析和主题建模。这将使我们更好地了解通常与俚语一起使用的一些关联单词,信息的情感,以及与这些单词一起讨论的话题。
资料组
我们将利用另一个社交媒体平台 Twitter,在一个月内,包含 9 个俚语中任何一个的推文将被捕获,这将形成我们的整个数据集。Python twitter
上的 Twitter 公共 API 库允许我们在获得消费者密钥和访问令牌的身份验证后收集过去 7 天的 tweets。一旦我们初始化了与 Twitter 的连接,我们就设置了纬度、经度的最大区域范围,并将搜索查询设置为俚语词。由于我对提取新加坡用户的推文感兴趣,所以我将地理位置设置为新加坡。最喜爱的计数和转发计数也是从 Twitter 上收集的。
# import libraries
from twitter import *
import pandas as pd
from datetime import datetime# store the slang words in a list
slangs = ['fax', 'no cap', 'ceo of', 'stan', 'bussin', 'slaps', 'hits different', 'sheesh', 'bestie']# twitter authentication
consumer_key = '...'
consumer_secret = '...'
access_token = '...'
access_token_secret = '...'
twitter = Twitter(auth = OAuth(access_token, access_token_secret, consumer_key, consumer_secret))# set latitude & longitude to Singapore, maximum radius 20km
latitude = 1.3521
longitude = 103.8198
max_range = 20# loop through each of the slang
for each in slangs:
# extract tweets with query containing the planning area; note max count for standard API is 100
query = twitter.search.tweets(q = each, geocode = "%f,%f,%dkm" % (latitude, longitude, max_range),\
lang = 'en', count = 100)
# once done, loop through each tweet
for i in range (0, len(query['statuses'])):
# store the planning area, tweet, created time, retweet count & favorite count as a list variable
temp_list = [each, query['statuses'][i]['text'],\
datetime.strptime(query['statuses'][i]['created_at'], '%a %b %d %H:%M:%S %z %Y').strftime('%Y-%m-%d'),\
query['statuses'][i]['retweet_count'], query['statuses'][i]['favorite_count']]
# append list to tweets dataframe
tweets.loc[len(tweets)] = temp_list
数据清理/令牌化
由于收集的推文是原始形式,包含用户名、表情符号和标点符号等单词,因此有必要进行数据清理以删除它们。我们将首先把所有的大小写转换成小写,过滤掉单个单词的回答,删除标点符号/网址/链接。
# function to clean column, tokenize & consolidate into corpus list
def column_cleaner(column, slang_word):
# convert all to lower case and store in a list variable
corpus = column.str.lower().tolist()
# filter off single word responses, 'nil', 'nan'
corpus = [x for x in corpus if len(x.split(' ')) > 1]
corpus = [x for x in corpus if x != 'nan']
corpus = [x for x in corpus if x != 'nil']
# remove punctuations, links, urls
for i in range (len(corpus)):
x = corpus[i].replace('\n',' ') #cleaning newline “\n” from the tweets
corpus[i] = html.unescape(x)
corpus[i] = re.sub(r'(@[A-Za-z0–9_]+)|[^\w\s]|#|http\S+', '', corpus[i])
然后我们扩展上面的函数column_cleaner
,将 tweets(来自RegexpTokenizer
函数)标记为单个单词,移除停用词(来自nltk
包)/数字,并使用词性(来自WordNetLemmatizer
函数)执行词条化。
# empty list to store cleaned corpus
cleaned_corpus = []
# extend this slang into stopwords
stopwords = nltk.corpus.stopwords.words("english")
stopwords.extend([slang_word])
# tokenise each tweet, remove stopwords & digits & punctuations and filter to len > 2, lemmatize using Part-of-speech
for i in range (0, len(corpus)):
words = [w for w in tokenizer.tokenize(corpus[i]) if w.lower() not in stopwords]
cleaned_words = [x for x in words if len(x) > 2]
lemmatized_words = [wordnet_lemmatizer.lemmatize(x, pos = 'v') for x in cleaned_words]
cleaned_corpus.extend(lemmatized_words)
return cleaned_corpus
整个功能将在我们收集的 tweets 数据集上运行,每条 tweets 将被标记化,然后我们将能够在我们的可视化软件(即 Tableau)上绘制出与俚语相关的前 n 个单词。
# loop through each slang word
for each in slangs:
# filter dataframe to responses with regards to this slang word
temp_pd = tweets.loc[tweets.slang == each, :]
# save result in temp pandas dataframe for easy output
temp_result = pd.DataFrame(columns = ['slang', 'word'])
# run column_cleaner function on the tweets
temp_result['word'] = column_cleaner(temp_pd['tweets'], each)
# add slang to slang column
temp_result['slang'] = each
# append temp_result to result
result = result.append(temp_result, ignore_index = True)
图片由作者提供—运行 column_cleaner 函数后的 excel 输出
情感分析/极性得分
我们可以利用 Python 包textblob
进行简单的情感分析,其中如果极性得分> 0 ,我们会将每条推文标记为正,如果极性得分< 0 ,则标记为负,否则标记为中性。请注意,在我们进行情感分析之前,不需要运行上述函数column_cleaner
,因为textblob
包可以直接从原始推文中提取极性得分。
from textblob import TextBlob# empty list to store polarity score
polarity_score = []
# loop through all tweets
for i in range (0, len(tweets)):
# run TextBlob on this tweet
temp_blob = TextBlob(tweets.tweets[i])
# obtain polarity score of this tweet and store in polarity_score list
# if polarity score > 0, positive. else if < 0, negative. else if 0, neutral.
if temp_blob.sentiment.polarity > 0:
polarity_score.append('Positive')
elif temp_blob.sentiment.polarity < 0:
polarity_score.append('Negative')
else:
polarity_score.append('Neutral')
# create polarity_score column in tweets dataframe
tweets['polarity_score'] = polarity_score
作者提供的图片—进行情感分析后的 excel 输出
主题建模
接下来,我们编写一个函数,可以对我们的推文进行主题建模。主题建模是一种统计建模,用于发现文档集合中出现的抽象“主题”。我们将使用常见的潜在狄利克雷分配(LDA)算法,该算法用于将文档中的文本分类到特定主题,我们可以在sklearn
库包中找到它。在我们的函数中,我们还将使用单个标记生成二元模型和三元模型,以及每个俚语词的前 3 个主题。
from sklearn.decomposition import LatentDirichletAllocation
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.pipeline import make_pipeline# function to conduct topic modelling
def topic_modeller(column, no_topic, slang_word):
# extend this slang into stopwords
stopwords = nltk.corpus.stopwords.words("english")
stopwords.extend([slang_word])
# set up vectorizer that remove stopwords, generate bigrams/trigrams
tfidf_vectorizer = TfidfVectorizer(stop_words = stopwords, ngram_range = (2, 3))
# set the number of topics in lda model
lda = LatentDirichletAllocation(n_components = no_topic)
# create a pipeline that vectorise and then perform LDA
pipe = make_pipeline(tfidf_vectorizer, lda)
# run the pipe on the cleaned column
pipe.fit(topic_column_cleaner(column, slang_word))
# inner function to return the topics and associated words
def print_top_words(model, feature_names, n_top_words):
result = []
for topic_idx, topic in enumerate(model.components_):
message = [feature_names[i] for i in topic.argsort()[:-n_top_words - 1:-1]]
result.append(message)
return result
return print_top_words(lda, tfidf_vectorizer.get_feature_names(), n_top_words = 3)
图片由作者提供—进行主题建模后的 excel 输出
数据可视化/分析
一旦我们准备好数据集,我们就可以将我们的发现绘制到数据可视化软件上,即 Tableau。由于本文更多地关注收集数据和生成我们的见解所需的步骤,我将不讨论我是如何设法将我的发现绘制到 Tableau 上的。可以参考我的 Tableau 公众号上的 Tableau 仪表盘。
让我们以俚语单词 sheesh 为例,我们可以将 Tableau 仪表板过滤到该俚语,整个仪表板将被刷新。使用 iPhone 线框作为用户过滤器的想法是不是很酷?
图片由作者提供—文字过滤器的表格截图
2021 年 8 月期间,在新加坡共收集了 173 条推文,我们的极性得分显示,31.8%的推文是正面的,47.4%是中性的,20.8%是负面的。这似乎表明俚语 sheesh 更多地带有中性到积极的意思。
图片由作者提供—情绪分析的 Tableau 截图
在我们的 Python 代码中,我们对 tweet 进行了标记,这样我们就可以根据单词在所有包含俚语单词的 tweet 中的出现频率对它们进行排序。我们的视觉化显示,像 *like、schmuck、*和 sembab (在印尼语中是肿胀的意思)这样的词似乎暗示 sheesh 被用来进一步加剧某事的影响。
作者提供的图片—前 5 个关联单词的表格截图
查看 3 个建模的主题,我们的假设是被用来加剧某事的影响,这在渴望 murtabak、和可爱女孩等主题中得到了进一步的暗示。**
图片由作者提供—主题建模的 Tableau 截图
事实上,根据 TheSmartLocal 的文章,单词 sheesh 与 damn 的用法相似,都是表示不相信或恼怒。如果我们看我们的一些推文,Sheesh渴求 murtabakSheesh*【他是一个幸运的人】做暗示的意思。*
结尾注释
我希望这篇文章是有趣的,并给你们一些关于自然语言处理技术如情感分析和主题建模如何帮助我们更好地理解我们的一系列文档(即我们的推文)的想法。玩 Tableau 仪表板玩得开心,整理仪表板真的很有趣, 没有大写 sheesh !
使用 Azure 机器学习和健康文本分析分析 COVID 医学论文
思想和理论
如何最大限度地利用人工智能,以便从海量文本语料库中提取见解
作者图片
自从 COVID 疫情开始以来,已经有超过 70 万篇关于这个主题的科学论文发表了。人类研究人员不可能熟悉如此庞大的文本语料库,因此非常需要人工智能的帮助。在这篇文章中,我们将展示如何从科学论文中提取一些知识,获得洞察力,并构建一个工具来帮助研究人员以有意义的方式浏览论文集。在这个过程中,我们还会遇到一些对数据科学家有用的云工具。
如果您想继续下去,自己做这个实验,您可以在这里找到所有源代码和分步说明:
http://github.com/CloudAdvocacy/AzurePaperExplorationWorkshop
如果要引用这段文字,请使用arXiv:2110.15453【cs。CL] 。
自动纸张分析
自动科学论文分析是快速发展的研究领域,并且由于 NLP 技术的最近改进,在最近几年中已经有了很大的改进。在本帖中,我们将向您展示如何从 COVID 论文中获得具体的见解,例如医学治疗随时间的变化,或使用几种药物的联合治疗策略。
我将在这篇文章中描述的主要方法是从文本中提取尽可能多的半结构化信息,然后将其存储到某个 NoSQL 数据库中以供进一步处理。将信息存储在数据库中将允许我们进行一些非常具体的查询来回答一些问题,以及为医学专家提供可视化探索工具以进行结构化搜索和洞察生成。提议系统的整体架构如下所示:
作者图片
我们将使用不同的 Azure 技术来深入了解纸质语料库,如 健康文本分析 、 CosmosDB 和 PowerBI 。现在,让我们关注该图的各个部分,并详细讨论它们。
如果你想自己尝试文本分析,你需要一个 Azure 账户。如果你没有免费试用版https://azure.microsoft.com/free/?OCID=AID3029145&WT.mc_id=aiml-20447-dmitryso,你可以随时获得。而且你可能还想为开发者查阅 其他 AI 技术 。
COVID 科学论文和 CORD 数据集
将自然语言处理方法应用于科学文献的想法似乎很自然。首先,科学文本已经是结构良好的了,它们包含关键词、摘要以及定义明确的术语。因此,在 COVID 疫情的最开始,一个 研究挑战已经在 Kaggle 上启动,以分析关于该主题的科学论文。这场比赛背后的数据集被称为CORD(publication),它包含了与 COVID 相关的主题中发布的所有内容的不断更新的语料库。
该数据集由以下部分组成:
- 元数据文件 Metadata.csv 在一个地方包含所有出版物的最重要信息。该表中的每篇论文都有唯一的标识符
cord_uid
(事实上,一旦你真正开始使用数据集,它并不完全是唯一的)。这些信息包括:出版物名称、期刊、作者、摘要、出版日期、doi - ****全文论文在
document_parses
目录下,用 JSON 格式的结构化文本表示,这大大简化了分析。 - 预构建的文档嵌入**,它将
cord_uid
映射到反映论文整体语义的浮点向量。**
在本帖中,我们将关注论文摘要,因为它们包含了论文中最重要的信息。然而,对于数据集的完整分析,在全文上使用相同的方法肯定是有意义的。
AI 能用文字做什么?
近年来,自然语言处理领域取得了巨大的进步,已经训练出了非常强大的神经网络语言模型。在 NLP 领域,通常会考虑以下任务:
- 文本分类/意图识别— 在这个任务中,我们需要将一段文本分成若干类别。这是一个典型的分类任务。
- 情感分析— 我们需要返回一个数字,显示文本的积极或消极程度。这是一个典型的回归任务。
- 命名实体识别(NER)——在 NER,我们需要从文本中提取命名实体,并确定它们的类型。例如,我们可能在寻找药品名称或诊断。另一个类似于 NER 的任务是关键词提取。
- 文本摘要— 这里我们希望能够产生原始文本的简短版本,或者选择最重要的文本片段。
- 问答— 在这个任务中,我们被给予一段文字和一个问题,我们的目标是从文字中找到这个问题的确切答案。
- 开放领域问答(ODQA)——与之前任务的主要区别在于,我们得到了一个大的文本语料库,我们需要在整个语料库的某个地方找到我们问题的答案。
在我之前的一篇文章 中,我描述了我们如何使用 ODQA 方法自动找到特定 COVID 问题的答案。然而,这种方法不适合严肃的研究。
要从文本中获得一些见解,NER 似乎是最突出的技巧。如果我们能够理解文本中存在的特定实体,我们就可以在文本中执行语义丰富的搜索,回答特定的问题,并获得不同实体共现的数据,找出我们感兴趣的特定场景。
为了训练 NER 模型以及任何其他神经语言模型,我们需要一个适当标记的相当大的数据集。找到这些数据集通常不是一件容易的事情,为新的问题领域生成数据集通常需要最初的人工努力来标记数据。
预先训练的语言模型
幸运的是,现代的 变压器语言模型 可以使用迁移学习以半监督的方式进行训练。首先,基础语言模型(例如, BERT )首先在大型文本语料库上训练,然后可以在较小的数据集上专门用于特定的任务,例如分类或 NER。
该迁移学习过程还可以包含额外的步骤——在特定领域数据集上进一步训练通用预训练模型。例如,在医学科学领域,微软研究院使用 PubMed 知识库中的文本,预先训练了一个名为PubMed Bert(publication)的模型。如果我们有一些专门的数据集可用,那么这个模型可以进一步用于不同的特定任务。
文本分析认知服务
然而,除了数据集之外,训练模型还需要大量的技能和计算能力。微软(以及其他一些大型云供应商)也通过 REST API 提供一些预先训练好的模型。这些服务被称为 认知服务 ,其中一个处理文本的服务被称为 文本分析 。它可以执行以下操作:
- ****关键词提取和 NER 用于一些常见的实体类型,如人、组织、日期/时间等。
- 情感分析
- 语言检测
- 实体链接,通过自动添加互联网链接到一些最常见的实体。这也执行了歧义消除,例如火星既可以指行星也可以指巧克力棒,正确的链接将根据上下文使用。**
例如,让我们来看看通过文本分析分析的一篇医学论文摘要:
作者图片
正如你所看到的,一些特定的实体(例如,HCQ,它是羟氯喹的缩写)根本没有被识别出来,而其他的则分类很差。幸运的是,微软提供了特别版的 健康文本分析 。
健康文本分析
面向健康的文本分析是一种认知服务,它公开了预训练的 PubMedBERT 模型以及一些附加功能。以下是使用健康文本分析从同一段文本中提取实体的结果:
作者图片
要执行分析,我们可以使用最新版本的 文本分析 Python SDK ,我们需要先安装:
pip install azure.ai.textanalytics
该服务可以分析一堆文本文档**,一次最多 10 个。您可以传递文档列表或字典。假设我们在txt
变量中有一个摘要文本,我们可以使用下面的代码来分析它:**
poller **=** client.begin_analyze_healthcare_entities([txt])
res **=** list(poller.result())
**print**(res)
在进行这个调用之前,您需要创建
TextAnalyticsClient
对象,传递您的端点和访问键。你从认知服务/文本分析 Azure 资源中获得这些价值,你需要通过门户或命令行在你的 Azure 订阅中创建这些价值。
除了实体列表之外,我们还会得到以下内容:
- 实体映射实体到标准医学本体,如https://www.nlm.nih.gov/research/umls/index.html。
- 文本内部实体之间的关系,如
TimeOfCondition
等。 - 否定,表示实体用于否定语境,例如新冠肺炎诊断没有发生。**
作者图片
除了使用 Python SDK,还可以直接使用 REST API 调用文本分析。如果您使用的编程语言没有相应的 SDK,或者如果您更喜欢接收 JSON 格式的文本分析结果以便进一步存储或处理,这将非常有用。在 Python 中,这可以通过使用requests
库轻松完成:
**uri **=** f"{endpoint}/text/analytics/v3.1/entities/
health/jobs?model-version=v3.1"
headers **=** { "Ocp-Apim-Subscription-Key" : key }
resp **=** requests.post(uri,headers**=**headers,data**=**doc)
res **=** resp.json()
**if** res['status'] **==** 'succeeded':
result **=** t['results']
**else**:
result **=** None**
生成的 JSON 文件将如下所示:
**{"id": "jk62qn0z",
"entities": [
{"offset": 24, "length": 28, "text": "coronavirus disease pandemic",
"category": "Diagnosis", "confidenceScore": 0.98,
"isNegated": **false**},
{"offset": 54, "length": 8, "text": "COVID-19",
"category": "Diagnosis", "confidenceScore": 1.0, "isNegated": **false**,
"links": [
{"dataSource": "UMLS", "id": "C5203670"},
{"dataSource": "ICD10CM", "id": "U07.1"}, ... ]},
"relations": [
{"relationType": "Abbreviation", "bidirectional": **true**,
"source": "#/results/documents/2/entities/6",
"target": "#/results/documents/2/entities/7"}, ...],
}**
****注意:在生产中,您可能希望包含一些代码,以便在服务返回错误时重试操作。有关正确实现认知服务 REST 客户端的更多指导,您可以 查看 Azure Python SDK 的源代码 ,或者使用 Swagger 生成客户端代码。
并行处理所有文件
****由于数据集目前包含 80 万篇论文摘要,通过文本分析按顺序处理它们将非常耗时,可能需要几天时间。要并行运行这段代码,我们可以使用 Azure Batch 或者Azure Machine Learning等技术。它们都允许您创建一个相同虚拟机的集群,并在所有虚拟机上并行运行相同的代码。
作者图片
Azure 机器学习是一项旨在满足数据科学家所有需求的服务。它通常用于培训和部署模型和 ML 管道;但是,我们也可以使用它在一个计算集群上运行我们的并行扫描作业。为此,我们需要提交一个sweep_job
实验。
有几种方法可以使用 Azure ML 并提交实验:
- 通过 Azure 门户进行交互。这可能最适合初学者,但不容易复制或记录。
- 使用Azure ML Python SDK。它允许你通过代码定义一个实验的所有属性,然而,Python 代码似乎有很多样板文件。
- 从 命令行 ,使用 YAML 文件 来定义参数。这是目前推荐的方法。
- 来自Visual Studio Code Azure ML Extension—它本质上与上面的方法非常相似,但是 VS Code 通过提供自动完成选项来帮助您简化所有配置文件的创作,它还可以为您提交命令。
首先,我们需要创建一个 Azure 机器学习工作区,以及一个运行实验的集群。这是通过 Azure CLI 完成的:
******$** az ml workspace create -w AzMLWorkspace -l westus -g MyGroup
**$** az ml compute create –n AzMLCompute --size Standard_NC
--max-node-count 8****
我们还需要将我们的 CORD 数据集上传到 Azure ML 中。我们首先用 YAML 文件data_metacord
定义数据集:
****name: metacord
version: 1
local_path: Metadata.csv****
然后我们将数据集上传到云端:
******$** az ml data create -f data_metacord.yml****
我们还需要定义脚本运行的环境。环境本质上是一个容器,可以通过指定一个起始容器并在其上应用一些附加配置来定义。这里,我们在env.yml
中定义一个环境:
****name: cognitive-env
version: 1
docker:
image: mcr.microsoft.com/azureml/base:intelmpi2018.3-ubuntu16.04
conda_file:
file:./cognitive_conda.yml****
我们从一个标准的 Azure ML Ubuntu 容器开始,并在cognitive_conda.yml
中指定额外的 Python 依赖项:
****channels:
- conda
dependencies:
- python=3.8
- pip
- pip:
- azure-cosmos
- azure.ai.textanalytics
- requests****
我们通过跑步来创造环境
****az ml environment create -f env.yml****
为了定义一个清扫任务,我们将使用下面的 YAML 文件sweepexp.yml
:
****experiment_name: sweep_experiment
algorithm: grid
type: sweep_job
search_space:
number:
type: choice
values: [0,1,2,3,4,5,6,7]
trial:
command: python process.py
--number {search_space.number}
--nodes 8
--data {inputs.metacord}
inputs:
metacord:
data: azureml:metacord:1
mode: download
code:
local_path: .
environment: azureml:cognitive-env:1
compute:
target: azureml:AzMLCompute
max_concurrent_trials: 8
timeout_minutes: 10000****
这里我们用整数参数number
定义一个搜索空间,取值从 0 到 7。我们允许最多 8 个并发运行,每个运行将包括调用process.py
脚本,向其传递数据集的命令行参数,并发运行的总数和单独运行--number
,其范围从 0 到 7。
注意,我们还在这里指定了环境名和计算机名。如果您使用带有 Azure ML 扩展的 Visual Studio 代码来创建这些脚本,您可以使用自动完成(按 Ctrl-Space)来填充字段的名称和必需的值(如可用的计算名称、容器名称等)。)自动。
处理逻辑将编码在 Python 脚本中,大致如下:
****## process command-line arguments using ArgParse
…
df = pd.read_csv(args.data) # Get metadata.csv into Pandas DF## Connect to the database
coscli **=** azure.cosmos.CosmosClient(cosmos_uri, credential**=**cosmoskey)
cosdb **=** coscli.get_database_client("CORD")
cospapers **=** cosdb.get_container_client("Papers")## Process papers
**for** i,(id,x) **in** enumerate(df.iterrows()):
if i%args.nodes == args.number: # process only portion of record
# Process the record using REST call (see code above)
# Store the JSON result in the database
cospapers.upsert_item(json)****
为了简单起见,我们不会在这里展示完整的脚本
使用 CosmosDB 存储分析结果
使用上面的代码,我们获得了一个论文集合,每个论文都有许多实体和对应关系。这种结构本质上是分层的,存储和处理它的最佳方式是使用 NoSQL 方法进行数据存储。在 Azure 中, Cosmos DB 是一个通用数据库,可以存储和查询类似我们的 JSON 集合的半结构化数据,因此将所有 JSON 文件上传到 Cosmos DB 集合是有意义的。上面显示的代码演示了如何从并行运行的处理脚本中将 JSON 文档直接存储到 CosmosDB 数据库中。
作者图片
我们假设您已经创建了一个名为“CORD”的 Cosmos DB 数据库,并获得了进入
cosmos_uri
和cosmoskey
变量所需的凭证。
运行完这段代码后,我们将以容器Papers
结束所有元数据。我们现在可以在 Azure Portal 中使用这个容器,方法是转到数据浏览器:
作者图片
现在我们可以使用 Cosmos DB SQL 来查询我们的集合。例如,下面是我们如何获得语料库中所有药物的列表:
***-- unique medication names*
**SELECT** **DISTINCT** e.text
**FROM** papers p
**JOIN** e **IN** p.entities
**WHERE** e.category**=**'MedicationName'**
使用 SQL,我们可以制定一些非常具体的查询。假设,一位医学专家想要找出一种特定药物的所有建议剂量(比如说羟氯喹),并查看所有提到这些剂量的论文。这可以使用以下查询来完成:
***-- dosage of specific drug with paper titles*
**SELECT** p.title, r.source.text
**FROM** papers p **JOIN** r **IN** p.relations
**WHERE** r.relationType**=**'DosageOfMedication'
**AND** r.target.text **LIKE** 'hydro%'**
更困难的任务是选择所有实体以及它们相应的本体 ID。这将是非常有用的,因为最终我们希望能够引用一个特定的实体(羟氯喹),而不管它在论文中被提及的方式(例如, HCQ 也指同一种药物)。我们将使用 UMLS 作为我们的主要本体。
***--- get entities with UMLS IDs*
**SELECT** e.category, e.text,
ARRAY (**SELECT** VALUE l.id
**FROM** l **IN** e.links
**WHERE** l.dataSource**=**'UMLS')[0] **AS** umls_id
**FROM** papers p **JOIN** e **IN** p.entities**
创建交互式仪表板
虽然能够使用 SQL 查询来获得一些特定问题的答案,如药物剂量,似乎是一个非常有用的工具——但对于没有很高 SQL 掌握水平的非 it 专业人员来说,这并不方便。为了使医疗专业人员能够访问元数据集合,我们可以使用 PowerBI 工具来创建一个用于实体/关系探索的交互式仪表板。
作者图片
在上面的例子中,您可以看到不同实体的仪表板。用户可以在左侧选择所需的实体类型(例如,本例中的药物名称,并在右侧观察该类型的所有实体及其数量。您还可以在表格中看到相关的 IDs in,并且从上面的例子中可以注意到几个实体可以引用同一个本体 ID ( 羟氯喹和 HCQ )。
要制作这个仪表盘,我们需要使用 PowerBI 桌面 。首先,我们需要导入 Cosmos DB 数据——这些工具支持从 Azure 直接导入数据。
作者图片
然后,我们提供 SQL 查询来获取具有相应 UMLS id 的所有实体——如上所示——以及另一个查询来显示所有唯一的类别。然后我们将这两个表拖到 PowerBI 画布上,得到上面显示的仪表板。该工具自动理解两个表由一个名为类别的字段链接,并支持基于第一个表中的选择过滤第二个表的功能。
同样,我们可以创建一个工具来查看关系:
作者图片
从这个工具中,我们可以进行类似于上面在 SQL 中进行的查询,以确定特定药物的剂量。为此,我们需要在左侧表格中选择药物剂量关系类型,然后根据我们想要的药物过滤右侧表格。还可以创建进一步的下钻表格,以显示提及选定药物剂量的特定论文,使该工具成为医学科学家的有用研究工具。
获得自动洞察
然而,故事最有趣的部分是从文本中得出一些自动的见解,例如随着时间的推移医疗策略的变化。为此,我们需要用 Python 编写更多的代码来进行适当的数据分析。最方便的方法是使用嵌入 Cosmos DB 的笔记本:
作者图片
那些笔记本支持嵌入式 SQL 查询;因此,我们能够执行 SQL 查询,然后将结果放入 Pandas DataFrame,这是 Python 固有的数据浏览方式:
****%%sql** *--database CORD --container Papers --output meds*
**SELECT** e.text, e.isNegated, p.title, p.publish_time,
ARRAY (**SELECT** VALUE l.id **FROM** l
**IN** e.links
**WHERE** l.dataSource**=**'UMLS')[0] **AS** umls_id
**FROM** papers p
**JOIN** e **IN** p.entities
**WHERE** e.category **=** 'MedicationName'**
这里我们以meds
数据框架结束,包含药物名称,以及相应的论文标题和出版日期。我们可以根据本体 ID 进一步分组,以获得不同药物的提及频率:
**unimeds **=** meds.groupby('umls_id') \
.agg({'text' : **lambda** x : ','.join(x),
'title' : 'count',
'isNegated' : 'sum'})
unimeds['negativity'] **=** unimeds['isNegated'] **/** unimeds['title']
unimeds['name'] **=** unimeds['text'] \
.apply(**lambda** x: x **if** ',' **not** **in** x
**else** x[:x.find(',')])
unimeds.sort_values('title',ascending**=**False).drop('text',axis**=**1)**
这为我们提供了下表:
作者图片
从该表中,我们可以选择 15 种最常提及的药物:
**top **=** {
x[0] : x[1]['name'] **for** i,x **in** zip(range(15),
unimeds.sort_values('title',ascending**=**False).iterrows())
}**
为了了解药物的提及频率如何随时间变化,我们可以计算每月提及次数的平均值:
***# First, get table with only top medications* imeds **=** meds[meds['umls_id'].apply(**lambda** x: x **in** top.keys())].copy()
imeds['name'] **=** imeds['umls_id'].apply(**lambda** x: top[x])*# Create a computable field with month* imeds['month'] **=** imeds['publish_time'].astype('datetime64[M]')*# Group by month* medhist **=** imeds.groupby(['month','name']) \
.agg({'text' : 'count',
'isNegated' : [positive_count,negative_count] })**
这为我们提供了一个数据框架,其中包含每个月对药物的正面和负面提及次数。从那里,我们可以使用matplotlib
绘制相应的图形:
**medh **=** medhist.reset_index()
fig,ax **=** plt.subplots(5,3)
**for** i,n **in** enumerate(top.keys()):
medh[medh['name']**==**top[n]] \
.set_index('month')['isNegated'] \
.plot(title**=**top[n],ax**=**ax[i**//**3,i**%**3])
fig.tight_layout()**
作者图片
可视化术语共现
另一个有趣的发现是观察哪些术语经常一起出现。为了可视化这种依赖关系,有两种类型的图表:
- 桑基图允许我们调查两类术语之间的关系,例如诊断和治疗
- 弦图有助于可视化同类型术语的共现(例如,哪些药物被一起提及)
为了绘制这两个图,我们需要计算共现矩阵,该矩阵在行i
和列j
中包含术语i
和j
在同一摘要中的共现次数(可以注意到这个矩阵是对称的)。我们计算的方法是为我们的本体手动选择相对少量的术语,如果需要,将一些术语组合在一起:
**treatment_ontology **=** {
'C0042196': ('vaccination',1),
'C0199176': ('prevention',2),
'C0042210': ('vaccines',1), ... }diagnosis_ontology **=** {
'C5203670': ('COVID-19',0),
'C3714514': ('infection',1),
'C0011065': ('death',2),
'C0042769': ('viral infections',1),
'C1175175': ('SARS',3),
'C0009450': ('infectious disease',1), ...}**
然后,我们定义一个函数来计算由这些本体字典指定的两个类别的共现矩阵:
****def** **get_matrix**(cat1, cat2):
d1 **=** {i:j[1] **for** i,j **in** cat1.items()}
d2 **=** {i:j[1] **for** i,j **in** cat2.items()}
s1 **=** set(cat1.keys())
s2 **=** set(cat2.keys())
a **=** np.zeros((len(cat1),len(cat2)))
**for** i **in** all_papers:
ent **=** get_entities(i)
**for** j **in** ent **&** s1:
**for** k **in** ent **&** s2 :
a[d1[j],d2[k]] **+=** 1
**return** a**
这里,get_entities
函数返回论文中提到的所有实体的 UMLS id 列表,而all_papers
是返回论文摘要元数据完整列表的生成器。
为了实际绘制桑基图,我们可以使用 Plotly 图形库。这个过程在 这里 有很好的描述,不再赘述。结果如下:
作者图片
作者图片
用 Plotly 绘制和弦图并不容易,但可以用一个不同的库— Chord 来完成。主要思想保持不变——我们使用上述相同的函数构建共现矩阵,传递相同的本体两次,然后将该矩阵传递给Chord
:
****def** **chord**(cat):
matrix **=** get_matrix(cat,cat)
np.fill_diagonal(matrix,0)
names **=** cat.keys()
Chord(matrix.tolist(), names, font_size **=** "11px").to_html()**
治疗类型和药物的弦图结果如下:
************
作者图片****
右图显示了哪些药物被一起提及(在同一摘要中)。我们可以看到那些众所周知的组合,如羟氯喹+阿奇霉素,清晰可见。
结论
在这篇文章中,我们描述了一个用于从大型医学文本语料库中提取知识的概念验证系统的架构。我们使用 Text Analytics for Health 来执行从文本中提取实体和关系的主要任务,然后一些 Azure 服务一起为医学科学家构建查询并提取一些视觉洞察。这个帖子目前还是概念性的,可以通过在 PowerBI 模块中提供更详细的下钻功能,以及对提取的实体/关系集合进行更多的数据探索来进一步改进系统。切换到处理全文也会很有意思,在这种情况下,我们需要考虑术语共现的稍微不同的标准(例如,在同一段落与同一篇论文中)。
同样的方法可以应用于其他科学领域,但我们需要准备训练一个定制的神经网络模型来执行实体提取。这个任务已经在上面简要地描述过了(当我们谈到 BERT 的使用时),我将在我的下一篇文章中集中讨论它。同时,如果你正在做类似的研究,或者对代码和/或方法有任何具体的问题,请随时联系我。
分析熊猫的数据
当熊猫脱颖而出
一年前,如果你问我是否认为有比使用 Excel 更好的方法来分析表格数据,我可能会摇头说“没有”,我职业生涯的前 8 年一直在提高我的 Excel 技能,从初级到高级,在公司财务部门担任各种角色。会计部门是一个很好的例子,说明微软 Excel 或谷歌 Sheets 在利用 Python 的 Pandas 软件包方面表现突出,因为它对非技术人员来说更加用户友好,并且易于创建报告,如账户对账。当你开始从一个更程序化的任务转向一个更深入的分析任务时——这就是我认为熊猫脱颖而出的地方。
探索数据
当你收到一个很大的 Excel 文件时,除非你有很多外部构建的 VBA 宏或其他插件,否则你需要大量的跑腿工作和 Excel 公式来熟悉这些数据。Pandas 用两行非常简单的代码解决了这个难题: df.info() 和 df.describe()。
**#importing pandas**
import pandas as pd**#reading in tabular data of All-NBA teams**
df = pd.read_csv('../Data/YoY_Analysis.csv', index_col = 0)**#selecting needed columns**
df = df[['YEAR','All_NBA', 'PLAYER', 'TEAM', 'Age', 'PTS', 'AST', 'TRB']]**#showing the first 5 rows of data**
df.head()
数据帧图像
**#pandas code giving statistical information for all numerical columns**
df.describe()
数据框架统计信息
**#pandas code showing count of all columns and data types**
df.info()
数据帧信息
如前所述,导入数据后,仅用两行简单的代码,我们现在就有了所有数字数据的统计数据,包括 IQR 的和每列的数据类型。我们不需要编写公式来计算每一列的最小值/最大值/平均值等,并且 df.info 还向我们显示,我们的数据集中有一些缺失的信息,如 TRB 的 699 非空计数所示——总反弹。经过研究,这是由于 NBA 直到 1951 年才正式追踪篮板。
重塑
Excel 为它提供了一个非常有用的数据透视表工具和用户友好的 GUI,但是它不允许您改变数据的形状,除非您在完成数据透视表的构建后选择全部并对其进行硬编码。Pandas 提供了两个内置函数来帮助重塑/聚合你的数据集: Groupby & Pivot_Table。
几乎在我最初探索数据集的任何时候,我都倾向于使用 groupby ,因为它快速、简单,并且在你想要开始创建视觉效果时非常有用。让我们再来看看我们的数据集,但假设我们对 NBA 球队每年的平均数据感兴趣。
**#creating a new dataframe aggregating average stats per year**
annual_averages = df.groupby('YEAR')['PTS', 'AST','TRB'].mean()annual_averages.head()
分组数据帧
我们现在也可以很容易地绘制这些数据,显示平均值随时间的变化。这使我们能够快速识别 1999 年停摆缩短赛季,导致只有 50 场常规赛正在进行。
annual_averages.plot()
Groupby 和 pivot_table 在熊猫身上的表现非常相似。主要区别在于 pivot_table 允许在行和列上进行聚合。让我们通过旋转数据,然后绘制图表,来看看所有 NBA 球队的统计平均值。
pivot = df.pivot_table(df[['AST', 'PTS', 'TRB']], **#selecting columns**
index = 'All_NBA', **#selecting index**
aggfunc = np.mean, **#selecting aggregate function**
margins = True ) **#column totals** pivot
数据框架数据透视表
pivot.plot(kind ='bar)
数据透视表绘图
结论
如上所示,在探索数据时,Pandas 是一个令人惊叹的工具。只需几行非常简单的代码,您就可以开始理解您正在处理的数据集。这个库还可以提供更多的东西,但是我希望这个快速浏览能够在下次您收到一个大的 Excel 文件并被要求提供分析见解时有所帮助。
分析巴黎迪士尼乐园游客对公园和酒店的评论—第一部分
对超过 12 万篇猫途鹰评论的探索性数据分析和主题建模📝
我们对巴黎迪士尼乐园的所有英文评论的词频
介绍
巴黎迪斯尼乐园是世界上最著名的娱乐胜地之一。它有两个公园,里面有表演、特技和游行、特别活动、人物和游乐设施。它还有几家酒店和餐厅,在 Tripadvisor 上排名第三。
准备好享受巴黎迪士尼乐园的神奇时光吧!
是出现在该公司网站上的第一句话之一,总的来说,这种交流似乎旨在与家人或朋友一起享受一种独特的体验。
有了一点关于该公司的背景和大量来自猫途鹰的评论,让我们试着,没有特定的期望,一起发现留下评论的访问者对它说了些什么。
关于我们的数据集
在开始分析之前,我们需要了解一些关于数据的细节。我们的数据集由迪士尼乐园和酒店的 12 万条 Tripadvisor 点评组成。它们于 2021 年 3 月 12 日在被提取。
迪士尼乐园
- 巴黎迪士尼乐园→ 41k 评论
- 朴华特·迪士尼工作室→ 16k 评论
合并成一个 57,799 行(216 MB)的数据集
迪士尼乐园酒店
- 迪士尼乐园酒店***** → 8k 评论
- 迪士尼纽约酒店**** → 8k 评论
- 迪士尼新港湾俱乐部**** → 8k 评论
- 迪士尼的红杉小屋*** → 12k 评论
- 迪士尼夏延酒店** → 11k 评论
- 迪士尼的大卫·克洛科特牧场→ 7k 评论
- 迪士尼圣达菲酒店** → 10k 点评
组合成一个 65,250 行(217 MB)的数据集
迪士尼乐园自然度假村
- 巴黎自然村****→ 3k 点评
分析巴黎迪士尼乐园🎢
本文将只关注公园评论*(巴黎迪士尼乐园和华特·迪士尼工作室)*。
为什么你会问?因为有更多的酒店*(其中七家)和评论包含更多的领域,如子评级(清洁度、睡眠质量、房间、服务、价值)*,我们必须从某个地方开始!
欢迎留下任何评论和反馈,如果你喜欢这篇文章,我们可以在第二部分再写一篇关于酒店的文章😉。现在,我们将分两步来尝试从我们的评论数据集中获得最大的收益。
探索性数据分析(EDA)
我们首先探索我们的数据集,并试图得出有趣的见解,如:
- 游客满意度
- 情绪随时间变化
- 响应时间和速率
文本分析和话题发现
我们有一堆像样的评论,我们希望了解访问者留下的文字内容*(主要通过提取不同的话题或主题)*。为此,我们将关注以下内容:
- 评论长度、表情符号和语言
- 词频和 N 元语法
- 使用 LDA 和 NMF 进行主题建模
既然一切都准备好了,让我们开始吧!
探索性数据分析
每月有多少评论?
Tripadvisor 创建于 2000 年,巴黎迪士尼乐园创建于 1992 年。华特·迪士尼工作室公园在 2002 年晚些时候开放。
从下图中,我们可以看到访客真正开始分享和写评论是从 2010 年开始的。
2004 年至 2021 年每月审查次数
观察到大多数峰值对应于 6 月到 8 月这一段时间非常有趣,而且有明显的季节性。
从 2019 年初开始,我们观察到下降的趋势,自 2020 年 3 月新冠肺炎疫情开始以来,几乎没有评论留下。
此外,通过计算巴黎迪士尼乐园和工作室公园之间的 CORR()函数,我们看到两条线具有 97% 的相关性,这意味着它们具有相同的游客评论季节性和趋势。
我们可以问自己一些问题,为什么冬天没有季节性🎃或者圣诞节🎄)?或者,如何解释 2019 年评论的持续减少?
SQL 提示
Tripadvisor API 以字符串类型格式返回日期,如下所示 2016–03–17t 12:40:44–04:00。为了解析它,我们在 BigQuery 中使用 PARSE_TIMESTAMP()函数。
总体评分和一段时间内的平均评分
除了留下书面文字,访问者还可以从 0 到 5 颗星评价他们的体验,我们将其转换为可读的标签。
按评分分组的评论(1-5 星)
在我们所有的评论中,报道的都是总体而言的美好体验。
对于这两个公园,游客的体验更有可能是优秀或非常好。
总的来说,游客似乎真的很享受这种体验,但这种体验会随着时间的推移而改善吗?
让我们使用一个季度的平均评分,可能从 2012 年开始,因为从今年开始,访问者开始留下很多评论。
平均评分和季度间的相对变化
不要让图表的比例产生误导。我们看到的平均评分在 3.7 到 4.3 星之间,这仍然是一个很小的区间。我们可以把这个图分成两部分,在 Q1 2018 年奥运会之前的 T36 和之后的 T38。
之前,似乎从 2012 年的到 2018 年的,平均评分正在超过的 4 星,其中最大的下降是从的 2016 年到 2016 年第三季度,平均评分从下降到的 3.95 星。
同样引人注目的是,从 2018 年第三季度到 2020 年 Q1持续下降,达到最低评级之一。
SQL 提示
为了获得季度,我们使用带有季度参数的 TIMESTAMP_TRUNC()函数。此外,我们正在利用 BigQuery 中 LAG()函数的功能计算相对变化。
让我们尝试一种不同的可视化方式,使用绿色-琥珀色-红色指示器*(基本上将我们的评级转换为阴性-中性-阳性指示器)*。
红色-琥珀色-绿色指示器,用于季度评审
在 2021 年 Q1 奥运会上,只有 8 条评论,这甚至没有显示在我们的规模上,但正如我们在第一张图表上看到的(每月评论)我们从 2017 年底到 2021 年 3 月有下降趋势,这意味着正面评论的数量也在减少,占总评论的比例更小。
响应速度和响应时间
评论可以由猫途鹰页面所有者回答,在这种情况下,是巴黎迪士尼团队。我想到的一个指标是响应率和响应时间。
巴黎迪士尼团队于 2016 年底开始在 Tripadvisor 上为各公园解答问题。他们在回答大多数评论方面有一个很好的开始,至少三个季度的回答率在 40%到 60%之间,然后这个比率急剧下降。
总的来说,巴黎迪士尼乐园的平均回答率为 **15%。**这意味着 Tripadvisor 上剩下的 100 条点评中,只有 15 条会得到回复。
响应时间呢?
以天为单位的响应时间的百分比
中值为 3 天,16 天后得到答案的可能性较小。除了这张表,平均回答时间是 5,7 天。
SQL 提示
为了统计一个季度中的回答数量,我们将 owner_response 字段转换为布尔值 1 或 0。然后,我们可以使用 SUM()函数在单个查询中对其进行聚合。
文本分析和主题发现
我们分析的第二部分将更加关注我们的访问者在这些评论中表达了什么*(我们将尽力找出答案*👀 ) 。
我们将使用不同的技术来帮助我们发现应该深入探究的话题、主题或问题。由于我们不知道这些评论中包含了什么,我们将使用大多数无人监管的方法来探索和发现。
评论长度、表情符号和语言
单纯出于好奇,我们来看看每次评论的字数有没有什么规律。为此,我们统计了一篇评论的字数,并在几个月和几年内进行平均。
一段时间内的平均审核长度
平均来说,我们的访问者每次评论使用 550 到 800 个字符。随着时间的推移,它看起来相当平坦,没有什么真正突出的。
表情符号能给我们一些有趣的暗示吗?这里需要注意的是,只有**1.7%**的评论包含表情符号,这在我们的评论数据集中所占的份额非常低。
查看不同评级中最常用的表情符号,我们可以看到 4-5 星的表情符号与爱、笑和幸福有关,1-2 星的表情符号与金钱、愤怒和困惑有关。
SQL 提示
表情符号是从每个评论中提取的。它们以字符串格式存储在 BigQuery 中,用两个方括号封装: [😎,🎉]
为了解析这个字段,我们使用 JSON_EXTRACT_STRING_ARRAY()将我们的字符串转换成一个单值数组。解析逗号分隔值列表非常有用。
来自世界各地的游客参观巴黎迪士尼乐园,因此,评论可能会用许多不同的语言编写。
在所有评论中,我们观察到五种主要语言。
大多数人的评论都是用英语写的。这可能代表美国、加拿大或英国等国家。
法国是第二大代表国家,紧随其后的是意大利和西班牙。
为了进行我们的主题分析,我们将只保留英文评论,这些评论仅占我们数据集的 41% ,这意味着我们将错过来自其他国家和语言的其他观点或想法。
字频率
词频是一种测量给定文本中最频繁出现的单词或概念的技术。然后,我们将它们显示为单词云,以帮助区分最具代表性的单词。
在我们的例子中,我们从评论中删除了一些词,如*、或、以及所有停用词(、、、【他们】、、、【你的】、、、【我们】、*等)
我们对巴黎迪士尼乐园的所有英文评论的词频
例如,这里我们看到单词*、、、*在我们的评论集中出现得最多。很难确切说出它暗示了什么,但值得注意。
让我们尝试应用相同的方法,但将其分为**正面(4-5 星)和负面(1-2 星)**评论,看看我们是否能注意到每个子集中的特定单词。
正面评价在左边是绿色,负面评价在右边是红色
我们已经可以注意到,有些词是两个词云共有的,比如*、、、或、【日】、*。我们可以说它们适用于消极或积极的感觉。
因此,我们可以观察到大多数出现在一个或另一个子集中的单词。
- *“时间”、“人员”或“食物”*大多出现在否定集中
- *“人物”、“游行”或“小鬼”*大多出现在正面集合中
这很有趣,但如果脱离上下文,只解释一个词可能会有点困难。我们将试着看看搭配,看看哪些单词通常会出现在一起。
Python 提示
我们没有使用正方形图像格式显示 wordcloud,而是使用了自定义的。PNG 图像来显示米老鼠形状中的单词。wordcloud librairy 允许我们使用“mask”参数来使用任何自定义图像。
搭配/ n-grams
搭配有助于识别共同出现的单词。它有助于识别句子中隐藏的意思。
例如,我们看到*“Rides”这个词被频繁提及。但也许它与其他有意义的词同时出现,如、、、【趣味骑行】。*
再比如,在我们之前的文字云中,我们看到了*【快速】**【通过】这几个字。*在互联网上,我们发现巴黎迪士尼乐园提供了一张通行证,让游客在一些游乐设施上跑得更快。我们可以假设这些单词更有可能一起出现,而不是单独出现。
为了不使陷入过于复杂的分析,我们将看看 bi-gram(两个相邻的词,如*“快传”)和 tri-gram(三个相邻的词,如“大雷山”*)。
我们的 top 按频率找到了二元模型
两个相邻单词的前 20 次出现(双字母组)
有些联想似乎比其他联想更有可能发生,如*、【巴黎迪士尼】、【快速通行证】、、、【过山车】、*。
但也许更有趣的是,我们有“G*o Back”或【值得】*的意思是游客可能愿意回来,因为他们的旅程值得。
另一个*“游乐设施关闭”*可能表示景点经常关闭,这是一个反复出现的话题。
我们的 top 按频率找到了三元组
前 20 个出现的三个相邻单词(三元组)
我们已经看到,这三个词的组合在我们的评论语料库中出现的频率大大降低了。
好像有几个是指向孩子年龄的,像*【6 岁】**【3 岁】或者【4 岁】。*
“*额外魔法时间”*和“*人物走动”*可能是公园提供的有趣功能,值得一看。
三元语法的列表更长,但它们可能不太相关,因为它们出现在更少的评论中。
巨蟒提示
我们使用一个自定义的清理功能来词条化和删除停用词,然后降低和修复编码问题。然后,NLTK librairy 给了我们 ngrams()函数。最后,我们将结果转换成可以在 BigQuery 中接收的数据帧。
主题建模
我们的目标是按照主题自动组织文本。在我们的例子中,我们有一堆评论,我们想弄清楚所有这些评论会产生什么主题。
例如,以下评论可以在一个名为神奇的地方的主题中建模。
- “我对这个神奇的地方爱得无以言表。”
- “真正神奇的体验和物超所值只要你在去哪里吃饭上做足功课,我绝对会再去!”
- “从《料理鼠王》和《海底总动员》这种独一无二的游乐设施来看,一切都很神奇。”
我们将使用两种算法, LDA (潜在狄利克雷分配)和 NMF (非负矩阵分解)来卧底这些话题。
这两种算法的工作原理是,根据评论包含的单词将评论分组,并注意它们之间的相关性。我们使用两种方法来比较发现的主题,即使它们不同,但它们应该会带来相似的结果。
LDA 发现的主题
使用 LDA 发现的主题
- 第一个话题听起来是关于好玩的游乐设施,比如太空山和大雷山
- 第二个话题是关于排队和等待时间。可能相关或由于封闭的游乐设施。
- 第三个话题好像是关于员工抽烟和钱的。
- 第四个主题描述了一次由于游行和迪斯尼人物而带来的神奇和令人惊奇的经历。
- 第五个主题似乎是与酒店和货币价值有关,或者也与烟火和一天中的繁忙时间有关。
要找到对这些主题的清晰解释并不总是容易的,但至少它给出了指示,也许是进一步探索的主题。
NMF 发现的话题
使用 NMF 发现的主题
至于 LDA,这种方法的结果也是主题的形状。
- 第一个话题可能是关于孩子们喜欢游行和见到迪斯尼人物。
- 第二个主题是关于有趣的游乐设施,类似于我们的 LDA 主题,但有替代名称(碾压过山车、恐怖塔、料理鼠王)。
- 第三个好像是关于快速通票和等待时间(小时或分钟之间)。
- 第四个话题与工作人员/演职人员和人有关。
- 第五个话题是关于酒店、餐厅、火车。
Python 提示
在这个例子中,我们使用 python Gensim librairy。LDA 函数提供了足够的参数进行调整,因此我们可以获得良好的结果。这里,提示可以是使用 Sparse2Corpus()函数来转换转换后的评论集。此外,我们使用两个工人来分配计算过程。
我们的下一步是什么?🐭
我们一直在分析关于两个巴黎迪士尼乐园的评论,但看看评论告诉我们关于酒店的什么也是很有趣的。
此外,我们只考虑了英语评论的文本分析部分。我们可以尝试使用不同的图书馆,以包括其他语言,如法语,西班牙语或意大利语的评论。
此外,我们可以针对不同的评级或情绪对文本进行详尽的分析。例如,对我们的正面和负面评论分别应用主题建模方法。
就是这样!我希望你喜欢这篇文章,了解更多关于文本分析的可能性,不要犹豫留下反馈或评论🤓