在 Python 中创建分形
深入几何学、递归算法和三角形……很多很多的!
·
关注 发表在 Towards Data Science ·8 分钟阅读·2023 年 3 月 24 日
–
这是我在今年早些时候拍的一张照片,那天特别阴沉,即使在英格兰也是如此。
分形 是在不同尺度上自相似的无限复杂的图案。例如,树干分裂成更小的枝条。这些枝条进一步分裂成更小的枝条,依此类推。
通过程序生成分形,我们可以将简单的形状转化为复杂的重复图案。
在这篇文章中,我将探讨如何使用一些基本的 A-Level 几何知识和一点编程技巧,在 Python 中构建令人印象深刻的分形。
分形在数据科学中扮演着重要角色。例如,在分形分析中,会评估数据集的分形特征,以帮助理解潜在过程的结构。此外,分形生成中心的递归算法可以应用于广泛的数据问题,从二分查找算法到递归神经网络。
想法
我想写一个可以绘制等边三角形的程序。在三角形的每一边上,它还必须能够绘制一个稍小的外向三角形。它应该能够根据我的需要重复这个过程,希望能创造出一些有趣的图案。
这个粗略的草图展示了我想生成的图案类型。
表示图像
我将把图像表示为一个二维像素数组。像素数组中的每个单元格将表示该像素的颜色(RGB)。
为了实现这一点,我们可以使用库NumPy生成像素数组,并使用Pillow将其转换为可以保存的图像。
蓝色像素的 x 值为 3,y 值为 4,可以通过二维数组 pixels[4][3] 进行访问
绘制直线
现在是时候开始编码了!
首先,我需要一个函数,可以接受两个坐标集并在它们之间绘制一条直线。
以下代码通过在两个点之间进行插值,每一步都向像素数组中添加新的像素。你可以把这个过程想象成逐像素地为一条线着色。
我在每个代码片段中使用了续行符 ‘\’,以便将一些较长的代码行适配进来。
import numpy as np
from PIL import Image
import math
def plot_line(from_coordinates, to_coordinates, thickness, colour, pixels):
# Figure out the boundaries of our pixel array
max_x_coordinate = len(pixels[0])
max_y_coordinate = len(pixels)
# The distances along the x and y axis between the 2 points
horizontal_distance = to_coordinates[1] - from_coordinates[1]
vertical_distance = to_coordinates[0] - from_coordinates[0]
# The total distance between the two points
distance = math.sqrt((to_coordinates[1] - from_coordinates[1])**2 \
+ (to_coordinates[0] - from_coordinates[0])**2)
# How far we will step forwards each time we colour in a new pixel
horizontal_step = horizontal_distance/distance
vertical_step = vertical_distance/distance
# At this point, we enter the loop to draw the line in our pixel array
# Each iteration of the loop will add a new point along our line
for i in range(round(distance)):
# These 2 coordinates are the ones at the center of our line
current_x_coordinate = round(from_coordinates[1] + (horizontal_step*i))
current_y_coordinate = round(from_coordinates[0] + (vertical_step*i))
# Once we have the coordinates of our point,
# we draw around the coordinates of size 'thickness'
for x in range (-thickness, thickness):
for y in range (-thickness, thickness):
x_value = current_x_coordinate + x
y_value = current_y_coordinate + y
if (x_value > 0 and x_value < max_x_coordinate and \
y_value > 0 and y_value < max_y_coordinate):
pixels[y_value][x_value] = colour
# Define the size of our image
pixels = np.zeros( (500,500,3), dtype=np.uint8 )
# Draw a line
plot_line([0,0], [499,499], 1, [255,200,0], pixels)
# Turn our pixel array into a real picture
img = Image.fromarray(pixels)
# Show our picture, and save it
img.show()
img.save('Line.png')
当我让这个函数在像素数组的每个角落之间绘制一条黄色直线时的结果
绘制三角形
现在我有了一个可以在两个点之间绘制直线的函数,是时候绘制第一个等边三角形了。
给定三角形的中心点和边长,我们可以使用方便的公式计算高度:h = ½(√3a)。
现在,利用这个高度、中心点和边长,我可以确定三角形的每个角落应该在哪里。使用我之前制作的plot_line函数,我可以在每个角落之间绘制一条直线。
def draw_triangle(center, side_length, thickness, colour, pixels):
# The height of an equilateral triangle is, h = ½(√3a)
# where 'a' is the side length
triangle_height = round(side_length * math.sqrt(3)/2)
# The top corner
top = [center[0] - triangle_height/2, center[1]]
# Bottom left corner
bottom_left = [center[0] + triangle_height/2, center[1] - side_length/2]
# Bottom right corner
bottom_right = [center[0] + triangle_height/2, center[1] + side_length/2]
# Draw a line between each corner to complete the triangle
plot_line(top, bottom_left, thickness, colour, pixels)
plot_line(top, bottom_right, thickness, colour, pixels)
plot_line(bottom_left, bottom_right, thickness, colour, pixels)
在 500x500 像素的 PNG 图像中心绘制一个三角形的结果
生成分形
一切就绪。几乎所有需要的条件都已经准备好,可以在 Python 中创建我的第一个分形了。真令人兴奋!
然而,这最后一步可以说是最棘手的。我希望我们的三角形函数能够对每条边调用自身。为了使其有效,我需要能够计算每个新小三角形的中心点,并正确地旋转它们,使其与附加的边垂直。
通过从我希望旋转的坐标中减去中心点的偏移量,然后应用旋转坐标对的公式,我们可以使用此函数旋转三角形的每个角。
def rotate(coordinate, center_point, degrees):
# Subtract the point we are rotating around from our coordinate
x = (coordinate[0] - center_point[0])
y = (coordinate[1] - center_point[1])
# Python's cos and sin functions take radians instead of degrees
radians = math.radians(degrees)
# Calculate our rotated points
new_x = (x * math.cos(radians)) - (y * math.sin(radians))
new_y = (y * math.cos(radians)) + (x * math.sin(radians))
# Add back our offset we subtracted at the beginning to our rotated points
return [new_x + center_point[0], new_y + center_point[1]]
一个我们将每个坐标旋转了 35 度的三角形
现在我可以旋转三角形,我必须将注意力转向在第一个三角形的每一边上绘制一个新的、更小的三角形。
为了实现这一点,我扩展了draw_triangle函数,以计算每条边的新三角形的旋转和中心点,新三角形的边长由参数shrink_side_by减少。
一旦计算出新三角形的中心点和旋转角度,它会调用draw_triangle(它自身)来从当前线的中心绘制新的、更小的三角形。这将再次触发相同的代码块,计算另一个更小三角形的中心点和旋转角度。
这称为递归算法,因为我们的draw_triangle函数现在会调用自身,直到达到我们希望绘制的三角形的max_depth。重要的是要有这个逃逸条件,否则函数理论上会无限递归(但实际上调用堆栈会变得过大,导致栈溢出错误)!
def draw_triangle(center, side_length, degrees_rotate, thickness, colour, \
pixels, shrink_side_by, iteration, max_depth):
# The height of an equilateral triangle is, h = ½(√3a)
# where 'a' is the side length
triangle_height = side_length * math.sqrt(3)/2
# The top corner
top = [center[0] - triangle_height/2, center[1]]
# Bottom left corner
bottom_left = [center[0] + triangle_height/2, center[1] - side_length/2]
# Bottom right corner
bottom_right = [center[0] + triangle_height/2, center[1] + side_length/2]
if (degrees_rotate != 0):
top = rotate(top, center, degrees_rotate)
bottom_left = rotate(bottom_left, center, degrees_rotate)
bottom_right = rotate(bottom_right, center, degrees_rotate)
# Coordinates between each edge of the triangle
lines = [[top, bottom_left],[top, bottom_right],[bottom_left, bottom_right]]
line_number = 0
# Draw a line between each corner to complete the triangle
for line in lines:
line_number += 1
plot_line(line[0], line[1], thickness, colour, pixels)
# If we haven't reached max_depth, draw some new triangles
if (iteration < max_depth and (iteration < 1 or line_number < 3)):
gradient = (line[1][0] - line[0][0]) / (line[1][1] - line[0][1])
new_side_length = side_length*shrink_side_by
# Center of the line of the traingle we are drawing
center_of_line = [(line[0][0] + line[1][0]) / 2, \
(line[0][1] + line[1][1]) / 2]
new_center = []
new_rotation = degrees_rotate
# Amount we need to rotate the traingle by
if (line_number == 1):
new_rotation += 60
elif (line_number == 2):
new_rotation -= 60
else:
new_rotation += 180
# In an ideal world this would be gradient == 0,
# but due to floating point division we cannot
# ensure that this will always be the case
if (gradient < 0.0001 and gradient > -0.0001):
if (center_of_line[0] - center[0] > 0):
new_center = [center_of_line[0] + triangle_height * \
(shrink_side_by/2), center_of_line[1]]
else:
new_center = [center_of_line[0] - triangle_height * \
(shrink_side_by/2), center_of_line[1]]
else:
# Calculate the normal to the gradient of the line
difference_from_center = -1/gradient
# Calculate the distance from the center of the line
# to the center of our new traingle
distance_from_center = triangle_height * (shrink_side_by/2)
# Calculate the length in the x direction,
# from the center of our line to the center of our new triangle
x_length = math.sqrt((distance_from_center**2)/ \
(1 + difference_from_center**2))
# Figure out which way around the x direction needs to go
if (center_of_line[1] < center[1] and x_length > 0):
x_length *= -1
# Now calculate the length in the y direction
y_length = x_length * difference_from_center
# Offset the center of the line with our new x and y values
new_center = [center_of_line[0] + y_length, \
center_of_line[1] + x_length]
draw_triangle(new_center, new_side_length, new_rotation, \
thickness, colour, pixels, shrink_side_by, \
iteration+1, max_depth)
三角形分形,shrink_side_by = 1/2 和 max_depth = 2
结果
以下是一些通过修改shrink_side_by和max_depth值输入到我们的draw_triangle函数中可以生成的不同图像示例。
有趣的是,这些大型重复模式通常会创造出更复杂的形状,如六边形,但具有迷人的对称性。
在重复三角形的对称性中,开始出现越来越复杂的形状。
一种类似雪花的分形,使用了修改版的draw_triangle
函数,该函数还绘制了一个朝内的三角形。
另一种创作,使用每次迭代减少的更小的尺寸
除非另有说明,否则所有图片均由作者提供。
结论
分形非常有趣,可以创造出美丽的图案。使用一些简单的概念和一丝创造力,我们可以生成非常令人印象深刻的结构。
在理解分形的核心属性并应用递归算法时,我们创建了一个坚实的基础,这有助于我们理解数据科学中更复杂的分形问题。
随时阅读和下载完整代码这里。如果你发现改进或扩展的方法,请告诉我!
我很好奇你能用不同的形状创造出什么?
使用 Python 的 Plotly 和 Folium 库创建地理空间热图
用于可视化地理空间变化的两个优秀 Python 选项
·发布于 Towards Data Science ·阅读时间 6 分钟·2023 年 3 月 17 日
–
图片由 KOBU Agency 提供,来源于 Unsplash
热图,也称为 密度图,是展示变量在地理区域内空间分布的数据可视化工具。它们是可视化和识别趋势、支持决策、检测异常值以及为演示文稿创建引人注目的可视化的绝佳工具。
有几种 Python 地图绘制库可供选择,然而,两个非常流行且易于使用的库是 Folium 和 Plotly Express。
Folium 是一个很棒的库,它使可视化地理空间数据变得简单。它由 Leaflet.js 提供支持,Leaflet.js 是一个领先的 JavaScript 地图绘制库,且平台无关。 Plotly 是一个流行的库,可以用极少的代码创建强大的交互式数据可视化,并可以与 MapBox 一起创建交互式地图。
在本文中,我们将展示如何使用这两个库在挪威大陆架上可视化声学压缩慢度数据。
使用 Plotly Express 的视频版本教程可以在我的 YouTube 频道找到。请查看下面的链接。
导入库和加载数据
在本教程中,我们将从导入 pandas 开始,这将用于从 CSV 文件中加载数据。
import pandas as pd
我们在本教程中使用的数据集是以下内容的组合:
-
Xeek Force 2020 机器学习岩石学竞赛数据集被用来推导 Shetland Group 的平均声波压缩慢度(DTC)值
-
来自挪威石油局网站的数据,用于提供位置数据
df = pd.read_csv('xeek_force_2020_dtc_mapping.csv')
df
当数据加载完成后,我们可以使用以下方法调用数据框:
挪威大陆架井的数据框视图。图片由作者提供。
我们可以看到我们有 7 列:
-
井名 — 井的名称
-
DTC — Shetland Group 的平均声波压缩慢度
-
温度 — 井底温度
-
水深 — 从海平面到海底的深度
-
完成年份 — 井的完成年份
-
纬度 — 井的纬度位置,单位为十进制度
-
经度 — 井的经度位置,单位为十进制度
使用 Plotly Express 创建热图
要开始使用 Plotly Express 创建热图,我们需要将该库导入到我们的笔记本中,如下所示:
import plotly_express as px
然后我们需要创建一个新的图形。这是通过调用 plotly express 的 density_mapbox
来完成的。
要创建我们的地图,我们需要传入几个参数:
-
df
— 包含数据的数据框名称 -
lat
— 纬度列的名称 -
lon
— 经度列的名称 -
z
— 包含我们希望在热图上可视化的数据的列名称 -
center
— 地图的中心位置。我们可以调用纬度和经度列的均值 -
zoom
— 地图的初始缩放级别
最后两个参数 mapbox_style
和 height
控制背景映射层和图的高度。
fig = px.density_mapbox(df, lat='Latitude', lon='Longitude',
z='DTC', radius=20,
center=dict(lat=df.Latitude.mean(),
lon=df.Longitude.mean()),
zoom=4,
mapbox_style="open-street-map",
height=900)
fig.show()
当我们调用 fig.show()
时,我们会得到以下地图。
使用 plotly express 的 density_mapbox 生成的热图。图片由作者提供。
从这张地图上,我们可以看到该区域北端的 DTC 值较高,这可能归因于几种因素,包括较低的压实度或较高的页岩度。
Plotly express 生成的地图的一个优点是我们可以悬停在数据上并获得绘制变量(DTC)的值。这是自动完成的,无需额外代码来创建弹出框。
使用 plotly express 的 density_mapbox 生成的热图增加了交互性。图片由作者提供。
使用 Folium 创建热图
要开始使用 Folium,我们需要导入它;然而,为了生成热图,我们还需要从folium.plugins
导入 HeatMap 插件。
import folium
from folium.plugins import HeatMap
一旦导入了 Folium,我们需要通过调用 folium.map()
来创建一个基础地图。在该类方法中,我们可以传入几个参数。对于这个例子,我们将使用以下参数:
-
location
— 地图的中心位置 -
zoom_start
— 地图的初始缩放级别 -
control_scale
— 是否在地图上显示比例控制
如果你想了解有关地图函数的参数,可以查看folium.map类的帮助文档。
m = folium.Map(location=[df_combined.Latitude.mean(),
df_combined.Longitude.mean()],
zoom_start=6, control_scale=True)
接下来,我们需要创建热力图图层。
要实现这一点,我们首先需要将纬度、经度和值转换为列表,然后可以传递给HeatMap
调用。
我们可以设置一些参数来美化热力图的外观,例如最小和最大不透明度、数据点的颜色半径等。
map_values = df_combined[['Latitude','Longitude','DTC']]
data = map_values.values.tolist()
hm = HeatMap(data,
min_opacity=0.05,
max_opacity=0.9,
radius=25).add_to(m)
当我们调用我们的地图对象时,我们可以看到与 plotly express 生成的图案类似。
使用 Folium 生成的热力图。图片由作者提供。
然而,这张地图有几个缺点:
没有类似于我们在 Plotly Express 中看到的悬停功能。我们可以添加标记,但这需要几行额外的代码。
如果你想了解如何实现这一点,可以查看我下面的文章。
在 Python 中向 Folium 地图添加标记的简短指南
towardsdatascience.com
另一个问题是没有颜色渐变条来帮助读者理解颜色范围。但可以通过创建颜色映射字典来解决这一问题,具体可以参见以下 StackOverflow 帖子。
我正在使用 Folium 创建热力图。我的数据包含 3 列:类别、纬度和经度。纬度-经度点是…
stackoverflow.com](https://stackoverflow.com/questions/47163728/how-to-add-legend-gradient-in-folium-heat-map?source=post_page-----4159e98a1ae8--------------------------------)
结论
热力图提供了一种出色的方式来可视化和识别地理区域的趋势,并且可以使用两个流行的 Python 库:Folium 和 Plotly Express 轻松创建。这两个库使用简单,可以用于在大范围内绘制岩石物理和井日志属性。从这些地图中,我们可以获得有关领域或区域的趋势和变化的信息。
感谢阅读。在你离开之前,你一定要订阅我的内容,将我的文章发送到你的收件箱。 你可以在这里做到这一点!或者,你可以 注册我的新闻通讯 ,以免费将额外内容直接发送到你的收件箱。
其次,你可以通过注册会员获得完整的 Medium 体验,支持我和其他成千上万的作者。每月仅需 $5,你即可全面访问所有精彩的 Medium 文章,还有机会通过写作赚钱。如果你通过 我的链接**, 你将直接用部分费用支持我,而且不会增加额外费用。如果你这样做了,非常感谢你的支持!
本教程中使用的数据集
本教程使用的数据集由两个其他数据集组成:
-
用于 Xeek 和 FORCE 2020 举办的机器学习竞赛中的训练数据集的一个子集 (Bormann 等人, 2020)。
可以通过以下链接访问完整数据集:
doi.org/10.5281/zenodo.4351155
。 -
来自挪威石油局网站的井位数据
数据可以在这里下载:
factpages.npd.no/en/wellbore/tableview/exploration/all
这两个数据集均根据挪威政府的 NOLD 2.0 许可证授权,详细信息可以在这里找到:挪威开放政府数据许可证 (NLOD) 2.0。
使用 dtreeviz 创建令人惊叹的决策树可视化
原文:
towardsdatascience.com/creating-incredible-decision-tree-visualizations-with-dtreeviz-820c6547b6a9
如何使用这个有用的库可视化决策树模型
·发布于 Towards Data Science ·阅读时长 6 分钟·2023 年 6 月 21 日
–
图片由作者提供,使用 dtreeviz 创建。
在模型可解释性方面,决策树是一些最直观和可解释的模型。每个决策树模型都可以解释为一组人类可解释的规则。能够可视化决策树模型对于模型的可解释性非常重要,并且可以帮助利益相关者和业务经理对这些模型建立信任。
幸运的是,我们可以使用 dtreeviz 库轻松地可视化和解释决策树。在本文中,我将演示如何使用 dtreeviz 可视化用于回归和分类的基于树的模型。
安装 dtreeviz
你可以使用以下命令通过 pip 轻松安装 dtreeviz:
pip install dtreeviz
有关依赖项和可能需要安装的额外库的详细列表,请参阅 这个 GitHub 仓库。
可视化回归树
在本节中,我们将对 糖尿病数据集 训练一个决策树回归器。请注意,你可以在这个 GitHub 仓库中找到本教程的所有代码。请记住,我使用 Jupyter 作为运行 Python 代码的环境。你可以在 这个 GitHub 仓库 中找到我为本教程编写的所有代码。
导入库
在下面的代码块中,我简单地导入了包括 scikit-learn 决策树模块和 dtreeviz 在内的几个常用库。
import numpy as np
import pandas as pd
from sklearn.tree import DecisionTreeClassifier, DecisionTreeRegressor
import dtreeviz
读取数据
糖尿病数据集可在 scikit-learn 中获取,因此我们可以使用以下代码导入数据集,并将特征和目标值存储在名为 X 和 y 的 numpy 数组中。
from sklearn.datasets import load_diabetes
diabetes_data = load_diabetes()
X = pd.DataFrame(data = diabetes_data['data'], columns=diabetes_data['feature_names'])
y = diabetes_data['target']
训练决策树模型
为了使树更容易可视化,我们可以限制决策树的最大深度,并按如下方式对数据进行训练。
dtree_reg = DecisionTreeRegressor(max_depth=3)
dtree_reg.fit(X, y)
可视化树
dtreeviz 的一个关键特点是能够可视化决策树模型。使用下面的代码,我们可以创建一个有趣的决策树可视化,并在每个节点处视觉上描绘决策边界。
viz_model = dtreeviz.model(dtree_reg,
X_train=X, y_train=y,
feature_names=list(X.columns),
target_name='diabetes')
viz_model.view()
糖尿病回归树可视化。图像由作者使用 dtreeviz 创建。
注意上面的可视化还给出了每个节点的决策边界和特征空间,以及每个叶节点的回归输出和样本大小。
可视化叶节点分布
dtreeviz 提供的另一个有用功能是可视化叶节点分布。决策树的叶节点包含根据每组条件预测的实际值。使用rtree_leaf_distributions函数,我们可以为回归树创建这种可视化。
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
%matplotlib inline
viz_model.rtree_leaf_distributions()
根据上面的可视化,我们可以看到决策树可以预测 268.9、208.6、176.9、137.7、154.7、274.0、83.4 或 108.8 作为糖尿病这一目标变量的值。水平分散的点表示糖尿病目标变量值的分布,小黑线表示用于预测该叶节点的平均值。理想情况下,叶节点的分布应具有低方差,以便我们对用于预测的平均值有更高的信心。
可视化叶节点大小
我们还可以可视化叶节点的大小,即每个叶节点的样本数量,如下面的函数所示。
viz_model.leaf_sizes()
根据上面的图,我们可以看到每个叶节点的样本数量。这种可视化是评估我们对回归树预测的信心的良好工具。
可视化分类树
我们还可以使用 dtreeviz 可视化分类树,且这些可视化与回归树创建的效果略有不同。在本节中,我们将使用乳腺癌威斯康星数据集来训练和可视化决策模型。
读取数据
乳腺癌威斯康星数据集在 scikit-learn 中可用,因此我们可以使用下面的代码加载它。
from sklearn.datasets import load_breast_cancer
cancer_data = load_breast_cancer()
X = pd.DataFrame(data = cancer_data['data'], columns=cancer_data['feature_names'])
y = cancer_data['target']
训练决策树模型
如往常一样,使用 scikit-learn 训练决策树模型是简单明了的。我们还可以对最大树深度施加约束,以便更容易可视化决策树。
dtree_clf = DecisionTreeClassifier(max_depth=4)
dtree_clf.fit(X, y)
可视化决策树
我们可以使用回归树部分的完全相同的函数来可视化分类树。不过,可视化效果会略有不同。
viz_model = dtreeviz.model(dtree_clf,
X_train=X, y_train=y,
feature_names=list(X.columns),
target_name='cancer')
viz_model.view()
癌症分类决策树。
注意,以上的分类树可视化与上一节的回归树可视化不同。我们看到的不是每个节点处选定特征和目标的散点图,而是显示每个节点处类别分布的彩色直方图。
可视化叶子分布
我们还可以使用相同的函数可视化回归树的叶子分布的类别分布。
viz_model.ctree_leaf_distributions()
分类树的叶子分布图。图像由作者使用 dtreeviz 创建。
每个叶子都有一个堆叠条形图,展示了该叶子中样本的类别标签分布。大多数叶子中的样本明显属于一个类别,这很好,有助于我们对模型的预测建立信心。
可视化特征空间
我们还可以使用以下函数可视化分类器的特征空间。
viz_model.ctree_feature_space()
上面的特征空间图展示了分类树的训练准确率,以及两个特征的散点图和可以用来区分两个类别的线性决策边界。
摘要
当涉及到可视化基于树的模型时,dtreeviz 是一个强大的库,提供了几个有用的可视化函数。我只介绍了这个库中提供的部分函数,还有许多其他功能,你可以在 dtreeviz GitHub 仓库 中阅读。像往常一样,你可以在 我的 GitHub 上找到这篇文章的所有代码。
加入我的邮件列表
加入我的 邮件列表 来获取关于数据科学内容的更新。当你 注册 时,你还会获得我的免费逐步解决机器学习问题指南!你也可以在 Twitter 上关注我,获取内容更新。
在此过程中,考虑 加入 Medium 社区,阅读成千上万其他作者的文章。
来源
- Terence Parr, dtreeviz: 决策树可视化, (2023), GitHub。
使用 Spark 和 Tableau Desktop 创建富有洞察力的仪表板
使用 Tableau Desktop 工具进行大规模数据可视化自动化
·
关注 发表在 Towards Data Science ·9 min read·2023 年 6 月 29 日
–
作者照片
1. 介绍
作为数据的可视化表示,数据可视化是数据分析中广泛采用的方法,用于从大规模数据集中获得有用的业务洞察(例如,趋势、模式、异常值、关联等)。最近,我介绍了一种使用 Spark、Plotly 和 Dash 开发用于 Web 应用的互动且富有洞察力的数据可视化仪表板的软件开发方法[1]。
类似于 [1],本文使用与 [2] 中相同的开源数据集,展示如何使用 Spark 和 Tableau Desktop [3] 从大规模数据集创建有洞察力的仪表板,而无需编程。
图 1: 工作流的高层次概述。
图 1 显示了工作流的高层次概述。它包括以下主要步骤:
-
将 Tableau Desktop 用于仪表板创作连接到 Spark
-
从 Cloud Data Lake 查询数据集
-
从加载的数据集创建数据可视化图表
-
从创建的单独图表中创建仪表板
-
将仪表板发布到 Tableau 服务器以便共享
2. 连接 Tableau Desktop 到 Spark
如 [4] 所述,以下步骤可以用来使用 Spark SQL 作为分布式查询引擎,通过其 JDBC/ODBC [5] 并将 Tableau Desktop 连接到分布式 Spark SQL 引擎 [4]:
-
安装 Hadoop
-
设置 Hive
-
设置 MySQL
-
设置 Spark
-
设置 Tableau Desktop
3. 从 Cloud Data Lake 查询数据集
一旦 Tableau Desktop 成功连接到分布式 Spark SQL 引擎,我们应该能够浏览默认模式并查看 Hive Hadoop 集群表 [4]。
从使用 Tableau Desktop 创建仪表板的角度来看,从 Hive Hadoop 集群加载的表和从本地 Microsoft Excel 文件加载的表没有区别。为了方便起见,本文将使用 Tableau Desktop Public 的免费版本,并将本地 Excel 文件(该文件由 [2] 中的数据集 csv 文件转换而来)用于演示目的。
4. 创建数据可视化图表
我们需要先创建单独的可视化图表,然后才能创建可视化仪表板。
我们可以使用 Tableau Desktop 创建多种类型的图表。如 [1] 所述,某些图表适合于可视化连续的数值特征,而其他图表适合于可视化离散的分类特征。
类似于 [1],本文使用 Tableau Desktop 创建以下常见图表以用于演示目的。
-
数值特征的图表: 散点图、直方图和折线图
-
分类特征的图表: 条形图、折线图和饼图
4.1 数值特征的图表
Tableau Desktop 使用符号 # 来指示数值特征。本小节展示如何使用 Tableau Desktop 创建以下三种常见的数值特征图表:
-
散点图
-
直方图
-
折线图
4.1.1 散点图
对于一对数值特征,散点图使用每对特征值作为坐标在 2D 平面上绘制一个点。例如,如 [1] 所示,图 2 显示了 21 到 30 岁人群的两个数值特征 Patient ID 和 Admission Deposit 的散点图。特征 Type of Admission 用于颜色编码。
以下步骤可以用来创建散点图:
-
将特征 Patientid 拖动到 Columns 区域
-
拖动特征入院押金并将其放到行货架上。
-
拖动特征入院类型并将其放到标记卡的颜色属性上。
-
点击标记卡上的下拉菜单并选择圆形。
-
右键点击特征年龄,选择显示过滤器,并仅选择21–30。
图 2: 数值特征对的散点图示例。
该散点图揭示了大多数 21–30 岁之间的急诊和创伤患者押金范围在$3,000 到$6,000 之间的商业洞察。
4.1.2 直方图
Tableau Desktop 将直方图视为条形图。因此,列的数值特征需要通过分箱转换为分类特征,而行的数值特征需要聚合,如求和。
可以按照以下步骤创建图 3 中的直方图:
-
右键点击数值特征病人 ID并选择“创建区间”以创建新特征病人 ID(区间)。
-
拖动新的特征病人 ID(区间)并将其放到列货架上。
-
拖动数值特征入院押金并将其放到行货架上,然后点击放置的特征并选择聚合总和。
-
拖动分类特征入院类型并将其放到标记卡的颜色属性上。
-
点击标记卡上的下拉菜单并选择条形图。
-
右键点击特征年龄,选择显示过滤器,并仅选择21–30。
图 3: 数值特征对的直方图示例。
该直方图向我们展示了紧急患者在 21–30 岁之间的总入院押金最少,而急诊患者的总入院押金最多的商业洞察。
4.1.3 折线图
类似于创建散点图,可以按照以下步骤创建图 4 中的折线图:
-
拖动特征病人 ID并将其放到列货架上。
-
拖动特征入院押金并将其放到行货架上。
-
拖动特征入院类型并将其放到标记卡的颜色属性上。
-
点击标记卡上的下拉菜单并选择折线。
-
右键点击特征年龄,选择显示过滤器,并仅选择21–30。
图 4: 数值特征对的折线图示例。
类似于散点图,该折线图显示了相同的商业洞察,即大多数 21–30 岁之间的急诊和创伤患者押金范围在$3,000 到$6,000 之间。
4.2 分类特征的图表
Tableau Desktop 使用符号Abc来表示分类特征。本小节展示如何使用 Tableau Desktop 创建以下三种分类特征值计数的常见图表:
-
条形图
-
折线图
-
饼图
4.2.1 条形图
作为示例,可以按照以下步骤创建图 5 中分类特征Stay的柱状图:
-
拖动特征Stay并将其放到Columns架上。
-
拖动相同的特征Stay并将其放到Rows架上,然后点击已放置的特征并选择聚合Count。
-
点击 Marks Card 上的下拉菜单,选择Bar。
-
右键点击特征Age,选择show filter,仅选择21–30。
-
点击 Marks Card 上的Color属性并选择purple颜色。
图 5: 分类特征值计数的示例柱状图。
该柱状图展示了业务洞察,即对于 21–30 岁之间的患者,更多患者住院时间为 21–30 天,相比其他住院时间间隔。
4.2.2 折线图
类似于柱状图,可以按照以下步骤创建图 6 中分类特征Stay的折线图:
-
拖动特征Stay并将其放到Columns架上。
-
拖动相同的特征Stay并将其放到Rows架上,然后点击已放置的特征并选择聚合Count。
-
点击 Marks Card 上的下拉菜单,选择Line。
-
右键点击特征Age,选择show filter,仅选择21–30。
-
点击 Marks Card 上的Color属性并选择purple颜色。
图 6: 分类特征值计数的示例折线图。
类似于柱状图,这个折线图揭示了相同的业务洞察,即对于 21–30 岁之间的患者,更多患者住院时间为 21–30 天,相比其他住院时间间隔。
4.2.3 饼图
创建饼图的过程不如创建折线图和柱状图那样直接。
我们可以按照以下步骤创建图 8 中分类特征Stay的饼图:
-
拖动特征Stay并将其放到Columns架上。
-
拖动相同的特征Stay并将其放到Rows架上,然后点击已放置的特征并选择聚合Count。
-
右键点击特征Age,选择show filter,仅选择21–30。
-
点击图表上方右角的Show Me,选择pies图标。一个小的pies图将如图 7 所示出现。
-
通过选择 Marks Card 上的Size属性来增加饼图的大小,然后选择并拖动饼图的边界框。
-
拖动聚合功能CNT(Stay)并放到Label属性的 Marks Card 上。
图 7: 将柱状图转换为饼图。
图 8 展示了完成上述步骤后的最终饼图。
图 8: 分类特征值计数的示例饼图。
与条形图和折线图类似,这个饼图确认了相同的业务洞察:对于 21-30 岁之间的患者,住院 21-30 天的患者更多(共 2,197 名),相比于其他住院时间段。
5. 创建仪表板
一旦单独的图表创建完成,我们可以选择并将这些图表组合成一个仪表板。
5.1 用于可视化数值特征对的仪表板
可以按照以下步骤创建一个用于可视化数值特征Patientid和Admission Deposit的仪表板。
步骤 1: 选择仪表板菜单,然后选择新建仪表板
步骤 2: 将以下创建的图表逐一拖动并放置到新的仪表板页面上:
-
数值特征对的示例散点图
-
数值特征对的示例直方图
-
数值特征对的示例折线图
图 9 展示了新创建的仪表板。
图 9: 用于可视化一对数值特征的示例仪表板。
5.2 用于可视化分类值计数的仪表板
可以按照以下步骤创建一个用于可视化分类特征Stay的值计数的仪表板。
步骤 1: 选择仪表板菜单,然后选择新建仪表板
步骤 2: 将以下创建的图表逐一拖动并放置到新的仪表板页面上:
-
categorical_feature_bar
-
categorical_feature_line
-
categorical_feature_pie
图 10 展示了新创建的仪表板。
图 10: 用于可视化分类特征值计数的示例仪表板。
6. 发布仪表板
一旦创建了仪表板,它可以发布到 Tableau Server 以进行共享。
服务器有三种类型:
-
Tableau Public
-
Tableau Server
-
Tableau Cloud
由于使用的是免费的 Tableau Desktop Public 创建这些仪表板,因此这些仪表板只能发布到 Tableau Public。
可以按照[6]中的发布步骤,将仪表板及相关数据集发布到 Tableau Public 服务器上以供公众查看。
7. 结论
Tableau 是一个多层次的视觉数据分析平台,具有复杂的架构。本文介绍了一种将 Spark 与 Tableau 集成的方法,用于首先从大规模数据湖(例如,Hadoop Hive)中查询数据,然后演示如何使用 Tableau Desktop 从加载的数据集中创建有洞察力的仪表板,而无需编程。
作为一个仪表板创建和共享工具,Tableau Desktop 支持多种创建可视化图表的方法。了解从哪里开始以及如何创建有洞察力的可视化图表和仪表板可能会让人感到困惑。本文通过专注于两个简单的可视化场景:一个是可视化一对数值特征,另一个是可视化分类特征的值计数,来帮助快速学习 Tableau Desktop。
参考文献
[1] 黄宇,使用 Spark 和 Plotly Dash 开发互动和洞察性仪表板
[2] 黄宇,预测 Covid-19 患者住院时间
[4] 设置 Tableau 与 Apache Spark 的指南
[5] 分布式 SQL 引擎
[6] 分享你的发现
注意: 本文中的所有照片/图片/图表均由作者提供。
使用 QGIS 创建地图
原文:
towardsdatascience.com/creating-maps-with-qgis-1af81b9d0e73
最佳开源 GIS 软件的全面指南
·发表于 Towards Data Science ·阅读时间 11 分钟·2023 年 12 月 24 日
–
照片由 Louis Hansel 提供,来源于 Unsplash
十多年前,当我开始作为 GIS(地理信息系统)分析师的数据职业生涯时,两款万能的 GIS 软件非常突出。十年后,这两款软件依然是同样的两款。ArcGIS (由 ERSI 提供) 迄今为止仍是最主流的选择,它非常易于使用,功能丰富,并配备了出色的 Python 库。然而,它需要付费,并且仅在 Windows 上运行。
QGIS(量子 GIS)则是最佳的开源替代品。它支持大多数操作系统,并拥有非常活跃的开源社区。无论选择哪款软件,你都不会出错,但随着我深入编程职业,使用 Windows 变得更加困难,因此我通常避免使用企业软件以避免采购行政工作。因此,我现在更倾向于使用 QGIS。
QGIS logo。(CC BY-SA)
以下教程显示的是 QGIS 3.34 Prizren 版本,可能与之前和未来的版本略有不同。
目录
键盘快捷键 添加底图
创建新图层
添加要素
编辑要素
符号系统
使用工具箱
字段计算器
添加标签
地图主题
地图布局
你将学到的内容
在这次演练结束时,你将学会如何制作类似这样的地图,我将用于森林调查。
从这篇文章中你将学到的内容。(作者创建)
键盘快捷键
有几个常用的操作可以通过实现键盘快捷键来简化你的工作。我会自定义它们,使其更容易使用。这可能看起来不重要,但相信我,当你在地图项目中移动和切换时,它会优化一切。
转到键盘快捷键。(作者截图)
这五个操作及其自定义快捷键为:
-
平移地图:C
-
放大:V
-
缩小:X
-
切换编辑:E
-
选择要素:R
当然,你可以随意使用你的快捷键。
搜索操作 > 更改 > 输入你想要的快捷键。(作者截图)
添加基础地图
基础地图是你整个地图项目的背景。我们通常使用权威地图作为背景,以便在其上添加图层时能够感知土地细节。在 QGIS 中,可以通过首先在插件中安装插件来添加基础地图,路径为 Plugins > Manage and Install Plugins > QuickMapServices。这些地图是通过外部 API 获取的,因此需要互联网连接。
安装 QuickMapServices 插件。(作者截图)
然后我们可以搜索并将基础图层添加到项目中。在这个例子中,我添加了 Google 卫星影像,它会出现在左侧的图层面板中。
添加基础图层。(作者截图)
我们可以稍后通过上一个截图中的快捷方式访问插件以选择其他基础图层,或者如下所示。
从 Web 菜单访问 QuickMapServices。(作者截图)
创建一个新图层
GIS 中使用了两种类型的图形。之前的 Google 卫星影像由一个颜色像素的网格组成,这被称为栅格。这种栅格有一个分辨率,当你放大足够时,最终会看到单独的像素。
矢量则没有分辨率,放大时始终保持清晰锐利。这些矢量由各种几何类型组成,即折线、多边形和点。GIS 中最常见的矢量存储格式是 ESRI shapefile。要创建此文件,转到 Layer > Create Layer > New Shapefile Layer。
创建一个新的 shapefile(作者截图)
如下所示,需要弹出窗口来定义 shapefile。shapefile 将包括一个属性表,我们可以在其中存储每个要创建的要素的信息。我们可以在此定义任何新字段。创建后,你应该会看到新图层添加到左侧的图层菜单栏中。
创建 shapefile 的属性。(作者截图)
需要注意的是,shapefile 由多个文件组成。特别值得注意的是 .shp
文件,它包含几何坐标,.dbf
文件,它包含属性表,以及 .prj
文件,它包含坐标参考系统。
一个 shapefile 由多个文件组成。(作者截图)
添加要素
创建一个要素(在此案例中是多边形)非常简单。我们只需在菜单中选择图层,启用 切换编辑(铅笔图标),然后点击 添加多边形 图标。接着,我们将鼠标指向底图,并在区域上绘制多边形,点击以完成。最后,当我们完成时,可以右键点击,弹出窗口将提示我们输入要素的属性到属性表中(如果需要)。
添加新要素。(作者截图)
编辑要素
有许多编辑方法,在这种情况下,我将展示如何将现有的多边形拆分为多个部分。首先,如之前所述选择图层并 切换编辑。然后前往 编辑 > 编辑几何 > 拆分要素。
拆分要素(作者截图)
你的鼠标箭头将变成靶心圆圈,然后你可以从多边形外部点击,通过绘制多边形线段将其切割成更小的部分,线段结束于多边形外部,并右键点击。
将多边形拆分为多个部分。(作者截图)
使用这个方法,我们将调查区域拆分为六个不同的部分,其中我知道植被类型存在一些差异。
符号系统
要调整图层的填充和边框颜色,我们可以右键点击图层 > 属性 > 选择 符号系统 标签。如果图层中的特征在其属性表中分配了类别或数值范围,我们也可以将颜色显示从 单一符号 更改为 分类 或 分级。
在这种情况下,我们只想去掉填充颜色,并将边框设置为红色,因此我们可以点击 填充,然后点击 简单线条 以依次更改它们。
调整图层的颜色和边框。(作者截图)
使用工具箱
处理工具箱包含你工作所需的所有空间处理功能。它们可以通过 处理 > 工具箱 访问,使用简单的搜索框来获取所需的功能。在这种情况下,我们希望通过在每个调查区域内添加随机点来创建一些分层随机样本。
在处理工具箱中获取随机点工具。(作者截图)
工具弹出窗口将显示,我们可以输入每个区域三个点的适当输入,距离至少相隔 10 米。
输入随机点生成的输入。(作者截屏)
这样,点就会作为地图上的新图层生成。
随机点已生成。(作者截屏)
字段计算器
我们之前稍微谈到了属性表,这是一个在 shapefile 或图层中的表格,其中每个要素可以有相应的数据存储在其中。通过图层中要素的空间属性,我们可以使用字段计算器在表格中进行计算。在这个实例中,我们希望在随机点的属性表中创建两个新字段 X 和 Y,以显示它们的坐标。
首先,我们右键点击图层并打开属性表。然后,我们切换到编辑模式 > 打开字段计算器。
打开属性表 > 字段计算器。(作者截屏)
在字段计算器中,我们想创建一个名为 X 的新字段,使用十进制格式。在表达式中,我们输入 X 坐标的计算。在这个实例中,我使用了以米为单位的本地坐标系统,但我希望标签显示全球坐标系统的纬度和经度,因此我进行了转换。
在字段计算器中,我们可以为特定字段添加计算。(作者截屏)
这一次重复相同的步骤以获取 Y 坐标,我们应该得到类似这样的结果。再次切换编辑图标以保存这两个新字段。
X 和 Y 坐标已创建。(作者截屏)
添加标签
现在我们已经为每个点创建了 X 和 Y 坐标,我们怎么在地图上显示它们?这可以通过从工具栏开启标签选项(或右键点击图层 > 属性 > 标签)来完成。然后我们选择图层 > 单一标签 > 并点击表达式对话框以设计标签的显示方式。
在表达式对话框中,我们添加了 X 和 Y 标签,并用新的一行 "X" || '\n' || "Y"
连接它们,以便文本标签将按此方式显示。
使用标签表达式启用标签(作者截屏)
然后我们通过增加字体大小和颜色,并为标签添加黑色缓冲区,使它们在黑暗的底图背景中更加突出。
调整字体大小和颜色(作者截屏)
最后,我们添加了一条白色的标注线,将每个点要素与标签连接起来。
添加标注线(作者截屏)
这样,标签在地图上看起来像这样。效果还不错,但不是最整洁的,因为其中一些标签聚集在一起,还阻碍了调查多边形的显示。
它的样子。(截图由作者提供)
我们可以通过选择移动标签图标,将标签从多边形中移开来解决这个问题,点击其中一个标签并将其移到另一个位置。
手动将标签拖出多边形。(截图由作者提供)
现在我认为最终状态更为干净。在添加其他地图符号时,可能需要进行一些细微调整以构建布局。
最终标签。(截图由作者提供)
地图主题
地图主题 在同一个项目中非常重要,因为你可以显示不同的图层而不必麻烦地切换它们。当我们在同一地图布局中创建多个地图时,主题也很重要,正如你将在下一部分中看到的那样,我们需要主要地图以及插图。
我们已经提前准备好了主要地图,所以我们将添加一个名为基础的主题。
添加一个主题。(截图由作者提供)
为了准备插图,我添加了手头的一个新加坡国家图层,并关闭了其他图层。
添加国家图层。(截图由作者提供)
接下来,我们想要将调查边界添加到国家地图中。为此,我们首先复制调查边界图层。
复制图层。(截图由作者提供)
然后,通过右键点击重复的图层 > 属性 > 符号系统,编辑颜色,将红色填充颜色添加到图层中。仅用这两个图层,调查的位置在国家中变得一目了然。
添加带有新填充颜色的复制图层。(截图由作者提供)
最后,我们将其作为另一个主题,称为插图。通过下拉菜单,我们应该能够在这两个主题之间切换。
添加了两个主题。(截图由作者提供)
地图布局
最后一步是添加所有必要的项目,使其成为一张完整的地图。这通过创建一个布局来完成。
创建一个新的布局。(截图由作者提供)
在布局页面中,我们首先定义页面属性,将其设置为纵向模式。
纵向布局。(截图由作者提供)
首先添加的当然是我们刚刚创建的地图。为此,我们需要选择添加地图图标,然后在空白画布上拖动一个矩形。
将我们的地图添加到布局中(截图由作者提供)
然后,我们可以通过选择移动图标进行一些精细调整。接着,我们可以平移地图上的内容。我们可以使用鼠标进行缩放,但对于精细调整,我们可以输入特定的比例尺。特别重要的是选择之前创建的地图主题。
在布局中调整地图并选择主题。(作者截图)
接下来,我们添加另一个称为插图的地图,它表示初始地图的相同区域,但以更广的比例显示它的位置。再次,我们需要将插图锁定为之前创建的地图主题。
添加插图。(作者截图)
现在,我们可以准备在空白矩形背景中添加其余的地图元素。角落经过圆角处理,使其看起来更美观。在右上角面板中,我们可以调整每个地图元素的层级,以便插图位于矩形背景的顶部。
添加一个空白元素。(作者截图)
完成这些步骤后,我们首先为其添加一个图例。我们可以自定义图例的标题,并删除一些不需要的条目。
添加一个图例。(作者截图)
北箭头也是地图的重要组成部分。有几种箭头类型可以选择。
添加一个北箭头。(作者截图)
最后,我们将为其添加一个比例尺。我们可以更改比例尺符号类型,并在项目属性中自定义比例尺。
添加一个比例尺。(作者截图)
最终,我们可以修饰地图元素,并将完成的地图导出为栅格图像,或保留为 SVG 或 PDF 矢量图形。
导出为图片。(作者截图)
总结
空间分析和制图是数据分析和可视化的一个小众领域。在我从事这个领域的那些年里,我为公共步道展示创建了地图,并将它们发表在杂志、报纸、书籍和期刊上。这是一项有趣且富有挑战性的工作,我相信你可以利用我提供的基础知识进行同样的尝试并在此基础上拓展。
在远程工作的时代培养新的数据科学家
学习如何成为一名专业数据科学家的方式现在有所不同,但并非不可能
·
关注 发表在 Towards Data Science · 9 分钟阅读 · 2023 年 10 月 17 日
–
今天的专栏部分涉及数据科学,但也涉及工作的社会学。作为该领域的高级从业者,我在 Covid-19 以及我们今天工作方式的根本转变之前很久就开始了我的数据科学职业生涯。我在那之前几年就开始了我的职业生涯。因此,我的多年学习如何成为任何职业人士(更不用说专业数据科学家了)是在与许多更有经验的人紧密相处中度过的,这在很多方面使我能够达到现在的位置。我的数据科学家发展不仅仅是关于课程学习和研究,它还涉及以各种方式学习如何成为数据科学家,其中许多都是通过与其他数据科学家在一起工作和进行工作而微妙地吸收的。
重要的是要认识到,工作不仅仅是我们对雇主的付出,即使是在资本主义体系下。它也包括我们得到的回报,而且不仅仅是金钱方面的。工作场所和工作对我们有许多社会和文化影响,不仅仅是领取薪水。特别是,我们通过职业发展我们的社会身份,我们通过观察其他人如何体现这些身份来学习如何体现这些身份。
我们通过职业发展我们的社会身份,我们通过观察其他人如何展示这些身份来学习如何体现这些身份。
我想指出的是,将聪明但缺乏经验的年轻人培养成专业数据科学家的过程,不仅仅是关于数学技能,更是关于社会规范、建立网络以及适应我们工作的环境。许多这些元素在最好的时候也很难获得,而我们现在的情况是远程和混合工作将要求我们找到新的方法来传递这些信息和文化。
(我将要讨论的许多内容可能与许多工作类型相关,但我这里特别关注的是年轻数据科学家的经历。)
让我们深入探讨一下我们从工作中获得的一些东西,这些东西使我们能够成为我们职业中的完全参与者。
规范
我们通过工作发展文化和社会规范,通过观察他人的行为,尤其是观察我们层级中更高职位的人的行为。例如,商业术语、着装规范和社交礼仪等,都可以通过在工作场所的间接学习而发展。在一些工作场所,特别是白领工作场所,这些规范代表了建立社会资本甚至阶层流动的工具。在数据科学领域,有一些规范是可以跨领域通用的,或者在不同的数据科学实践行业中通用。例如,在技术数据科学领域,休闲装确实是常态。还有一些关于如何与你的老板和其他领导者互动的无形标准,包括如何沟通技术话题。还有许多关于如何成为一个专业人士的规范——如何处理商务旅行、与客户互动等等。这些技能对于职业成功迟早都是必不可少的,但根据我的经验,这些大多是通过观察和渗透学习的。
技能
我们还从工作场所获得了实际技能,因为几乎每个人都需要学习一些东西,以在新工作中获得成功。以我为例,经过几年的学术生涯后进入数据科学领域,我需要学习如何将我所了解的数据科学和机器学习应用于商业问题,而不是学术问题。我从我曾担任的数据科学职位的同事那里,特别是我的第一个职位中,学到了新的算法、编码最佳实践以及许多其他技能。这些并不全是正式培训——其中相当一部分是通过观察和吸收其他经验丰富且成功的人士如何做事的方式进行的被动学习。相关地,我们还了解了我们的“未知未知”。我们都有盲点,特别是当我们刚开始时,我们没有意识到自己缺少了一块拼图或一种可能有用的方法,直到这些缺失被指出来为止。观察那些使用你不知道存在的技能的同事可以为你打开构建该技能的大门。
网络
此外,还有一个更抽象但仍然重要的工作场所提供的同事情谊和网络创建元素。理想情况下,当你加入一个团队或公司时,你会与其他人建立关系,而这些联系是职业网络的粘合剂,能够帮助你的职业生涯发展。如果你没有建立这些联系,你不仅在当前工作中处于不利地位,还会在未来受到影响。我个人非常幸运,通过同事间的友谊建立了强大的职业网络,这对我的职业成功起到了关键作用。数据科学家是很棒的人,我们互相帮助寻找机会并建立联系,但你需要一种方式来进入这些网络。通常,有经验的同事会帮助介绍并非正式地为你担保,这会让这件事变得更容易。
成为一名成功的数据科学家涉及以某种方式获取所有这些组件(可能还有其他组件,具体视情况而定)。但正如我提到的,自从我开始职业生涯以来,工作的物理环境发生了很大变化(我认为是变好的)。我们如何在这个新世界中吸引新从业者进入这个领域?
我们的工作地点
在我看来,对于像我们这样从事数据科学/机器学习的白领人士来说,实际上有四种工作方式。
-
100% 在办公室工作,没有人进行远程工作
-
混合模式:部分或主要远程工作,加上有意的、目的明确的面对面交流
-
混合模式:部分或主要远程工作,加上随意、不规律的面对面交流
-
完全远程工作,无面对面交流
正如许多专家所争辩的那样,混合工作模式可能是我们这些数据科学家在未来几个月和几年中会经历的(如果我们尚未经历的话)。对于大多数人来说,全职办公室工作不会回归,因为我们已经体验到远程工作的自主性和灵活性,并意识到这对我们的生活质量有多大的改善。数据科学家拥有的技能需求很高,我们可以在工作中获得这种灵活性,如果我们想要的话。
理清“混合模式”是什么意思很重要。每周三天通勤到办公室或市中心并不是唯一的工作方式,人们有时见面,有时不见面,而看到关于这方面的讨论如此无感是令人沮丧的。我会把大多数关于混合工作的概念视为“部分或主要远程工作,加上随意、不规律的面对面交流”。这是因为他们试图在疫情前的工作模式下创建混合工作模式。这是对我们希望工作是什么以及值得权衡的内容几乎没有理解的结果。
在一个几乎空无一人的办公室里,与少数你几乎不认识并且很少互动的人待在一起,是初级数据科学家实现上述好处的糟糕方式(如果能实现的话)。对他们、他们的家庭和社区的权衡是巨大的。通勤对我们的个人健康、社会福利以及环境健康都非常糟糕,更不用说浪费了我们可以用来高效工作的宝贵时间。如果我们要花时间去工作地点,那就必须值得。
通勤对我们的个人健康、社会福利和环境健康都非常糟糕,更不用说浪费了我们可以用来高效工作的宝贵时间。
另一个选择是什么?我很喜欢“部分或主要远程工作加上有意的面对面时间”。一个例子可能是日常远程工作与季度现场会议,在这期间,人们前往一个中心地点(不仅仅是地区或本地办公室),进行战略规划、协作工作、社交互动以及相互学习。你可以以多种方式分配这段时间,但关键是这些面对面时间是有目的的,并且设计上就是为了实现这个目的。
有效混合工作的可能特征:
-
这可能比远程工作或完全在办公室工作更贵。
-
成功需要思考和规划。
对于那些在数据科学领域工作多年的经验丰富的人员来说,完全远程工作可能是合适的。我们已经融入了网络,学习了社交规范,并获得了技能(最重要的是,更新技能的渠道),这些都不需要特别的面对面时间。然而,我认为我们有责任帮助那些后来的同行,而与初级同事面对面有目的地相处是一种回馈,是值得的。
如何做到这一点
我不会精确规定如何构建有意的面对面时间,因为每家公司和组织的情况都不同,无法一刀切。然而,我有一些针对上述具体目标的建议。
-
规范:传达规范和文化最好是有意为之。不要仅仅希望你的初级员工会立即理解人际期望的运作方式。我们可能在每周工作 40 多个小时时不需要明确说明这些事情,但情况可能已经改变。比你认为需要的更明确一些。一些对这些规范的被动吸收也会在有意的面对面时间中发生。
-
技能:数据科学的关键技能根据不同人的定义有所不同,但通常涉及一些编码、统计学、机器学习、商业头脑和沟通技巧的混合。这些都是通过实际工作发展和提高的技能,但我们也可以通过观察其他人如何做这项工作来获得这些技能。通过在你有意安排的面对面时间中创造协作工作机会,而不仅仅是专注于繁琐的会议,你可以帮助这些技能的传递。
-
网络:我真的认为,在远程工作的数据科学家中建立网络可能是最困难的事情,因为我们经常独自完成日常工作。尽管你会有团队的模型和代码审查,可能会在站会、会议和黑客马拉松中进行连接,但在疫情前的工作场所中,大部分网络发展来自于边缘社交。咖啡机旁的闲聊虽然是陈词滥调,但确实能让同事们更加熟悉。这就是为什么随意而无序的面对面混合工作与有目的的面对面工作完全不同——在这些指定的现场中进行社交互动可以大大促进强大网络的发展。
许多雇主似乎不确定如何引进初级数据科学家,并将他们培养成经验丰富的从业者,因此他们往往倾向于招聘比实际工作需求更高级的人员。虽然这为我这样的从业者提供了更多机会和需求,但对整个领域来说并不利。我们需要让新入行的人员带来新的想法和创造力,并且要为他们提供成长和成功的工具,即使我们不像以前那样整天在同一个办公室里工作。
我们需要让新入行的人员带来新的想法和创造力,并且要为他们提供成长和成功的工具。
作为数据科学领域的资深成员,我们的任务首先是承认现在的情况有所不同,这没问题。我们无法幻想回到不同的工作世界,我也不愿意这样做。工作灵活性让我们的生活和社区变得更好。我们只需要努力识别重要的事项,并弄清楚如何在这个新环境中实现这些目标。
查看更多我的工作请访问 www.stephaniekirmer.com.
使用 scienceplots 和 matplotlib 轻松创建科学图表
使用几行 Python 代码立即转换你的 Matplotlib 图形
·发布在Towards Data Science ·阅读时间 9 分钟·2023 年 7 月 17 日
–
在为学术期刊撰写文章时,图表的布局和样式应符合预定格式。这确保了该出版物所有文章的一致性,并且所包含的图表在打印时质量高。
Python 在科学界广泛使用,并提供了创建科学图表的绝佳方式。然而,当我们使用 matplotlib 这一 Python 中最流行的绘图库时,默认的图表质量较差,需要调整以满足要求。
更改 matplotlib 图形的样式可能很耗时,这就是scienceplots库的用武之地。只需几行代码,我们就能立即改变图形的外观,而不必花费太多时间去调整图形的各个部分。
scienceplots库允许用户创建类似于学术期刊和研究论文中常见的简单而信息丰富的图表。不仅如此,它还将某些样式的 DPI 设置为 600,这通常是出版物要求的,以确保高质量的打印图像。
scienceplots 库包含众多样式,包括对多种语言的支持,如中文和日文。你可以通过下面的链接探索scienceplots库中的所有样式。
科学绘图的 matplotlib 样式。通过创建一个帐户来贡献于 garrettj403/SciencePlots 的开发…
在本文中,我们将探讨如何将一些基本的常见数据可视化转换为可以包含在科学出版物中的内容。
设置 scienceplots
在使用 scienceplots 库创建图表之前,你需要确保你的计算机上已安装了 LaTeX。LaTeX 是一个排版系统,专为技术和科学文档的创建而设计。
如果你还没有在机器上安装 LaTeX,可以在 这里 和 这里 找到有关 LaTeX 及其安装的更多详细信息。
如果你在 Google Colab 上运行,你可以在单元格中运行以下代码以安装 LaTeX。
!sudo apt-get install dvipng texlive-latex-extra texlive-fonts-recommended texlive-latex-recommended cm-super
在设置 LaTeX 之后,我们可以使用 pip 安装 scienceplots 库:
pip install SciencePlots
一旦在你选择的平台上安装了库和 LaTeX,你就可以导入 scienceplots 库以及 matplotlib。
import scienceplots
import matplotlib.pyplot as plt
为绘图创建虚拟数据
在生成一些图表之前,我们首先需要创建一些样本数据。稍后我们将看到 scienceplots 库如何处理实际数据。
在本文的这一部分,我们将使用 np.linspace
创建一些线性间隔的值,然后对这些数据进行一些随机的数学计算。
# Generate x values
x = np.linspace(0, 10, 20)
# Generate y values with random noise
y = np.sin(x)
y2 = np.cos(x)
y3 = y2 * 1.5
一旦我们创建了数据(或从 csv 文件中加载到 pandas 中),我们就可以开始创建我们的图表。
使用 Matplotlib 创建带标记的折线图
我们将使用的第一个图是折线图。这可以通过使用 matplotlib 的 .plot()
函数并传入 x
和 y
参数所需的数据来轻松创建。
由于我们处理的是从方程中派生的变量,因此有时在图例中包含这些变量对于读者理解它们可能很有帮助。
matplotlib 的一个优点是我们可以使用 LaTeX 方程作为标签。我们只需将方程用美元符号($
)括起来。
plt.figure(figsize = (6,6))
plt.plot(x, y, marker='o', label='$y=sin(x)$')
plt.plot(x, y2, marker='o', label='$y=cos(x)$')
plt.plot(x, y3, marker='o', label='$y=y2*1.5$')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()
当我们运行上述代码时,我们将得到以下非常基本的 matplotlib 图形,具有标准颜色。
应用 scienceplots 之前的基本 matplotlib 折线图。图像由作者提供。
尽管上面的图形看起来可用,但它的质量(dpi 和大小)以及样式可能不完全适合在期刊中发表。
将 scienceplots 样式应用于折线图
为了即时转换我们的图形,我们可以添加一行代码:一个 with
语句,它调用 matplotlib 的 style.context
函数,并允许我们传入 scienceplots 提供的多种风格之一。
with plt.style.context(['science', 'high-vis']):
plt.figure(figsize = (6,6))
plt.plot(x, y, marker='o', label='$y=sin(x)$')
plt.plot(x, y2, marker='o', label='$y=cos(x)$')
plt.plot(x, y3, marker='o', label='$y=y2*1.5$')
plt.xlabel('X Variable (mm)')
plt.ylabel('Y Variable')
plt.legend()
plt.show()
当我们运行上述代码时,我们会得到如下图,这图更适合用于期刊出版。
应用 scienceplots 风格后的 Matplotlib 线图。图片由作者提供。
该图形简单(即没有图表杂质),不同的线条很容易区分。此外,当在 Jupyter Notebook 中查看此图形时,即使我们设置了相对较小的图形尺寸,它可能看起来仍然非常大。这是因为图形的 DPI 设置为 600,这通常是许多出版物的要求,并确保图形尽可能清晰。
让我们尝试应用另一种风格。这次我们将使用 电气和电子工程师协会(IEEE) 的风格。
要做到这一点,我们只需将 high-vis
替换为 ieee
即可改变风格。
with plt.style.context(['science', 'ieee']):
plt.figure(figsize = (6,6))
plt.plot(x, y, marker='o', label='$y=sin(x)$')
plt.plot(x, y2, marker='o', label='$y=cos(x)$')
plt.plot(x, y3, marker='o', label='$y=y2*1.5$')
plt.xlabel('X')
plt.ylabel('Y')
plt.legend()
plt.show()
当我们运行上述代码时,我们将获得符合 IEEE 推荐风格的下图。
应用 scienceplots IEEE 风格后的 Matplotlib 线图。图片由作者提供。
带有 Science Plots 的直方图
在之前的示例中,我们探讨了如何将风格应用于线图。
但是我们能将相同的风格应用于其他类型的图吗?
当然可以!
让我们看看如何将这种风格应用于直方图。
首先,让我们使用以下代码创建一个使用伽马射线(地质构造自然放射性测量)数据的 matplotlib 图形。为了展示第二个数据集,我将相同的数据调整了 20 个 API 单位。
plt.figure(figsize = (6,6))
plt.hist(df['GR'], bins=100, label='GR1', alpha =0.5)
plt.hist(df['GR']+20, bins=100, label='GR2', alpha=0.5)
plt.xlim(0, 150)
plt.xlabel('Gamma Ray')
plt.ylabel('Frequency')
plt.legend()
plt.show()
当我们运行上述代码时,我们会得到以下图形。
简单的 Matplotlib 伽马射线测量直方图。图片由作者提供。
我们会注意到它使用了 matplotlib 的标准风格,看起来非常基础,两组数据重叠在一起。这导致一些信息被遮盖。
让我们看看 IEEE 风格如何改变了这些内容。
with plt.style.context(['science', 'ieee']):
plt.figure(figsize = (6,6))
plt.hist(df['GR'], bins=100, label='GR1')
plt.hist(df['GR']+20, bins=100, label='GR2')
plt.xlim(0, 150)
plt.xlabel('Gamma Ray')
plt.ylabel('Frequency')
plt.legend()
plt.show()
当我们运行上述代码时,我们得到应用 IEEE 风格后的下图。然而,第二个 GR 数据集仍然遮挡了第一个。
应用 scienceplots IEEE 风格后的 Matplotlib 伽马射线测量直方图。图片由作者提供。
也许我对 scienceplots 库能处理任何重叠并自动应用透明度有较高的期望。
然而,这并不是太费力。我们只需为每个数据集添加 alpha 参数。
with plt.style.context(['science', 'ieee']):
plt.figure(figsize = (6,6))
plt.hist(df['GR'], bins=100, label='GR1', alpha=0.5)
plt.hist(df['GR']+20, bins=100, label='GR2', alpha=0.5)
plt.xlim(0, 150)
plt.xlabel('Gamma Ray')
plt.ylabel('Frequency')
plt.legend()
plt.show()
当我们运行上述代码并进行 alpha 更改时,我们得到如下图形。
在应用 scienceplots 并向数据集添加透明度后得到的伽马射线测量直方图。图片由作者提供。
现在我们可以看到两个数据集的条形图变化。
建议您检查预期出版物的样式指南,以确保使用透明度是可接受的。在大多数情况下,应该是可以的,但值得检查一下。
将 Science Plots 应用于 Seaborn 图形
我们不仅限于将 scienceplots 库的样式应用于 matplotlib 图形。我们还可以将其应用于Seaborn图形。这是因为 Seaborn 基于 matplotlib 代码。
有时候,在创建图形时,Seaborn提供了比 matplotlib 更简便的方法来创建某些图形。例如,当我们有一个基于文本的分类变量时,我们希望能够绘制它,而不需要为每个类别添加一个单独的散点图。
在这个例子中,我们有一些中子孔隙度和体积密度数据——常见的测井测量。对于每个测量,我们还拥有一个岩性类别。
这个数据集源自 Force 2020 Xeek 机器学习竞赛数据集。详细信息可以在文章末尾找到。
首先,我们需要将 seaborn 导入到我们的笔记本中。
import seaborn as sns
导入 seaborn 库后,我们可以使用以下代码创建散点图。
plt.figure(figsize=(6, 6))
sns.scatterplot(data=df, x='NPHI',
y='RHOB', hue='LITH', s=10)
plt.ylabel('Bulk Density (RHOB) - g/cc')
plt.xlabel('Neutron Porosity (NPHI) - dec')
plt.ylim(2.8, 1.4)
plt.show()
当我们运行上述代码时,我们会得到以下散点图,其中数据通过不同的岩性进行了着色。
使用 Seaborn 生成的基本中子密度交叉图。图片由作者提供。
看起来还不错。然而,我们需要确保样式适合预期的期刊,并且颜色对所有读者都是可访问的。
为了应用我们的 scienceplots 样式,我们可以使用与之前相同的语法:
with plt.style.context(['science', 'ieee']):
plt.figure(figsize=(10, 8))
sns.scatterplot(data=df, x='NPHI', y='RHOB', hue='LITH', s=10)
plt.ylim(2.8, 1.4)
plt.title('RHOB vs NPHI Crossplot')
plt.show()
当我们运行上述代码时,我们会得到以下具有改进样式的图形,包括新的色彩调色板。
Seaborn 散点图,应用 scienceplots 样式,展示了体积密度与中子孔隙度的关系,并根据岩性变化着色。图片由作者提供。
选择图形的色彩调色板可能会很棘手且耗时;然而,经过一些考虑,它可以使您的图形对视觉障碍的读者更为友好。
如果您想找到一些工具来帮助您选择有效且可访问的色彩调色板,请查看下面的链接。
- 4 种帮助您选择数据可视化色彩调色板的必备工具
此外,当在黑白打印时,一些颜色可能难以区分。因此,考虑为不同类别分配不同的形状可能是值得的。这一点在我们处理来自实验室过程的小数据集时尤为重要。
摘要
在本文中,我们探讨了如何迅速将基本的 matplotlib 图形转换为可以轻松添加到科学出版物中的内容。这些图形可能仍需进一步调整,但通过使用 scienceplots 库,我们可以基本实现目标。此外,建议检查你所选期刊的作者工具包,以确保你创建的图表符合要求的标准。
本教程使用的数据集
训练数据集是 Xeek 和 FORCE 2020 机器学习比赛的一部分 (Bormann et al., 2020)。该数据集在 Creative Commons Attribution 4.0 International 许可下发布。
完整的数据集可以通过以下链接访问:doi.org/10.5281/zenodo.4351155
。
感谢阅读。在离开之前,你绝对应该订阅我的内容,获取我的文章到你的邮箱中。 你可以在这里做到这一点!
其次,你可以通过注册会员来获得完整的 Medium 体验,并支持成千上万的其他作者和我。这只需每月 $5,你就能全面访问所有精彩的 Medium 文章,并且有机会通过你的写作赚取收入。
如果你使用 我的链接注册,你将直接通过一部分费用支持我,而且不会增加你的开支。如果你这样做,非常感谢你的支持。
使用 PCA 创建评分和排名
原文:
towardsdatascience.com/creating-scores-and-rankings-with-pca-c2c3081fdb26
使用 R 语言基于多个变量为观测值创建评分
·发布于 Towards Data Science ·9 分钟阅读·2023 年 4 月 10 日
–
Joshua Golde 提供的照片,来源于 Unsplash
介绍
我对主成分分析[PCA]的研究越多,我越喜欢这个工具。我已经写过其他关于这个主题的文章,但我不断学习更多关于这个美丽数学“幕后”的知识,当然,我会与您分享这些知识。
主成分分析(PCA)是一组基于数据协方差和相关性的数学变换。它基本上会查看数据点,找出变异性最大的位置。一旦完成,这些数据会被投影到那个方向。新数据会被投影到一个新的轴上,称为主成分。
数据被投影到一个新的轴上,以解释尽可能多的变异性。
投影本身就是变换。而新数据具有许多属性,可以帮助我们数据科学家更好地分析数据。例如,我们可以进行因子分析,将相似的变量组合成一个因子,从而减少数据的维度。
另一个有趣的属性是通过观察相似性来创建排名的可能性,如我们将在本文中看到的。
使用 PCA 创建评分和排名
数据集
在这个练习中,我们将使用mtcars
,一个著名的“玩具数据集”,包含有关汽车的一些信息。尽管这是一个非常著名的数据,但它仍然非常适合作为教学示例,并且是开放的,许可证为 GPL 3.0。
我们还可以加载tidyverse
库进行数据整理,使用psych
进行 PCA。
# imports
library(tidyverse)
library(psych)
# dataset
data("mtcars")
这里是数据的小提取。
mtcars:在 Dplyr 中原生支持。图片由作者提供。
编码
现在,让我们开始编写代码吧。
重要的是要说明,PCA 和因子分析仅适用于定量数据。因此,如果你有定性或分类数据,可能对应分析会更适合你的情况。
使用 PCA 进行良好的因子提取需要变量对之间存在统计显著的相关性。如果相关性矩阵中有太多低相关性,则提取的因子可能不会很好。
Bartlett 检验
但是如何确保这些因子呢?我们可以使用Bartlett 检验,在零假设下,相关性在统计上等于零[p-value > 0.05],而在对立假设下,相关性不同于 0 [p-value ≤ 0.05]。
# Bartlett Test
cortest.bartlett(mtcars)
# RESULT
$chisq
[1] 408.0116
$p.value
[1] 2.226927e-55
$df
[1] 55
如我们所见,我们的结果是 p 值等于 0,因此可以拒绝零假设,我们可以理解提取的因子将是合适的。
接下来,我们可以使用 psych
库运行 PCA 部分。我们可以使用 pca()
函数完成这项任务。我们将输入:
-
数据集(仅包含数值)
-
所需因子的数量。在这种情况下,所有的 11 个,因此我们使用数据的第二维度位置(
dim(mtcars)[2]
) -
旋转方法:
none
。现在这可能会改变我们的结果,正如我们将看到的。默认的旋转是“varimax”
,其目的是最大化因子载荷的方差,得到一个更简单的矩阵,其中每个变量高度关联于一个或几个因子,从而更易于解释。
#PCA
pca <- pca(mtcars, nfactors=dim(mtcars)[2], rotate='none')
一旦代码运行完成,我们可以查看碎石图,它会告诉我们每个主成分捕获的方差量。
# Scree Plot
barplot(pca$Vaccounted[2,], col='gold')
接下来,结果将被显示出来。
碎石图。84% 的方差由前两个组件捕获。图片由作者提供。
凯泽准则
下一步是查看我们将用于分析的主成分。一个好的方法是查看特征值,并确定哪些值大于 1。这个规则也被称为凯泽的潜在根准则。
# Eigenvalues
pca$values
[1] 6.60840025 2.65046789 0.62719727 0.26959744 0.22345110 0.21159612
[7] 0.13526199 0.12290143 0.07704665 0.05203544 0.02204441
注意: (1) 有 11 个特征值,每个主成分一个; (2) 只有前两个符合凯泽规则的要求。因此,我们再对两个成分运行一次 PCA。
# PCA after Kaiser's rule applied
pca2 <- pca(mtcars, nfactors=2, rotate='none')
# Variance
pca2$Vaccounted
PC1 PC2
Proportion Var 0.6007637 0.2409516
Cumulative Var 0.6007637 0.8417153
绘制变量
为了绘制变量,我们需要先收集载荷。载荷矩阵显示了每个变量与每个主成分的相关性。因此,数值将在 -1 和 1 之间,记住越接近零,主成分和变量的相关性越小。越接近 1/-1,相关性越强。
载荷是变量与主成分的相关程度。
# PCA Not rotated
loadings <- as.data.frame(unclass(pca2$loadings))
# Adding row names as a column
loadings <- loadings %>% rownames_to_column('vars')
# RESULT
vars PC1 PC2
1 mpg -0.9319502 0.02625094
2 cyl 0.9612188 0.07121589
3 disp 0.9464866 -0.08030095
4 hp 0.8484710 0.40502680
5 drat -0.7561693 0.44720905
6 wt 0.8897212 -0.23286996
7 qsec -0.5153093 -0.75438614
8 vs -0.7879428 -0.37712727
9 am -0.6039632 0.69910300
10 gear -0.5319156 0.75271549
11 carb 0.5501711 0.67330434
然后,由于我们只有两个维度,我们可以轻松地使用 ggplot2 绘制它们。
# Plot variables
ggplot(loadings, aes(x = PC1, y = PC2, label = vars)) +
geom_point(color='purple', size=3) +
geom_text_repel() +
theme_classic()
显示的图形如下。
载荷图,展示了基于 PC1 x PC2 的变量之间的关系。图片由作者提供。
太棒了!现在我们对哪些变量彼此相关有了一个很好的了解。例如,油耗(Miles Per Gallon)与齿轮数、发动机类型、传动类型、drat 等因素的相关性更大。另一方面,它与 HP 和重量正好相反,这非常有意义。我们思考一下:一辆车的动力越大,燃烧的油也越多。同样,重量也如此。移动一辆更重的车需要更多的动力和油,导致油耗比率更低。
旋转版本
好的,现在我们查看了未旋转的 PCA 版本,让我们来看一下默认的"varimax"
旋转的旋转版本。
# Rotation Varimax
prin2 <- pca(mtcars, nfactors=2, rotate='varimax')
# Variance
prin2$Vaccounted
RC1 RC2
Proportion Var 0.4248262 0.4168891
Cumulative Var 0.4248262 0.8417153
# PCA Rotated
loadings2 <- as.data.frame(unclass(prin2$loadings))
loadings2 <- loadings2 %>% rownames_to_column('vars')
# Plot
ggplot(loadings2, aes(x = RC1, y = RC2, label = vars))+
geom_point(color='tomato', size=8)+
geom_text_repel() +
theme_classic()
由 2 个组件捕获的方差相同(84%)。但请注意,现在方差的分布更加分散。旋转后的组件 RC1 [42%]和 RC2 [41%];与没有旋转的版本中的 PC1 [60%]和 PC2 [24%]相比。然而,变量保持在类似的位置,只是现在稍微旋转了一下。
加载量图,显示基于 RC1 x RC2 的变量之间的关系。图片由作者提供。
共同性
对于带旋转和不带旋转的两种主成分分析(PCA),最后的比较是关于共同性。共同性会显示在应用凯瑟规则并从分析中排除了一些主成分后,每个变量的方差损失了多少。
# Comparison of communalities
communalities <- as.data.frame(unclass(pca2$communality)) %>%
rename(comm_no_rot = 1) %>%
cbind(unclass(prin2$communality)) %>%
rename(comm_varimax = 2)
comm_no_rot comm_varimax
mpg 0.8692204 0.8692204
cyl 0.9290133 0.9290133
disp 0.9022852 0.9022852
hp 0.8839498 0.8839498
drat 0.7717880 0.7717880
wt 0.8458322 0.8458322
qsec 0.8346421 0.8346421
vs 0.7630788 0.7630788
am 0.8535166 0.8535166
gear 0.8495148 0.8495148
carb 0.7560270 0.7560270
如所见,两个方法中捕获的方差是相同的。
很好。但是这会影响排名吗?让我们接着检查。
排名
一旦我们进行了 PCA 转换,创建排名是非常简单的。我们需要做的就是收集组件的方差比例,使用pca2$Vaccounted[2,]
和pca$scores
,然后进行相乘。因此,对于 PC1 中的每个分数,我们将其乘以该 PCA 运行的对应方差比例。最后,我们将这两个分数添加到原始数据集 mtcars 中。
### Rankings ####
#Prop. Variance Not rotated
variance <- pca2$Vaccounted[2,]
# Scores
factor_scores <- as.data.frame(pca2$scores)
# Rank
mtcars <- mtcars %>%
mutate(score_no_rot = (factor_scores$PC1 * variance[1] +
factor_scores$PC2 * variance[2]))
#Prop. Variance Varimax
variance2 <- prin2$Vaccounted[2,]
# Scores Varimax
factor_scores2 <- as.data.frame(prin2$scores)
# Rank Varimax
mtcars <- mtcars %>%
mutate(score_rot = (factor_scores2$RC1 * variance2[1] +
factor_scores2$RC2 * variance2[2]))
# Numbered Ranking
mtcars <- mtcars %>%
mutate(rank1 = dense_rank(desc(score_no_rot)),
rank2 = dense_rank(desc(score_rot)) )
结果如下所示。
基于 PCA/因子分析的排名。图片由作者提供。
上面的表格是未旋转PCA 的 TOP10。观察它如何突出显示低mpg
、高hp
、cyl
、wt
、disp
的汽车,就像加载量建议的那样。
底下的表格是varimax 旋转PCA 的 TOP10。由于方差在两个组件之间更加分散,我们看到了一些差异。例如,disp
变量现在不那么均匀了。在未旋转的版本中,PC1 的加载量主导了该变量,具有 94%的相关性,而在 PC2 中几乎没有相关性。对于 varimax,它在 RC1 中为-73%,在 RC2 中为 60%,因此有些混乱,因此尽管排名有所不同,但它显示了高和低的数字。mpg
也可以这样说。
基于相关变量的排名
在我们完成所有这些分析后,我们还可以为排名创建设定更好的标准。在我们的研究案例中,我们可以这样说:我们想要最佳的mpg
、drat
和am
手动变速箱(1)。我们已经知道这些变量是相关的,因此结合使用它们进行排名会更容易。
# Use only MPG and drat, am
# PCA after Kaiser's rule applied: Keep eigenvalues > 1
pca3 <- pca(mtcars[,c(1,5,9)], nfactors=2, rotate='none')
#Prop. Variance Not rotated
variance3 <- pca3$Vaccounted[2,]
# Scores
factor_scores3 <- as.data.frame(pca3$scores)
# Rank
mtcars <- mtcars %>%
mutate(score_ = (factor_scores3$PC1 * variance3[1] +
factor_scores3$PC2 * variance3[2])) %>%
mutate(rank = dense_rank(desc(score_)) )
以及结果。
按照 MPG、Drat 和变速箱进行排名。图片由作者提供。
现在结果变得很有意义。以本田思域为例:它具有高 MPG、数据集中最高的 drat 和 am = 1。现在看看排名为 4 和 5 的车。保时捷的 mpg 较低,但 drat 高得多。莲花则正好相反。成功!
在你离开之前
本文旨在向你展示 PCA 因子分析的介绍。我们可以在这个教程中看到工具的强大。
然而,在进行分析之前,重要的是要研究变量的相关性,然后设定排名创建的标准。还需注意 PCA 受异常值的影响很大。所以如果你的数据包含过多的异常值,排名可能会扭曲。解决办法是对数据进行标准化处理。
如果你喜欢这些内容,不要忘记关注我的博客以获取更多信息。
gustavorsantos.medium.com/?source=post_page-----c2c3081fdb26--------------------------------
[## Gustavo Santos - Medium]
在 Medium 上阅读 Gustavo Santos 的文章。数据科学家。我从数据中提取见解以帮助人们和公司…
gustavorsantos.medium.com/?source=post_page-----c2c3081fdb26--------------------------------
在 Linkedin 上也可以找到我。
这是这段代码的 GitHub 仓库。
github.com/gurezende/Studying/tree/master/R/Factor%20Analysis%20PCA?source=post_page-----c2c3081fdb26--------------------------------
[## Studying/R/Factor Analysis PCA at master · gurezende/Studying]
你现在无法执行该操作。你已在另一个标签页或窗口中登录。你在另一个标签页或窗口中注销了…
参考文献
FÁVERO, L.; BELFIORE, P. 2022. Manual de Análise de Dados. 第 1 版. LTC.
www.datacamp.com/tutorial/pca-analysis-r
在 Grafana 中创建时间序列图
原文:
towardsdatascience.com/creating-time-series-plots-in-grafana-f9dade30dff4
学习如何使用 Python 和 Grafana 绘制动态时间序列图
·发表在 Towards Data Science ·5 分钟阅读·2023 年 2 月 9 日
–
图片来源:Dan Lohmar 在 Unsplash
Grafana 是一个多平台开源分析和交互式可视化 Web 应用程序。如果你进行数据分析,Grafana 是一个宝贵的工具,它允许你使用各种数据源以及不同的内置可视化类型来构建仪表板。
你可以从
grafana.com/grafana/download
下载并安装 Grafana。支持的平台包括 Mac、Windows、Linux、Docker 和 ARM。
在这篇文章中,我将向你展示如何构建一个显示特定地点的温度和湿度的时间序列图。
对于这篇文章,我将假设你已经熟悉 Grafana 和 MySQL 的基础知识。如果你对 Grafana 不熟悉,可以查看我在 Code Magazine 上的文章 (
www.codemag.com/Article/2207061/Developing-Dashboards-Using-Grafana
)。
作者:魏孟 李 发表在:CODE Magazine: 2022 - 七月/八月 最后更新:2022 年 8 月 31 日 在我早期的文章中…
www.codemag.com](https://www.codemag.com/Article/2207061/Developing-Dashboards-Using-Grafana?source=post_page-----f9dade30dff4--------------------------------)
示例应用
对于这篇文章,我将涉及三个组件:
-
一个 Python 脚本用于持续将值写入 MySQL 服务器。在现实生活中,Python 脚本可能会从传感器读取值。本文中,我将模拟一些随机的温度和湿度值。这些值将每五秒发送到 MySQL 服务器。
-
一个 MySQL 服务器,包含一个数据库,用于存储所有由 Python 脚本发送的值。
-
Grafana 仪表盘从 MySQL 服务器中提取数据。
图片由作者提供;Python 的徽标来自 commons.wikimedia.org/wiki/File:Python_Windows_source_code_icon_2016.svg
MySQL 服务器将有一个名为WeatherReadings的数据库,其中包含一个名为Readings的表。表的架构如下:
本文中的所有图片均由作者创建。
创建数据库和表
以下 SQL 语句在 MySQL 中创建数据库和表:
CREATE DATABASE `WeatherReadings`;
USE WeatherReadings;
CREATE TABLE `Readings` (
`datetime` datetime NOT NULL,
`temperature` float DEFAULT NULL,
`humidity` float DEFAULT NULL,
PRIMARY KEY (`datetime`)
)
创建 Python 脚本
以下 Python 脚本使用mysqlclient包连接到 MySQL 服务器,并将值写入数据库表:
import datetime
import random
import threading
import MySQLdb # conda install mysqlclient
db = MySQLdb.connect (user='user1', # database user account
passwd='password', # password for user1
host='127.0.0.1', # IP address of MySQL
db='WeatherReadings') # database name
cur = db.cursor()
def insert_record(datetime, temperature, humidity) :
try:
cur.execute("""
INSERT INTO Readings (datetime, temperature, humidity) VALUES
(%s, %s, %s)
""", (datetime, temperature, humidity))
db.commit()
except MySQLdb.Error as e:
print ("Error %d: %s" % (e.args[0], e.args[1]))
db.rollback()
def update():
threading.Timer(5.0, update).start() # call update() every 5s
insert_record(datetime.datetime.utcnow(), # datetime in UTC
random.uniform(20, 39), # temperature
random.uniform(0.7, 0.9)) # humidity
update()
上述脚本执行了以下操作:
-
使用
user1
账户和“password”作为密码连接到 MySQL 服务器的WeatherReadings数据库。 -
定义
insert_record()
函数,将新的温度和湿度值插入到读数表中。 -
update()
函数每五秒调用insert_record()
函数,模拟温度和湿度值。
注意,当保存日期和时间时,我使用了 utcnow() 函数而不是
now()
函数。utcnow()
函数返回当前的 UTC(协调世界时)日期和时间。例如,新加坡的时区是 UTC +8,因此如果新加坡当前的日期和时间是 2023–02–08 10:07:38,那么 UTC 时间是 2023–02–08 02:07:38(减去 8 小时)。存储时间为 UTC 的原因是 Grafana 将根据浏览器的时区自动将 UTC 时间转换为本地时间。
配置 Grafana
在 Python 脚本完成之后,现在可以配置 Grafana 了。
添加 MySQL 数据源
在 Grafana 中,添加一个新的MySQL 数据源并按如下配置:
向仪表盘添加面板
在 Grafana 中创建一个新的仪表盘,并点击添加新面板按钮:
使用默认的时间序列面板,并使用以下值配置面板:
注意使用的 SQL 语句:
Select
datetime as time,
temperature,
humidity * 100
FROM Readings
你需要将 datetime
字段设置为 time
,以便时间序列面板能够识别数据作为时间序列。
配置面板的标题属性如下:
按如下配置面板的图表样式属性:
点击应用按钮以退出面板并返回到仪表板。现在你应该能看到面板显示温度和湿度读数的时间序列:
动态更新时间序列
点击显示在刷新按钮旁边的箭头,然后选择5 秒:
这将导致面板每五秒从 MySQL 数据源获取数据。现在面板应该每五秒刷新一次:
如果你喜欢阅读我的文章并且它对你的职业/学习有所帮助,请考虑注册成为 Medium 会员。每月费用为 5 美元,这将为你提供对 Medium 上所有文章(包括我的文章)的无限制访问。如果你使用以下链接注册,我将获得少量佣金(对你没有额外费用)。你的支持意味着我将能够投入更多时间来撰写类似的文章。
阅读韦梦李的每一篇文章(以及 Medium 上其他成千上万位作者的文章)。你的会员费直接支持……
weimenglee.medium.com](https://weimenglee.medium.com/membership?source=post_page-----f9dade30dff4--------------------------------)
摘要
在这篇文章中,你学会了如何使用 Grafana 和 MySQL 服务器绘制时间序列。在实际应用中,你的数据将不断地发送到数据库服务器,Grafana 将配置为每隔几秒刷新一次数据(由你配置)。
创建你自己的 ChatGPT 无需编码——一步步指南
原文:
towardsdatascience.com/creating-your-own-chatgpt-without-coding-a-step-by-step-guide-a4523e6a46e1
·发布于 Towards Data Science ·阅读时间 9 分钟·2023 年 11 月 12 日
–
几乎在 ChatGPT 发布一年后,OpenAI 继续用其平台的新功能和能力给我们带来惊喜。
OpenAI 最近的发布说明确实提供了一个创建自定义 ChatGPT 的新功能,称为 GPTs。
GPTs 是提升生产力的另一种方式。如果你曾经使用过 ChatGPT,你可能已经发现了许多能够帮助你日常活动的用例:它可以优化你的推文,帮助头脑风暴文章创意,生成销售话术的变体,审查代码或帮助你学习世界语。GPTs 可以帮助你制作一个“专业化”的 ChatGPT,针对你的需求进行个性化,并且在某一特定领域表现出色,而不是过于通用。
这开启了新的可能性。在本文中,我们将一步一步地创建一个新的自定义 GPT,并讨论这个新功能的一些限制。
前提条件
前提条件很简单,你需要:
-
一个 ChatGPT Plus 许可证或企业账户(这意味着,基本上,你不能使用免费账户创建 GPTs)。
-
还有一个新的 GPT 的想法(考虑你的主要用例,或请 ChatGPT 帮助你进行头脑风暴)。这里是 OpenAI 分享的一些用例以供参考:
OpenAI 提供的 GPTs 示例——OpenAI 博客——作者截图
用例
在这篇文章中,我想以我过去遇到的痛点为基础,研究一个实际的用例。
在之前的职业经历中,我不得不处理面向客户的 GDPR 主题。GDPR,或通用数据保护条例,是一项关于数据保护和隐私的欧盟(EU)法律。它旨在赋予人们对其个人信息及其使用方式的更多控制。然而,它的实施可能很棘手。法律文本超过 150 页,而且相当技术化。作为技术人员,探索法律和监管主题可能具有挑战性。在那个时候,ChatGPT 还不存在,因此我不得不提升技能并寻求外部法律专家的帮助(这也增加了成本),直到我拥有更多的自主权。但即便如此,我仍然面临新的主题,例如:处理数据跨境传输、管理安全事件、更新隐私政策或进行数据保护影响评估。
所以我想要构建一个当时我没有的 GDPR 智能助手,全天候提供帮助。
当然,这只是一个用例,但在我看来,这是一个有趣的用例,因为它解决了一个明确的需求,并且有明显的商业案例。
当你使用 ChatGPT 并询问关于 GDPR 的问题时,ChatGPT 已经“消耗了所有互联网”(虽然不完全如此,但很大一部分),因此它确实有一些准确的信息,但也有一些不够准确和精确的信息。在这种情况下,GPTs 将允许我使用特定选项来限制知识,这些选项我们将在指南中看到,还可以调整语言语调和其他一些细节。
之后你可以应用相同的逻辑,并将使用案例调整到你的需求中,通常情况下,如果你想基于知识数据库、系列文章、PDF 集合或类似使用案例来构建聊天机器人,你可以遵循相同的步骤。
让我们开始构建吧
要创建你的 GPT,你需要使用 OpenAI 提供的编辑器。
编辑器由 2 个区域组成:左侧有 2 个标签页,用于创建和配置,而右侧用于预览和测试。
你可以使用以下链接打开它(查看先决条件,你需要 ChatGPT Plus 或 Enterprise 许可证):chat.openai.com/gpts/editor
编辑器看起来是这样的:
创建新 GPT 的编辑器 — OpenAI — 作者截图
我们将按照编辑器指南中的建议步骤进行。我以以下提示开始:“我想创建一个新的 GPT,以帮助回答与 GDPR 相关的问题。它可以是与 GDPR 相关的一般问题(如主要原则),也可以是特定于用户情况的问题(例如,对于特定的安全事件,是否需要通知)。”
在提供这些指令时,你应该尽可能具体。我的提示可能不是完美的,但我们将有机会随着进展进行改进。
现在,根据我提供的描述,我得到了一个名称建议:
GPT 名称建议 — OpenAI — 作者截图
我不喜欢“GDPR Guide”这个名字,所以我会建议另一个名字:“My GDPR companion”。新的 GPT 将获得这个名称,并会建议一个徽标:
徽标建议和 GPT 初始化 — OpenAI — 作者截图
我觉得徽标不是很好,因为 GDPR 是一项欧洲法律,我认为徽标应该反映这一点。不过有趣的是,我得到了一个代表安全和隐私的徽标,这些都是 GDPR 的主要支柱。我们还可以在预览部分看到徽标(生成)、简短描述(生成)和问题示例(生成)。这有助于你初步了解 GPT 的外观以及它预计回答的问题。
因此,鉴于我想调整徽标,我将提供额外的指令,请求修订“GDPR 是一项欧洲法律。我认为徽标应该反映这一点。”
My GDPR Companion GPT 更新后的徽标 — OpenAI — 作者截图
现在的徽标在我看来更好。编辑考虑了我的意见,并提供了一个与欧洲旗帜(十二颗黄色星星和蓝色背景)更相关的徽标。
然后,编辑请求更多信息以细化其行为。
编辑器机器人请求更多信息以细化 GPT 行为 — OpenAI — 作者截图
这是真正的 ChatGPT 增强功能,因为它实际上会主动问你问题,并指导你以确保它提供正确的语调,并且很好地适应你的需求。我回答了这些问题,并确认我们一切就绪。它还会以简洁的方式重新表述你的输入,以表明它“理解”了你分享的内容。
GPT 准备情况确认 — OpenAI — 作者截图
如你所见,我还要求添加一种免责声明。在一些领域,如法律建议或财务建议,此类免责声明是必要的,以确保用户清楚地理解该工具仅用于帮助,而不承担责任。
现在,我们已经设置好了 GPT,在测试之前,我们需要在配置标签中添加一些配置:
配置标签,由 GPT 编辑器生成 — OpenAI — 作者截图
多个字段的设置不完全符合我的期望。所以我将调整其中一些,包括
-
描述:我想要一个更简短的,
-
指令:细化一些指令,
-
对话启动者:添加一个关于如何开始使用 GDPR 的对话启动者,
-
我还将添加知识库。对于知识库,我推荐添加一个(普通)文本文件。我尝试使用 PDF,但结果不是很准确(请查看限制)。供你参考,我使用的原始来源位于这里。(你可以上传多个文件)。
-
还有一些高级配置功能允许与 API 交互。这些功能也很有趣,但在本文中,我将指南限制为“无需编码”的方法。
我的 GDPR Companion GPT 已经准备好了 — OpenAI — 作者截图
现在是测试的时候了!
从一个简单的请求开始,询问法律中特定条款的信息。注意我可以仅提供简短的提示。不需要说明这是关于 GDPR 的或从知识库中获取数据:
预览模式下的 GPT — OpenAI — 作者截图
这里还有另一个示例,这个示例针对特定情况。答案解释得非常清楚,引用了正确的法律条款(尽管它很长且复杂,且我的提示没有使用完全正确的技术术语):
使用知识库的 GPT — OpenAI — 作者截图
你可以继续测试你的 GPT。如果某些回答不符合你的期望,你可以返回“创建”标签并添加一些评论和反馈,以便进行改进。你还可以通过调整说明部分或更新知识库及其他参数来细化配置。
一旦你达到了正确的配置,你现在可以保存并发布你的 GPT,使用编辑器右上角的保存按钮,你将有一些选项。在我的情况下,我将选择公开:
保存选项 GPT — OpenAI — 作者截图
请注意,对于企业用户,还可以选择在公司级别发布 GPT。
一旦保存,我会被重定向到 ChatGPT 界面,并选择我的 GPT,
我的 ChatGPT 中的 GDPR Companion — 一些部分因隐私原因被隐藏 — 作者截图
我现在可以分享我的 GPT 链接,这是我为此次测试创建的 GPT 链接。
OpenAI 提到,一些 GPT 将会提供货币化功能。目前尚不清楚具体如何实现。预计将在接下来的几周内公布。
限制
GPTs 也有一些限制。它仍然是一个新工具,应该会随着时间的推移而改进,但目前我观察到以下限制:
-
幻觉:GPTs 基于 GPT-4\。它们继承了 GPT-4 的很多特性,包括幻觉。这一点在 GPTs 中没有改变。
-
使用 PDF 时的准确性是知识库:关于使用“知识”功能的特点,允许上传各种文档,我最初尝试了一个 PDF,但结果显示出一些限制,可能与抓取问题有关。我使用计划文本格式重新尝试了一下,这似乎效果更好。
-
对于长或复杂指令的准确性:当给出长指令时,GPT 可能只考虑了一部分,而不是其他部分,或者可能没有将所有指令应用于所有回答。通常,在我的测试中,它没有在所有回答中提到免责声明。
-
响应时间: 响应时间比 GPT-4 长很多。对于一些提示,它花费了超过 1 分钟。这当然取决于许多因素,可能与最近的发布有关。但看起来,知识库越大,响应时间就越长。实际上,每次发送提示时,GPT 似乎都在访问知识库。
顺便提一下,即使这本身不是一个限制,这个新功能也会事实上使一些插件和第三方工具过时,通常,一些 管理 PDF 的插件(如 AskYourPDF),或者一些基于知识数据库生成 ChatBot 的应用程序。
结束语
目前,GPT 看起来是一个很酷的新功能,但它对于 ChatGPT 来说更像是“增量式”的,而不是真正的颠覆性。
如果你能够在 ChatGPT 或 Playground 中(使用 System 字段)良好地进行提示,也就是说,你提供了清晰的背景、指令和语气,你可能不需要这个新功能,除非你想将其与一些更高级的功能结合使用。
真正的新鲜事是分享你的 GPT 并进行货币化的能力。这些目前无法测试,我们应该期望在接下来的几周内可用。
如果你创建了一些 GPT,欢迎分享你的反馈以及你遇到的限制!
如果你创建了一些 GPT,欢迎分享你的想法和遇到的限制!
如果你想 了解人工智能,加入我的课程!
使用 GPT 和 Whisper 创建个性化语音助手
原文:
towardsdatascience.com/creating-your-personalized-voice-assistant-with-gpt-and-whisper-ddb9bd8c419
分步指南
·发表于 Towards Data Science ·6 分钟阅读·2023 年 5 月 18 日
–
照片由 Ivan Bandura 拍摄,来源于 Unsplash
本文旨在指导你创建一个简单而强大的语音助手,按照你的偏好定制。我们将使用两个强大的工具——Whisper 和 GPT,来实现这一目标。你可能已经知道 GPT 及其强大之处,但Whisper 是什么?
Whisper 是 OpenAI 提供的先进语音识别模型,能够提供准确的音频转文本服务。
我们将逐步指导你完成每个步骤,并包含编码指令。最终,你将拥有一个运行良好的语音助手。
在你开始之前
OpenAI API 密钥
如果你已经有了 OpenAI API 密钥,可以跳过这一部分。
Whisper 和 GPT APIs 都需要 OpenAI API 密钥才能访问。与 ChatGPT 的固定费用订阅不同,API 密钥的费用是根据你使用服务的多少来计算的。
价格合理。撰写本文时,Whisper 的价格为 $0.006 / 分钟,GPT(使用模型 gpt-3.5-turbo)的价格为 $0.002 / 1K tokens(一个 token 大约是 0.75 个单词)。
OpenAI 网站。图片来源于作者。
要获取你的密钥,首先在 OpenAI 网站上创建一个账户。登录后,点击右上角的你的名字,然后选择查看 API 密钥。点击创建新的密钥后,你的密钥将会显示出来。务必保存它,因为你之后将无法再次查看。
包
代码块显示了项目所需的库。该项目涉及使用 OpenAI 的 Python 库进行 AI 任务,pyttsx3用于生成语音,SoundDevice用于录音和播放音频,numpy和scipy用于数学运算。像往常一样,在开始新项目时,你应该创建一个新的虚拟环境,然后安装包。
代码结构
我们的代码将围绕一个类进行结构化,总共约 90 行代码。假设你对 Python 类有基本了解。
由作者提供的图片。
listen
方法捕获用户的语音输入,并使用 Whisper 将其转换为文本。think
方法将文本发送到 GPT,生成自然语言响应。speak
方法将响应文本转换为音频并播放。这个过程会重复:用户可以通过发出另一个请求来继续对话。
代码结构。由作者提供的图片。
init
此函数负责初始化历史记录和设置 API 密钥。
我们需要一个历史记录来跟踪之前的消息。它基本上是我们助手的短期记忆,允许它记住你在对话中早些时候说过的话。
listen
listen 函数。由作者提供的图片。
这个方法是我们助手的“耳朵”。
listen
函数允许接收用户的输入。此函数从你的麦克风录制音频,并将其转录为文本。
它的功能如下:
-
录制音频时打印Listening…。
-
使用 sounddevice 在 44100 Hz 的采样率下录制 3 秒(或任何你想要的时间)的音频。
-
将录制的音频作为 NumPy 数组保存到临时 WAV 文件中。
-
使用 OpenAI API 的
transcribe
方法将音频发送到 Whisper 进行转录。 -
打印转录的文本到控制台,以确认转录是否成功。
-
返回转录的文本作为字符串。
在示例中,助手监听了 3 秒,但你可以根据需要更改时间。
think
think 函数。由作者提供的图片。
我们助手的大脑由 GPT 提供支持。think 函数接收助手听到的内容并提出响应。怎么做到的?
响应不是在你的计算机上生成的。文本需要发送到 OpenAI 的服务器,通过 API 进行处理。然后将响应保存在响应变量中,用户消息和响应都添加到历史记录中,这是助手的短期记忆,为 GPT 模型生成响应提供上下文。
speak
speak 函数。由作者提供的图片。
speak函数负责将文本转换为语音并播放给用户。这个函数接受一个参数:text。它应该是一个表示要转换为语音的文本的字符串。
当函数被调用并传入一个文本字符串作为参数时,它会用命令engine = pyttsx3.init()
初始化 pyttsx3 语音引擎。这个对象engine
是将文本转换为语音的主要接口。
然后,函数指示语音引擎使用命令engine.say(text)
将提供的文本转换为语音。这会将提供的文本排队等待朗读。命令engine.runAndWait
告诉引擎处理排队的命令。
Pyttsx3 在本地处理所有文本到语音的转换,这在延迟方面可以是一个显著的优势。
最终修饰
助手现在已经准备好。我们只需创建一个助手对象,开始对话即可。
对话是一个无限循环,直到用户说出包含Goodbye的句子时才结束。
个性化体验的小贴士
自定义你的 GPT 助手非常简单!我们构建的代码非常模块化,可以通过添加各种功能来进行自定义。这里有一些想法可以帮助你入门:
-
为助手赋予角色:更改初始提示,让你的助手扮演英语老师、励志演讲者或其他任何你能想到的角色!查看Awesome ChatGPT Prompts获取更多创意。
-
更改语言: 想使用其他语言?没问题!只需将代码中的english更改为你想要的语言即可。
-
构建应用程序: 你可以轻松地将助手集成到任何应用程序中。
-
**添加个性:**通过添加自定义回应或使用不同的语调和语言风格,赋予你的助手独特的个性。
-
与其他 API 集成: 将你的助手与其他 API 集成,以提供更高级的功能,如天气预报或新闻更新。
结论
在这篇文章中,我们解释了如何检索你的 OpenAI API 密钥,并提供了用于捕获用户输入、生成回应和将文本转换为语音以进行播放的 listen、think 和 speak 函数的代码示例。
有了这些知识,你可以开始创建适合你特定需求的独特语音助手。从创建一个帮助日常任务的个人助手,到构建一个语音控制的自动化系统,可能性是无限的。你可以在链接的GitHub repo中获取所有代码。
喜欢这篇文章吗?订阅我的新闻通讯,The Data Interview,每周将数据科学面试问题发送到你的邮箱。
此外,你还可以在 LinkedIn上找到我。