如何加快本地机器学习模型的开发
介绍一个强大的机器学习模板
在 Unsplash 上拍摄的 ThisisEngineering RAEng
TL/DR:我在 Github 上开发了一个包,ml-template,通过加速了本地机器学习模型的开发
- 提供一个结构良好的通用代码库,可以根据您的用例轻松调整
- 使用最新的软件包(DVC 和 MLFlow)确保模型结果的再现性和有效的模型性能跟踪
开发包装的动机
虽然这似乎就发生在昨天,但我现在已经在 4 年多前开始了我的机器学习之旅。在那段时间里,我很幸运地解决了一些很酷的问题。从编写算法根据某人鞋子的照片检测其性别,到使用自然语言处理根据你的简历预测你的下一份工作,再到预测临床试验的结果,我处理过各种各样的问题。
这些问题显然大相径庭,有其独特的挑战。然而,这篇文章让我感兴趣的不是这些问题有什么不同,而是它们有什么共同点。每当我开始编写机器学习问题的代码时,我都必须编写相同的对象和函数来分割训练集和测试集,训练算法,执行交叉验证,保存训练好的模型等等。无论是自然语言问题、机器学习视觉还是任何其他类型的问题,这一点都适用。
如果你正在匆忙地开发你的代码,你也会写出结构不良的代码。我不需要告诉你,糟糕的结构代码会让任何人在以后的日子里更难发现,也意味着更不容易发现错误。
约书亚·索蒂诺在 Unsplash 上拍摄的照片
我遇到的另一个挫折是,当主体结构建成时,我要监控模型。根据我的经验,建立机器学习模型是一个迭代过程,需要对不同版本的数据和不同的转换、算法和超参数进行大量实验。
我试图通过在 Excel 电子表格中记录模型“主要”运行的参数和输出来解决这个问题,但我发现这很快变得难以操作。如果您需要将模型切换回上周运行的数据/代码组合,会发生什么呢?这可能很棘手。
为了尝试解决这些痛点,我开发了一个面向对象的机器学习模板,可以根据您的特定问题进行相应的调整。我认为这个项目相当于建造一栋房子的地基和结构——在完工之前还有相当多的工作要做,但它极大地加快了这个过程。
但是首先,让我带您看一下我用于数据和模型版本控制的两个包。
DVC 和 MLFlow 是什么?
在 Git 出现之前,对代码的修改是作为补丁和归档文件传递的。这使得两个或更多的人很难处理同一个代码,并且很难快速切换到以前的版本。Git 的采用极大地提高了软件开发的效率。
机器学习目前感觉像是处于“前 Git”时代。当然,您可以对您的代码进行版本控制,但是今天大多数数据科学家不会对他们的数据或模型进行版本控制。这意味着,你猜对了,在一个模型上合作和切换到以前的版本变得更加困难。DVC 和 MLFlow 是两个旨在提供帮助的软件包。
DVC 是数据的版本控制包。还有其他的数据版本控制包,比如“Git-LFS ”,但是这个有很多问题(更多细节见这篇博客)。DVC 的巧妙之处在于它如何将 Git 中的相同概念运用到数据管理领域。它很容易在许多不同的文件系统(本地、S3、GCP 等)上存储数据,它可以处理大量的文件大小,并与 Git 无缝集成。DVC 正在积极开发和不断扩展其功能,以处理改进模型管理和模型部署。一个面向未来的包裹。
MLFlow 是一个开源包,最初由 Databricks 开发,用于管理从实验到模型部署的整个机器学习生命周期。如果你看看他们的网站,他们有大量与所有流行的机器学习工具的集成,令人印象深刻的一系列公司正在使用并为此做出贡献。我只使用了软件包的“跟踪”功能,这使得在一个好看的用户界面上跟踪不同的机器学习实验变得非常容易。
使用软件包的提示
因此,使用 DVC 来控制数据的版本,使用 MLFlow 来记录实验结果,我创建了一个 Github 包, ml-template ,来帮助加速开发机器学习模型的过程。我的希望是,当你将来开始一个机器学习项目时,你会发现从 Github 克隆 ml-template 然后为你的项目定制代码是有帮助的。
现在,当然,当任何过程都是自动化的,是不是总是很容易使用“自动驾驶”软件,而不去想一些正在做的默认假设。特别是,每次你克隆 ml-template 的时候,我觉得你应该思考以下几点:
- 数据转换-确保适当完成必要的缩放、分类编码和特征转换(默认为无转换)。
- 训练/测试分割—确保分割适合您的问题(例如,默认为随机训练/测试分割,但分层分割可能更合适)。
- 算法—确保它适合任务(默认为随机森林)
- 度量——确保度量对于您的任务是合理的。一个典型的错误是在数据集高度不平衡时使用准确性作为衡量标准(默认的衡量标准是 AUC)
此外,这里有一些最有效地使用软件包的技巧:
- 每次进行“主”运行时,都要重新提交代码和数据。这确保了数据/代码/模型输出和保存的模型是一致的
- 调试时,设置 mlflow_record = False。这确保了只有重要的运行被记录,这有助于下游的模型分析
- 当试验新数据/新方法时,在 git 中创建一个新的分支。这利用了该框架的力量,使得比较/切换回现有设置变得非常容易
- 使用 MLFlow 中的实验对运行进行分组
结论
我希望人们发现这个包在更好地设置和管理他们的本地机器学习模型开发方面是有用的。
请不要客气贡献和建议的方式,以进一步改善包向前发展。未来发展的思路包括:
- 添加一组测试
- 用于直观显示模型结果的基本 UI 框架(使用工具,如 Streamlit
如何将你的熊猫代码加速 10 倍
骗了你!诀窍是离开熊猫
图片来自 JESHOOTS athttps://www . pexels . com/photo/fuzzy-motion-of-illuminated-railway-station-in-city-253647/
众所周知,熊猫是一个神奇的数据科学工具。它为我们提供了我们需要的数据框架结构、强大的计算能力,并且以非常用户友好的格式做到了这一点。它甚至有高质量的文档和一个庞大的支持网络,使它易于学习。太棒了。
但并不总是特别快。
当涉及很多很多计算时,这可能会成为一个问题。如果处理方法很慢,则运行程序需要更长的时间。如果需要数百万次计算,并且总计算时间不断延长,那就非常麻烦了。
这是我工作中常见的问题。我工作的一大重点是开发代表建筑中常见设备的模拟模型。这意味着我在一台设备中创建模拟热传递过程和控制逻辑决策的功能,然后将描述建筑条件和居住者行为选择的数据传递到这些模型中。然后,模型预测设备将做什么,它将如何满足居住者的需求,以及它将消耗多少能量。
为了做到这一点,模型需要基于时间。它需要能够计算模拟中某一点发生了什么,然后才能进行下一组计算。这是因为一次的输出是下一次的输入。例如,想象一下预测你的烤箱在任何时间点的温度。目前正在加热吗?自上次讨论以来,温度上升了多少?当时的温度是多少?
这种对上一次的依赖导致了一个问题。我们不能使用向量计算。我们必须使用可怕的 for 循环。For 循环速度很慢。
我们能做些什么让事情进展得更快一点?
无论矢量化计算是否可行,一个解决方案是将计算转换为 numpy。根据 Sofia Heisler 在 Upside Engineering 博客上的说法,numpy 使用预编译的 C 代码执行大量的后台信息。这种预编译的 C 代码通过跳过编译步骤和包含预编程的速度优化,使它比 pandas 快得多。此外,numpy 删除了许多关于熊猫的信息。Pandas 跟踪数据类型、索引,并执行错误检查。所有这些都非常有用,但在这个时候没有必要,而且会减慢计算速度。Numpy 不会这样做,并且可以更快地执行相同的计算。
有多种方法可以将 panads 数据转换为 numpy。
可以使用。价值方法。这将在 numpy 中创建相同的系列。对于一个简单的示例,请参见下面的代码:
import pandas as pd
Series_Pandas = pd.Series(data=[1, 2, 3, 4, 5, 6])
Series_Numpy = Series_Pandas.values
数据帧可以使用。to_numpy()函数。这将在 numpy 中创建一个具有相同值的 int64 对象。注意,这不会保留列名,您需要创建一个字典,将 pandas 列名转换为 numpy 列号。这可以通过下面的代码来实现:
import pandas as pd
import numpy as npDataframe_Pandas = pd.DataFrame(data=[[0,1], [2,3], [4,5]], columns = ['First Column', 'Second Column'])
Dataframe_Numpy = Dataframe_Pandas.to_numpy()
Column_Index_Dictionary = dict(zip(Dataframe_Pandas.columns, list(range(0,len(Dataframe_Pandas.columns)))))
该代码将 dataframe 转换为 numpy int64 对象,并提供了遍历每一行所需的所有工具,以用户友好的方式编辑特定列中的值。每个单元都可以用类似熊猫的方式来调用。具有 numpy 索引的 loc 函数,遵循结构 int64object[row,Dictionary[‘Pandas 列名’]] 。例如,如果要将“第二列”的第一行中的值设置为“9”,可以使用以下代码:
Dataframe_Numpy[0, Column_Index_Dictionary['Second Column']] = 9
这会让我的代码快多少?
当然,这将因情况而异。通过切换到 numpy,一些脚本会比其他脚本有更多的改进。这取决于脚本中使用的计算类型以及转换为 numpy 的所有计算的百分比。但是结果可能是激烈的。
例如,我最近用它将我的一个模拟模型从熊猫基地转换为 numpy 基地。最初,基于熊猫的模型需要 362 秒来进行年度模拟。超过 6 分钟了。如果你用模型运行一个模拟,这并不可怕,但是如果你运行一千个呢?在将模型的核心转换为 numpy 之后,同样的年度模拟需要 32 秒来计算。
做同样的事情要多花 9%的时间。将我的代码从 pandas 转换到 numpy 的速度比用户预先存在的函数快了 10 倍以上。
包装它
Numpy 拥有熊猫的所有计算能力,但执行它们时没有携带太多的开销信息,并且使用预编译、优化的方法。因此,它可以明显快于熊猫。
将数据帧从 pandas 转换为 numpy 相对简单。您可以使用数据框。to_numpy()函数来自动转换它,然后创建一个列名字典,以便像访问熊猫一样访问每个单元格。锁定功能。
这个简单的改变可以产生显著的效果。使用 numpy 的脚本执行时间大约是使用 pandas 所需时间的 10%。
如何分割一个 Pickled 模型文件以绕过 PythonAnywhere 上的上传限制
在这篇短文中,我将分享如何使用 python 和 os 库分割和连接一个 pickled 模型文件,以绕过 PythonAnywhere 上的上传限制。
凯文·Ku 拍摄的图片
在我的上一篇文章“建立一个卷积神经网络来识别剃过脸和没剃过脸的人”中,我分享了我用 Pickle 保存最终训练好的模型的方法。
“pickle”是将 Python 对象层次结构转换成字节流的过程,“unpickling”是相反的操作,将字节流(来自二进制文件或类似字节的对象)转换回对象层次结构。— 源代码: Lib/pickle.py
作为一个复习,这里有一行代码来处理你的最终模型,保存所有的权重,没有将结构保存为。json 文件,并作为. h5 文件单独加权。
import picklepickle.dump(model, open(“Your_Saved_Model.p”, ‘wb’))
因为我有一个模型,所以我的目标是构建一个 Flask 应用程序,并部署它供公众使用。我选择 PythonAnywhere 来托管我的应用程序,因为我需要访问 Bash 控制台,还需要设置一个虚拟环境,但是我意识到文件上传是有限制的,我的模型比允许的大了三倍。
我做了一些研究,发现了一篇非常有帮助的文章,在理解如何用 Python 拆分和合并文件方面。使用os
库和下面的函数,我能够将 pickled 模型文件分割成三个更小的文件:
def split(source, dest_folder, write_size):
# Make a destination folder if it doesn't exist yet
if not os.path.exists(dest_folder):
os.mkdir(dest_folder)
else:
# Otherwise clean out all files in the destination folder
for file in os.listdir(dest_folder):
os.remove(os.path.join(dest_folder, file)) partnum = 0
# Open the source file in binary mode
input_file = open(source, 'rb') while True:
# Read a portion of the input file
chunk = input_file.read(write_size)
# End the loop if we have hit EOF
if not chunk:
break
# Increment partnum
partnum += 1
# Create a new file name
filename = '/Model_Files/final_model' + str(partnum)
# Create a destination file
dest_file = open(filename, 'wb')
# Write to this portion of the destination file
dest_file.write(chunk) # Explicitly close
dest_file.close() # Explicitly close
input_file.close() # Return the number of files created by the split
return partnum
该函数需要 source、write_size 和 dest_folder。source 是保存整个模型的位置,write_size 是每个文件的字节数,dest_folder 是保存每个分割文件的目标文件夹。
这里有一个例子:
split(source='Your_Saved_Model.p', write_size=20000000, dest_folder='/Model_Files/')
因为我现在有三个可接受的上传文件,所以一旦应用程序在浏览器中启动,我需要更新我的 flask 应用程序来处理服务器上的文件连接。这里有一个到我的 GitHub repo 的链接,可以在部署到 PythonAnywhere 之前查看完整的代码。
我使用下面的函数来连接文件,并将合并后的模型保存在应用程序的服务器上:
def join(source_dir, dest_file, read_size):
# Create a new destination file
output_file = open(dest_file, 'wb')
# Get a list of the file parts
parts = ['final_model1','final_model2','final_model3']
# Go through each portion one by one
for file in parts:
# Assemble the full path to the file
path = file
# Open the part
input_file = open(path, 'rb')
while True:
# Read all bytes of the part
bytes = input_file.read(read_size)
# Break out of loop if we are at end of file
if not bytes:
break
# Write the bytes to the output file
output_file.write(bytes)
# Close the input file
input_file.close()
# Close the output file
output_file.close()join(source_dir='', dest_file="Combined_Model.p", read_size = 50000000)
这个函数将单个文件字节合并成一个单独的 pickled 对象。看看我如何使用 jQuery 让用户以一种交互的方式上传图像,并通过向后端发送请求来进行预测,使用新的组合模型来服务于预测。查看我的 GitHub repo 应用程序。
资源 :
《编程 Python:强大的面向对象编程》这本书有一个示例程序,展示了如何拆分和…
stonesoupprogramming.com](https://stonesoupprogramming.com/2017/09/16/python-split-and-join-file/)
如何用 Python 将一个数据帧分割成训练集和测试集
在熊猫数据帧上使用 sklearn train_test_split 的简短指南
作者插图
在这篇短文中,我描述了如何通过应用 sklearn 的 train_test_split 函数,将数据集分割成用于机器学习的训练和测试数据。我使用我上一篇文章中的程序创建的数据框。这些数据基于 D. Greene 和 P. Cunningham 发表的原始 BBC 新闻文章数据集[1]。
如果你感兴趣,可以在这里查看源代码。
如果您错过了我的第一个从文本文件中提取信息的指南,您可能想要查看它以更好地理解我们正在处理的数据。
从任何文本文件中提取信息的可重用方法
towardsdatascience.com](/transforming-text-files-to-data-tables-with-python-553def411855)
数据理解
因为我想让本指南保持简短,所以我不会像在我的上一篇文章中那样详细描述这个步骤。在这一部分要提到的最重要的信息是数据是如何构造的以及如何访问它。
从下面的截图可以看出,数据位于 generated_data 文件夹中。一旦创建了这些文件,我们还想将训练和测试数据保存到这个文件夹中。此外,该脚本在 prepare_ml_data.py 文件中运行,该文件位于 prepare_ml_data 文件夹中。
文件系统的屏幕截图
正如我在关于将文本文件转换为数据表的上一篇文章中所介绍的,bbc_articles.tsv 文件包含五列。然而,对于本教程,我们只对文本和流派列感兴趣。
数据集的列
加载数据
第一步,我们希望将数据加载到我们的编码环境中。为此,我们需要存储数据的目录的路径。我们保存本地变量的路径来访问它,以便加载数据,并使用它作为保存最终训练和测试集的路径。由于数据存储在与运行脚本的文件不同的文件夹中,我们需要在文件系统中返回一级,在第二步中访问目标文件夹。我们通过加入“…”来实现这一点以及导致‘的数据文件夹…/generated_data/'。
使用 generated_data 文件夹的路径,我们创建另一个指向数据文件本身的变量,称为 bbc_articles.tsv。由于它是一个制表符分隔值文件(tsv),我们需要添加’ \t '分隔符,以便将数据作为 Pandas Dataframe 加载。
选择要分割的数据(可选)
将数据分成训练集和测试集不需要以下命令。然而,由于我不需要数据集的所有可用列,所以我选择了想要的列,并创建了一个新的 dataframe,其中只有“text”和“genre”列。
分割和保存
现在,我们已经准备好了分割它的数据。幸运的是,sklearn 库的 train_test_split 函数能够处理 Pandas 数据帧和数组。因此,我们可以简单地通过提供数据集和其他参数来调用相应的函数,例如:
- test_size :
该参数表示应该包含在测试分割中的数据集的比例。这个参数的缺省值被设置为 0.25,这意味着如果我们不指定 test_size,那么产生的分割由 75%的训练数据和 25%的测试数据组成。 - random_state :
该参数控制分割前应用于数据的洗牌。通过定义随机状态,我们可以在多个函数调用中重现相同的数据分割。 - 洗牌 :
该参数表示数据在分割前是否需要洗牌。因为我们的数据集是按流派排序的,所以我们肯定要打乱它。否则,训练集和测试集将不会包含相同的类型。
在分割数据之后,我们使用目录路径变量来定义保存训练和测试数据的文件路径。通过将数据帧转换为 csv,同时使用’ \t '作为分隔符,我们创建了制表符分隔的训练和测试文件。
结论
在这篇短文中,我描述了如何加载数据,以便将数据分成训练集和测试集。相应的数据文件现在可以用于训练和评估文本分类器(尽管取决于模型,可能需要额外的数据清理)。
在未来的文章中,我将描述如何建立不同的深度学习模型(如 LSTM 和伯特)来训练文本分类器,这些分类器根据文章的文本来预测文章的体裁。下面是我的文章的链接,在这篇文章中,我使用 FARM 框架为文本分类微调 BERT。
使用最先进的 NLP 模型进行简单快速的迁移学习
towardsdatascience.com](/fine-tuning-bert-for-text-classification-with-farm-2880665065e2)
非常感谢你的阅读和快乐编码!
参考
1d .格林和 p .坎宁安。核心文档聚类中对角优势问题的实际解决方案。ICML 2006。
如何拆分 Shapefiles
切割阿拉斯加附近的西阿留申群岛(它们大多无人居住)
有时您只需要 shapefile 的一部分。根据哪一部分和 shapefile 源,这可能非常简单,也可能不那么简单。例如,前几周,我在绘制美国各州向联邦消费者金融保护局投诉的相对比率(更多此处),我的 choropleth 是这样绘制的:
虽然在这个比例下很难看到,但是西阿留申群岛穿过了 180 度经线,形成了这幅试图将球体展平为矩形的不连贯地图。
解决这个问题有几种选择:
- 将不需要的(同样是无人居住的)面从其多面簇中分离出来
- 对整个地理数据框使用 shapely 函数
.intersects()
- 在 matplotlib 中设置绘图的 x 极限
- 将正/东经多边形转换为负/西经多边形
- 使用 Cartopy 进行不同的地图投影,而不是拆分形状
更多的阿拉斯加,而不是西阿留申群岛。帕克森·沃尔伯在 Unsplash 上拍摄的照片
我们开始吧:
将不需要的(同样是无人居住的)面从其多面簇中分离出来
我想从这个选项开始,因为它解决了一个我一次又一次碰到的更普遍的问题。如何在shapely
和/或geopandas
中拆分多个多边形,然后将它们放回一起用于 choropleths。
首先,我加载 shapefiles 并选择我想要处理的记录,在本例中是阿拉斯加。(谢谢美国人口普查提供的 shapefiles!#opendata)
# import necessary packages
import geopandas as gpd
from matplotlib import pyplot as plt# load shapefile
states_gdf = gpd.read_file('./data/cb_2018_us_state_5m.shp')# select Alaska
alaska_gdf = states_gdf.loc[states_gdf['STUSPS'] == "AK"]
修改前的阿拉斯加地块。
“geometry”列返回一个单项数据帧。您可以通过.values
访问形状良好的几何图形列表。在这种情况下,我们的单记录数据框架有一个项目列表。通过访问第一个值,我们得到了阿拉斯加形状优美的多多边形。
alaska_mp = alaska_gdf['geometry'].values[0]
或者,您可以使用原始状态地理数据框架,但我总是忘记到底有多少层,并且发现使用我的单记录数据框架进行猜测和检查更容易。
alaska_mp_alt = states_gdf.loc[states_gdf['STUSPS'] == "AK",
'geometry'].values[0]
使用多重多边形,您可以像访问列表或数组一样访问每个多边形。
阿拉斯加多重多边形中的第一个多边形。
在其当前形式下,当使用 Shapely 函数(如)时,整个多边形集合(多多边形)被视为一个整体。相交())。为了分别考虑每个面,我将多重面转换为其自己的地理数据框架:
# create the GeoDataFrame
ak_exp_gdf = gpd.GeoDataFrame(alaska_mp)# set the geometry column
ak_exp_gdf.columns = ['geometry']
现在我们有了一个地理数据框,其中每一行都是一个多边形,它们共同构成了阿拉斯加,我们可以根据我们想要或不想要的位置来过滤这些地理数据框了。我们需要制作一个形状优美的多边形,用来判断和过滤阿拉斯加的每一片土地。我们需要一个多边形来覆盖你想要(或不想要)的所有区域,我们将使用.intersects()
或你选择的另一个 shapely 函数来分类你的形状。
多边形是用一列点/顶点创建的。最后一个点会自动连接到第一个点,因此您不需要自己闭合回路。
from shapely.geometry import Polygon# create polygon that covers Alaska up to the 180th Meridian
target_poly = Polygon([(-180, 50), (-180, 75),
(-100, 75), (-100, 50)])
现在我们可以使用这个多边形和 shapely/geopandas 的.intersects()
进行过滤。
western_isles = ak_exp_gdf[al_exp_gdf.intersects(target_poly) ==
False].copy()
eastern_ak = ak_exp_gdf[al_exp_gdf.intersects(target_poly)].copy()
阿拉斯加东部的地块
厉害!!!
照片由 McKayla Crump 在 Unsplash 上拍摄
将面的地理数据框架合并为多面
现在我们有了感兴趣的阿拉斯加多边形,我们准备将此几何图形放入我们的州地理数据框架中。我们使用“by”参数,用.dissolve()
将一个多边形的数据帧组合成一个或多个多多边形。(我仍然不明白让“溶解”感觉像是“粘合”或“结合”的同义词的框架——也许我们正在溶解边界?)
# add a column to groupby
eastern_ak['STUSPS'] = 'AK'# combine polygons/records into a single multipolygon/record
alaska_trimmed = eastern_ak.dissolve(by='STUSPS')# add this new multipolygon in place of the old alaska multipolygon
states_trimmed = states_gdf.copy()
states_trimmed.loc[states_trimmed['STUSPS'] == 'AK', 'geometry']
= alaska_trimmed['geometry'].values
我们准备好了!
修剪过的美国地图。充分披露:我还修剪关岛,北马里亚纳群岛联邦,美属萨摩亚出这个阴谋。
这是一个包含阿拉斯加的 choropleth 示例——水域面积与陆地面积的比率。阿拉斯加的巨大面积确实让我们很难看到东部的一些州,但控制局面很好,可以自由决定是否(以及如何)通过修剪来包含不同的形状。
在整个地理数据框上使用匀称的.intersects()
您也可以修改几何图形,而无需将多重多边形分解为单独的多边形。这种方法确实有其特殊性,但是代码行要少得多。请注意,使用GeoDataFrame.intersection(*shape*)
会返回一系列几何图形,而不是添加了新信息的原始地理数据框。您需要添加或替换一个列来将此信息存储在现有的地理数据框中。
from shapely.geometry import Polygon# create a polygon with the desired dimensions of the map
desired_map = Polygon([(-180, 80), (-60, 80), (-60, 15),
(-180, 15)])# create a new copy of the states GeoDataFrame for this example
states_trimmed_v3 = states_gdf.copy()# get the intersection of the states geometries with the desired map states_trimmed_v3['geometry'] = states_gdf.intersection(desired_map)
如果你试图直接.plot()
这个几何集合,你可能会得到一个TypeError: ‘Polygon’ object is not subscriptable
。当您有一些记录与您的相交几何不重叠时,就会发生这种情况,在我们的示例中,就是太平洋地区。在这种情况下.intersection()
返回一个空多边形。我的解决方案是在绘图前过滤这种情况。
states_trimmed_v3[states_trimmed_v3['geometry'] != Polygon()].plot()
我们得到了与上面相同的结果,不需要找到令人讨厌的形状,分割多重多边形,然后将多边形融合成一个单一的多重多边形。根据您的用例,这绝对是一个好的选择。
美丽的阿拉斯加天空。照片由麦克凯拉·克伦普在 Unsplash 上拍摄
在 matplotlib 中设置绘图的 x 极限
另一个简单的选择是使用matplotlib
的图形界面来删除任何不想要的区域。
fig, ax = plt.subplots(figsize=(15,10))
alaska_gdf.plot(ax=ax)
ax.set_xlim(-180, -128)
使用 matplotlib 的绘图选项 ax.set_xlim()修剪阿拉斯加
将正/东经多边形转换为负/西经多边形
如果你想保留投影和阿留申群岛西部,你可以使用.translate()
将这些多边形的 x 值移动-360°。该选项使用上文描述的分割多多边形的技术
# shift the western isles by 360 degrees
western_isles_shifted = western_isles.translate(xoff=-360)# convert to GeoDataFrame
west_ak_shift_gdf = gpd.GeoDataFrame(western_isles_shifted)
west_ak_shift_gdf.columns = ['geometry']# add 'STUSPS' column
west_ak_shift_gdf['STUSPS'] = 'AK'# combine the western and eastern parts into the same dataframe
ak_shifted_actual_gdf = west_ak_shift_gdf.append(eastern_ak,
ignore_index=True)# combine/dissolve into a single MultiPolygon
ak_shifted_actual_dissolved =
ak_shifted_actual_gdf.dissolve(by='STUSPS')
这会生成 x 值为-190 到-125 的阿拉斯加。在绘图时,您可能需要调整 x 刻度标签,以符合传统的-180°到+180°约定。
fig, ax = plt.subplots(figsize=(15, 12))
ak_shifted_actual_dissolved.plot(ax=ax)# get the locations and labels of the x-ticks
locs, labels = plt.xticks()# set the first label in labels to 170 instead of -190
labels[1] = '170'# set the x-ticks with new labels (keeping the locs)
plt.xticks(locs, labels)
阿拉斯加和所有的阿留申群岛。
注意:我试图将整个美国移动+30 °,但这只改变了 x 轴上的 x 刻度值,而没有将地图最右边的部分移到左边。
对 Cartopy 使用不同的地图投影
或者,您可以使用Cartopy
根据自己的喜好改变地图投影。我喜欢这个选项!它允许您将地理空间数据调整到对项目最有意义的视图。
首先,用conda install -c conda-forge cartopy
安装或查看完整安装指南。请注意,我在 conda-forge 通道上也安装了 geopandas 将所有这些包及其依赖项安装在同一个通道上可能很好。
那你准备好了!基本使用与上述相同的投影(平板托架):
# set figure size
fig = plt.figure(figsize=(15, 12)# set axis with desired projection
ax = plt.axes(projection=ccrs.PlateCarree())# add shapes, indicating their original projection
ax.add_geometries(states_gdf['geometry'],
crs=ccrs.PlateCarree())# add gridlines
gl = ax.gridlines(crs=ccrs.PlateCarree(), draw_labels=True,
linewidth=.5, color='gray', alpha=0.5)# display map
plt.show();
美国地图与卡雷板投影。
你可以在这里查看所有的预测。在我的例子中,允许你设置视图中心的投影正是我所寻找的。
# set desired projection/view
ax = plt.axes(projection = ccrs.Orthographic(central_longitude=-100,
central_latitude=40))# add your shapes (indicating their existing projection)
ax.add_geometries(states_gdf.geometry, crs=ccrs.PlateCarree())# add coastlines and gridlines for context
ax.coastlines(linewidth=.5)
ax.gridlines()
未用正交投影修剪的美国
您还可以使用ax.set_extent(*xmin, ymin, xmax, ymax*)
聚焦于特定区域。
若要调整几何图形的颜色,请使用各种面颜色分别添加它们。例如与上述相同的 choropleth:
from matplotlib.colors import Normalize# value normalization for the color map
values = list(states_trimmed_v2['water:land'])
norm = Normalize(vmin=min(values), vmax=max(values))# select color map
cmap = plt.cm.get_cmap('viridis')#create chorpleth: set fig and ax projection
fig = plt.figure(figsize=(15,15))
ax = plt.axes(projection = ccrs.Orthographic(central_longitude=-100, central_latitude=40))# add each state to the ax with its appropriate facecolor
for state_i in states_trimmed_v2.index:
geom = []
geom.append(states_trimmed_v2.loc[state_i, 'geometry'])
facecolor = cmap(norm(states_trimmed_v2.loc[state_i, 'water:land']))
ax.add_geometries(geom,
ccrs.PlateCarree(),
facecolor=facecolor,
edgecolor='grey',
linewidth=.2)
ax.set_title('States By Water Area to Land Area Ratio', fontsize=20)
ax.coastlines(linewidth=.2)
ax.gridlines()
带有卡通图案的 Choropleth
有关更多信息,请查看以下资源:
- 使用地理空间数据:这篇博文(由你的真实作者撰写)
- Cartopy 简介:由 geohackweek 发布
在这里找到 GitHub 回购。编码快乐!
如何识别数据骗子
识别骗子和中和他们的蛇油的提示
你可能听说过分析师、 ML/AI 工程师和统计员,但你听说过他们的高薪表亲吗?认识一下数据江湖骗子!
受到有利可图的工作的诱惑,这些叫卖者给合法的数据专业人士带来了坏名声。
图片:来源
【赶时间?向下滚动查看底部的快速摘要。]
数据骗子无处不在
您的组织很可能已经窝藏这些骗子多年,但好消息是,如果您知道要查找什么,他们很容易识别。
数据骗子非常善于隐藏在众目睽睽之下,以至于你甚至可能已经是一个了,而你却没有意识到这一点。啊哈!
第一个警告信号是未能理解分析和统计是非常不同的学科。我将在下一部分给你一个简要的概述,但是如果你想更深入地理解它,我在这里写了一整篇文章。
不同学科
统计学家接受的训练是推断数据之外的东西,而分析师接受的训练是探索数据集内容。换句话说,分析师对数据中的内容做出结论,而统计学家对数据中的内容做出结论。
分析师帮助你提出好的问题(假设生成),而统计学家帮助你得到好的答案(假设检验)。
也有奇特的混合角色能够身兼两职…但他们不会同时身兼两职。为什么不呢?数据科学的一个核心原则是,如果你在处理不确定性,那么使用相同的数据点来生成假设和进行测试是无效的。当你的数据有限时,不确定性迫使你在统计和分析之间做出选择。(此处 找到我的解释 )。)
没有统计数据,你就无法知道你刚刚形成的观点是否站得住脚。
没有分析,你就像瞎飞一样,几乎没有机会驯服你未知的未知。
这是一个艰难的选择!当你发誓放弃知道你的新观点是否站得住脚的满足感时,你会睁开眼睛寻找灵感吗?或者你会冷汗直流,祈祷你选择问的问题——在没有任何数据的情况下独自沉思——值得你即将得到的严谨答案(统计)吗?
兜售后见之明的人
江湖骗子摆脱这种困境的方法是忽略它,在薯片中找到猫王的脸,然后假装惊讶于同一个薯片看起来像猫王。(统计假设检验的逻辑可以归结为一个问题:我们的数据是否足以让我们惊讶到改变主意。如果我们已经看到了数据,我们怎么会对它们感到惊讶呢?)
你觉得这些像兔子和猫王的肖像吗?或者总统肖像?关于这个话题的乐趣,请看我的相关文章这里。
每当江湖骗子找到一个模式,得到灵感,然后测试相同的 数据以得到那个相同的模式发布结果,并在他们的理论旁边加上一两个合法化的 p 值,他们实际上是在骗你(也许也在骗他们自己)。那个 p 值没有任何意义,除非你在查看数据之前先确认你的假设。
江湖骗子模仿分析师和统计学家的行为,却不理解其原因,这给整个数据科学领域带来了坏名声。
真正的统计学家总是发号施令
由于统计行业在严谨推理方面近乎神秘的声誉,数据科学领域的“蛇油”销量创下了历史新高。用这种方式作弊很容易不被抓到,尤其是如果你不知情的受害者认为这都是方程式和数据的问题。数据集就是数据集,对吧?不对。你如何使用它很重要。
数据集就是数据集,对吧?不对。你如何使用它很重要。
幸运的是,对于他们的潜在目标,你只需要一条线索就能抓住他们:江湖骗子兜售马后炮。
一个江湖骗子兜售后见之明——从数学上**重新发现他们已经知道存在于数据中的现象——而一个统计学家则提供远见测试。
与江湖骗子不同,优秀的分析师是思想开放的典范,总是将鼓舞人心的见解与提醒相结合,提醒人们观察到的现象可能有许多不同的解释,而优秀的统计学家在做出判断之前会小心谨慎。
优秀的分析师是思想开放的典范。不像江湖骗子,他们不会在数据之外下结论。
分析师产生灵感
分析师可以免于发号施令……只要他们的数据不超过。如果他们想对自己没见过的东西发表看法,那就是另一回事了。他们应该摘下他们的分析师帽子,戴上他们的统计学家头盔。毕竟,不管你的正式职称是什么,没有规定说你不能想学就学。别把他们搞混了。
江湖骗子如何测试假设?迷因:来源。
擅长统计并不意味着你擅长分析,反之亦然。如果有人试图告诉你,检查你的口袋。如果那个人告诉你,你被允许对你已经研究过的数据进行统计推断,检查你的口袋两次。
躲在花哨的解释后面
如果你在野外观察数据骗子,你会注意到他们喜欢编造一些奇特的故事来“解释”观察到的数据。越学术化越好。不要介意这些故事只是(过度)符合事后的数据。
当江湖骗子那样做时——让我直截了当地说吧——他们是在胡扯。再多的等式或相当的武断也无法弥补这样一个事实,即他们没有提供任何证据证明他们知道自己在谈论的数据之外的东西。
不要被他们的解释有多花哨所打动。为了进行统计推断,他们必须在看到数据之前做出决定。
这相当于炫耀他们的“通灵”能力,首先偷看你拿到的手牌,然后预测你手里拿的是什么……不管你手里拿的是什么。准备好接受他们的小说吧,是你的面部表情泄露了秘密。那是 后知后觉的偏见 而数据科学职业就是用它塞到腮里的。
分析师说,“你刚才出的是一张方块皇后。”统计学家说,“在我们开始之前,我在这张纸上写下了我的假设。我们来玩玩,观察一些数据,看看我说的对不对。”江湖骗子说,“我知道你会一直玩方块皇后,因为……”(机器学习说,“我会不断提前调用它,看看我做得如何,一遍又一遍,我可能会调整我对有效策略的反应。但我会用算法来做,因为手动跟踪一切很烦人。”)
江湖骗子-证明你的生活
当没有足够的数据时,你不得不在统计和分析之间做出选择。
数据分割是每个人都需要的文化快速解决方案。
幸运的是,如果你有足够的数据,你有一个很好的机会利用分析和统计数据而不作弊。你也拥有对抗骗子的完美保护。它被称为数据分割,在我看来,这是数据科学中最强大的想法。
永远不要认真对待未经检验的意见。相反,使用一堆测试数据来找出谁知道他们在谈论什么。
为了保护自己免受骗子的攻击,你所要做的就是确保你让一些测试数据远离他们窥探的目光,然后把其他一切都当作分析(不要当真)。当你面对一个你可能会相信的理论时,用它来发号施令,然后打开你的秘密测试数据,看看这个理论是否是胡说八道。就这么简单!
确保您不允许任何人在探索阶段查看测试数据。坚持探索性的数据。测试数据不应用于分析。迷因:来源
这是一个巨大的文化转变,在“小数据”的时代,你必须解释你如何知道你所知道的,以便说服人们——脆弱地——你可能确实知道一些东西。
同样的规则也适用于 ML/AI
一些冒充 ML/AI 专家的江湖骗子很容易被发现。你会像抓其他糟糕的工程师一样抓到他们:他们试图构建的“解决方案”反复失败。(早期的警告信号是缺乏行业标准编程语言和库的经验。)
但是那些生产看起来工作正常的系统的人呢?你怎么知道是否有可疑的事情发生?同样的规则也适用!江湖骗子是一个阴险的角色,他向你展示他们的模型表现得有多好……基于他们用来制作模型的相同数据。*face palmT5***
如果你已经建立了一个疯狂复杂的机器学习系统,你怎么知道它有没有用?你不…直到你证明它对以前没有见过的新数据有效。
如果你在制作数据之前已经看过了,那就很难说了。
当你有足够的数据来拆分时,你不需要用漂亮的公式来证明你的项目(这仍然是一个过时的习惯,我在任何地方都能看到,不仅仅是在科学领域)。你可以说,“我知道它有效的原因是,我可以获得一个我以前没有见过的数据集,我可以准确地预测那里将会发生什么……并且是正确的。一遍又一遍。”
掌握你的统计数字,或者保持谦逊
套用经济学家保罗·萨缪尔森的一句妙语:
江湖骗子成功预测了过去五次衰退中的九次。
我对数据骗子没有耐心。你认为你“知道”一些关于猫王薯片的事情吗?我不在乎你的观点有多符合你的旧芯片。你的解释多么花哨,我不以为然。让我看看你的理论/模型在你从未见过的一大堆新芯片中是有效的(并且一直有效)。这是对你观点勇气的真正考验。
图片:来源
给数据科学专业人员的建议
数据科学专业人士,如果你想被理解这种幽默的人认真对待,就不要再躲在花哨的方程式后面支撑你的人类偏见。让我们看看你有什么。如果你想让那些“明白”的人将你的理论/模型视为不仅仅是一首鼓舞人心的诗歌,就要有勇气在一个全新的数据集上展示它有多好……在证人面前!
给领导者的建议
领导者,拒绝认真对待任何数据“见解”,直到它们在新数据上得到检验。不想努力吗?坚持分析,但不要依赖这些见解——它们是脆弱的,没有经过可信度检查。此外,当您的组织拥有大量数据时,将拆分作为您的数据科学文化的核心部分,甚至通过控制对指定用于统计的测试数据的访问,在基础架构级别强制执行拆分,也没有什么坏处。这是将蛇油销售企图扼杀在萌芽状态的好方法!
更多坏把戏
如果你想看到更多江湖骗子不怀好意的例子,这条 Twitter 帖子很棒。
摘要
当数据太少而无法分割时,只有一个数据骗子试图严格地遵循灵感,通过数学方法重新发现他们已经知道存在于数据中的现象,并声称他们的惊喜具有统计意义,兜售后见之明。这将他们与处理灵感的开明分析师和提供远见证据的一丝不苟的统计学家区分开来。
当数据充足时,养成分割数据的习惯,这样你就可以两全其美而不作弊了!确保对原始数据的不同子集分别进行分析和统计。
- 分析师为你提供开明的灵感。
- 统计学家为你提供严格的测试。
- 江湖骗子向你提供扭曲的马后炮,假装是分析加统计。
感谢阅读!人工智能课程怎么样?
如果你在这里玩得开心,并且你正在寻找一个为初学者和专家设计的有趣的应用人工智能课程,这里有一个我为你制作的娱乐课程:
在这里欣赏整个课程播放列表:bit.ly/machinefriend
与凯西·科兹尔科夫联系
让我们做朋友吧!你可以在 Twitter 、 YouTube 、 Substack 和 LinkedIn 上找到我。有兴趣让我在你的活动上发言吗?使用表格联系。
如何使用谷歌云平台启动数据科学项目
利用谷歌云平台(GCP)服务创建 Python Jupyter 笔记本工作环境
什么是数据科学项目?
我的导师曾经告诉我,数据科学是关于:
1.从数据中获得洞察力
2.将这些见解传达给你的客户
沟通对于几乎每个数据科学家来说都是至关重要的,在所有的沟通方式中,展示代码和可视化将是最直接和最常见的方式。和这个领域的大多数人一样,我在我的数据科学项目中使用了很多笔记本/减价品。因此,我很有信心地说,笔记本风格的工作流,使您能够在编写新代码时看到代码的所有结果,将是进行数据科学项目的一个很好的环境。
为什么要用谷歌云平台?
GCP ( 谷歌云平台)是谷歌提供的云计算服务。对于那些不熟悉云服务的人来说,它基本上是使用网络连接到你租用的远程机器,在那台机器上进行计算并发回结果。就像租车一样。显然,使用云计算服务:
1.给你一台性能更好的机器来完成你的计算。(当然,如果你付够钱的话)
2.通过租赁而不是购买超级计算机来降低计算的实际成本。(就像租车一样不是吗)
3.解放您自己的笔记本电脑,这样您就可以一边玩视频游戏,一边进行繁重的并行计算。
现在实际上有很多公司提供云服务。AWS、Azure、GCP,应有尽有。然而,谷歌为第一年使用的注册用户提供 300 美元的积分。有了它,你可以租用一个简单的实例一整年,或者尝试一个巨大的实例几天。因此,对于任何不熟悉云服务并且在尝试之前不愿意付费的人来说,这是一个不错的选择!
在下面的案例中,我将展示如何在使用谷歌云平台的 Python 下使用 Jupyter Notebook 启动一个数据科学项目。
1.注册谷歌云平台
首页上应该有一个邀请,要求您激活 300 美元的试用版。输入你的信息和支付信息(只是为了验证你不是机器人,在你用完你的信用后不会有收费或订阅),你就可以走了!
2.创建新的项目和实例
如果你刚到 GCP,你应该已经有一个自动生成的项目,叫做“我的第一个项目”。您可以稍后在项目设置中更改项目名称。如果你更喜欢创建一个新的,那就用谷歌的这个教程吧。
创建虚拟机实例
现在选择左侧栏—计算—计算引擎—虚拟机实例。您现在应该没有任何实例,请单击“创建”。
设置实例第 1 部分
- 名字:你可以选择给你的实例命名
- Region and Zone :这是您的实例的物理位置。你会想选择一个离你比较近的地点,但是只要和你在同一个洲就不会有太多的差异。
- 机器配置:这是最重要的部分。除非明确知道自己需要什么,否则不必指定 CPU 系列、平台、GPU。默认情况下,它将选择 n1-standard-1 机器,具有 1 个内核和 3.75GB RAM。你可以向下滚动机器类型并选择你想要的,或者选择自定义,这样你就可以分别输入 CPU 内核和内存的数量。
- 启动盘:英文中是指你选择的操作系统。我一般选择默认的 Debian GNU/Linux 9 (stretch)。和 CPU 一样,不知道自己需要什么就不想换。我还发现 Linux 上的深度学习很有用,因为它预装了许多重要的软件包,尽管如此,我还是选择了默认的,这样我就可以跟踪我正在使用的软件包的具体版本。
设置实例第 2 部分
在这里,您可以选择 API 访问和防火墙设置。
将服务帐户保留为默认值,并选择“ 允许完全访问所有云 API”,以便在使用新 API 时节省大量设置 API 的工作。在防火墙 中允许 HTTP 和 HTTPS 流量 。
设置实例第 3 部分
如果您点击 【管理、安全、磁盘、联网】 您可以选择进一步的设置。通常情况下,你不想改变这些。但是,您可以在可用性策略中选择开启 抢占 。抢占性就像 AWS 中的 Spot 实例一样:
- 它的价格要低得多,大约是正常价格的 20%到 30%
- 它只持续 24 小时
- 它可以在你运行的任何时候被关闭
所以,如果你正在做的项目不需要连续运行几个小时并且在 24 小时内完成工作也没问题,这就是省钱的方法。现在一切都设置好了,点击 create 来创建您的第一个 GCP 实例。
3.设置外部 IP 和防火墙
设置网络第 1 部分
首先进入左侧栏——网络——VPC 网络——外部 IP 地址。
设置网络第 2 部分
在该类型下,您应该会发现您的新实例是短暂的。点击它并将其更改为静态,随你怎么命名。
现在进入左侧栏—网络— VPC 网络—防火墙规则—创建防火墙规则。
随便你怎么命名,在目标中选择“ 网络中的所有实例 ,放入“ 0.0.0.0/0 ”
在源 IP 范围中,选择 指定协议和端口 ,在***【TCP***中输入 8888 。
然后单击创建。
4.连接到您的实例
现在回到左侧栏——计算——计算引擎——虚拟机实例。您应该看到您的实例正在运行,名称前面有一个绿色的勾号。单击 SSH 按钮连接到您的实例,这将启动一个自动连接到它的云终端。
连接到您的实例
如果你更喜欢通过你的本地终端或者云外壳来连接它,你将不得不安装 gcloud 并设置Google SDK然后使用 gcloud compute ssh 命令来连接。你可以带着这个教程去。
5.设置您的工作环境
我们正在使用 Linux 系统内置的 Makefile 命令来设置一切。您可以创建自己版本的事物和环境,也可以尝试我的代码作为快速入门。
首先,来自 GCP 的普通 Debian 环境可能没有我们需要的完整的基本工具和软件包:
当提示您是否继续时,输入“y”。
现在做 git 克隆来下载我的快速入门代码:
您可以使用 ls 命令检查下载,它应该只返回您刚刚下载的 MyEnv 。使用 cd 命令转到目录 MyEnv 。
然后运行这三行代码:
6.打开你的 Jupyter 笔记本
首先确保你在正确的目录中,在那里你已经准备好了你的数据,因为一旦你启动一个笔记本,你就不能去父目录。其次,确保你在虚拟环境中,因为你所有的包都被安装在那里:如果你在这个环境中,一个*(。env)* 应该显示在你的名字前面。
然后放进去:
然后回来。现在笔记本已经在运行了,但是你仍然需要自己连接它。打开浏览器,输入下面一行,其中显示在实例页面上,当然没有括号。这应该把你带到好的老 jupyter 笔记本界面。
7.(可选)使用云存储桶传输数据
您还可以选择使用上传按钮直接在实例界面中上传数据。但是,我鼓励您使用 Gcloud Storage Buckets 来完成这项工作,因为它可以轻松连接到您所有的 GCP 项目。
首先,您需要单击这个页面顶部的 Create Bucket。
创建一个桶
注意命名指南,因为每个 bucket 名称必须是唯一的,并且所有名称都是公开可见的。对于位置,您应该考虑存储桶价格以及实例的位置。(例如 US-WEST1 、 US-CENTRAL1 和 US-EAST1 有 5 GB 的免费存储空间,在同一区域内将数据从 bucket 传输到实例是免费的,请参见定价详情此处),以便您根据自己的使用情况获得最佳设置。我倾向于将其他一切都保留为默认设置,以便您可以从日常使用中获得最佳设置。
创建存储桶后,您可以通过单击存储桶中的上传按钮将数据从本地上传到存储桶。
将文件上传到您的存储桶
或者使用 Gcloud SDK 工具自带的 gsutil 函数。代码格式就像 cp 或者 scp 一样。假设您想将 data.csv 从您的主目录上传到 bucket:
现在您已经将数据放入桶中,接下来您应该做的是连接到您的实例,使用相同的 gsutil 函数,并将其传输到您的实例的主目录:
现在,通过第 6 步,您可以打开笔记本,读取数据并继续探索您的数据科学项目!
如何在一个月内开一个机器学习博客
你学了人工智能,现在教它!
我是怎么做到的,你也能做到!
我是深度学习爱好者 Dweep。我已经完成了许多 ML 和 AI 课程,我觉得是时候回报社会了。
MS Paint 的奇迹
因此,我在 Blogger 上开了一个名为LightSpeedAC的博客,向成千上万愿意进入人工智能、机器学习或深度学习的人分享我的知识。我开始写了几篇关于 NNs 的介绍性博客,当然,还有一篇 MNIST 教程。我觉得虽然写一个数据科学或人工智能博客并不太难,而且有一些事情你必须记住。我将与你分享。
我的博客(很棒的 UI,对吧?)
写博客(直觉部分)
对于初学者来说,博客不应该看起来充满了外国词汇和术语。是的,ML 确实有几个可怕的词,然而大多数都意味着惊人的简单事情! 还有,尽量少理论化。我发现人们更有兴趣知道它是如何工作的,然后直接看代码。我特意保留了博客的名字光速以保证趣味性。
另外一个超级重要的事情就是 写你的意思,写你的意思。 如果你的博客标题是零到人工智能英雄,并且你完成了一个 MNIST 教程,那就是完全的点击诱饵!此外,对读者坦诚总是在许多方面有所帮助。
我最后想说的是,一个教一些概念 的 AI 博客,得有代码 !!一个理论性的博客可能更容易写,但是你最终给了他们他们没有办法实现的知识。很明显,代码需要充满注释和解释,因为读者应该能够理解每一行。如果你鼓励读者尝试一些代码行,比如超参数,这总是有帮助的。
一个额外的提示,让你的博客读者友好,是使用语法,以确保没有污点的语法。这比你想象的更重要!我写了一篇关于语法对博客作者的重要性的博客。
写什么?
写一些人们在 之前没有写过的东西总是好的,尽管这并不总是可能的。我知道有成千上万的 MNIST 教程,但我仍然写了另一个。 为什么? 因为我感觉他们都没有我这样的逐行代码注释。还有一次,我写了一篇关于激活函数的博客。同样,我知道有数百个,其中一些是关于数据科学的,内容非常好。然而他们中的大多数人解释了这个功能。另一方面,我做了一个比较,并详细说明了在什么情况下使用什么激活。因此,我写了这本激活功能手册。找到机会并抓住它们!
怎么宣传?
自然,这将是下一个问题。我想这个问题没有明确的答案。我采取了许多不同的方法,并定期检查哪些可行,哪些不可行。
所有博主获取有机流量的地方
我首先尝试的是 Quora 。这有两个故事。我的合著者(实际上是我的兄弟)也在我们的博客中尝试了同样的方法。我们俩几乎是同时开始的。18 天后, 我的 4k 浏览量 越来越多,我的 80 个回答带来了不错的流量,而我的哥哥 面临着被 Quora 封禁两周的处罚。
我在 2 周内获得了 4.1K 的浏览量!
这些截然不同的结果的原因是什么?
我在 Quora 上的回答是真实的,只有不到 40%的人有我博客网站的链接。我保证读者会希望 去我的网站更好地学习。我不是在发垃圾信息,只是在帮忙。
如你所料,我哥哥的邮件是垃圾邮件。
*如果问题是“*好的博客是什么样子的?”
他会回答“一个好的博客看起来像这个”
图片来自 Shutterstock.com two mine 公司
通过那个故事,我的意思是让你明白 如何从 Quora 获得流量, 和 如何获得封禁。
我做的第二件事,也是更有用的一件事,是发电子邮件。我给很多公司发了邮件,请求合作机会。有些人回答了,有些人没有。但是最好的部分是每个公司给的反馈。而且我说的是 Coursera、Grammarly 甚至 deeplearning.ai 这样的大公司! 这些邮件帮助我显著提高了市场占有率。
并维护它
同样,Paint 女士也给人留下了深刻的印象:)
我定期写博客,比如每两天一次,这有助于提高我的存在感。此外,我 删除了 几个表现不佳的博客,以帮助维持内容质量。
还有,评论
如果你开始写博客,那太好了!下面用链接评论!
免费的任何合作,项目帮助和集成!
如有任何关于 TensorFlow、Keras、TFjS 或 Python 的疑问或项目,请发邮件至我的 Gmail。
谢谢,祝您有美好的一天!
如何开始一个机器学习项目
做机器学习项目的分步指南
在 a 之前的文章中,我们讨论了很多关于什么是机器学习,机器学习是如何工作的,以及机器学习实现的例子。如果你是机器学习的新手,你可能会问,你如何开始一个机器学习项目?
这可能很多人都经历过,包括我。我读了很多书,但仍然不知道从哪里开始。我发现,学习启动机器学习项目的最佳方式是通过设计和完成小项目。因为要做大,我们必须从小做起。但是这个过程因人而异。
在这篇文章中,我将根据我的经验分享从事机器学习项目的几个阶段。
理解问题
开始一个项目的最初阶段是知道我们将解决什么问题。这适用于任何项目,包括机器学习项目。当然,一切都从问题开始,因为如果没有问题,就没有什么需要解决的。
我们必须确定我们要解决的问题。例如,我们希望实时了解用户在社交媒体上对某个产品的看法。但是因为存在的很多意见,完全靠人类是不可能做到的。
然后我们也确定目标。由此,我们可以确定目标是创建一个机器学习系统来实时分类用户意见(情感分析)并预测未来意见的情感。
如果你不能解决一个问题,那么有一个更容易的问题你可以解决:找到它乔治·波利亚
建议你学习一下计算思维中的分解,就是把复杂的问题分解成更小的部分的过程。通过分解,起初看起来势不可挡的问题变得更容易管理。
数据采集
米卡·鲍梅斯特在 Unsplash 上的照片
如果你已经找到了一个问题和你想要解决的目标,那么下一步就是获取所需的数据。有许多方法可以收集数据。我将解释其中的一些。
- 第一种方式是在网上下载开源数据如 Kaggle 、 Google dataset 、 UCI 机器学习等。但你也必须注意使用这些数据集的局限性,因为有些数据集只能用于个人需求或仅用于研究目的。
- 接下来的方式就是在网站上做抓取/抓取。比如你想检索社交媒体上仇恨言论评论的数据,可以在社交媒体 Twitter 、 Instagram 等上抓取。或者,如果你需要来自新闻网站的数据,你可以在新闻网站上做网络搜集。
抓取网站的简单方法
towardsdatascience.com](/scraping-a-website-with-4-lines-using-python-200d5c858bb1)
在某些情况下,您可能需要标记数据,特别是如果您通过 web 爬行/抓取获得数据集,并且您将使用的机器学习方法是监督学习。必须考虑的是标注数据时可能出现的偏差。这可能会影响模型的性能。
如果你想验证你标记的数据,你可以向他们领域的专家寻求帮助。例如,如果您在健康领域创建了一个数据集,那么您可以验证您为医生创建的数据。
数据准备
我们得到需要的数据后,下一步就是在进入训练阶段前准备数据。这是为什么呢?
让我们比较一下作为烹饪材料的数据。我们在烹饪之前,肯定会先对原料进行处理,比如清洗、清洁、去除不必要的成分、切块等。,不可能把原料放进煎锅里。
数据也是如此。我们需要准备数据,以便在进入训练阶段时,数据不包含会影响所创建模型的性能的噪声。
在进一步输入之前,请注意有 2 种类型的数据,即结构化数据和非结构化数据。结构化数据是一种数据模型,它组织数据元素并标准化它们之间的关系。通常,这种类型的数据以表格、JSON 等形式出现。而非结构化数据是没有预定义的数据模型或者没有以预定义的方式组织的信息。这种类型的数据通常是自由文本、图像、信号等形式。
结构化数据与非结构化数据
以下是准备数据时常用的一些流程。
- 数据清理用于消除不需要的数据或特征。对于每种数据类型,处理方式是不同的。在结构化数据中,它用于清除不一致的数据、缺失值或重复值。而在非结构化数据中,例如在文本的情况下,它用于清除在形成模型的过程中实际上不太必要的符号、数字、标点符号或单词。
- 数据转换用于改变数据结构。这对于非结构化数据(例如文本)的情况尤其必要,因为基本上分类器模型不能接受文本输入,所以它必须首先被转换成另一种形式。一些常用的方法有 PCA、LDA、TF-IDF 等。
另一件同样重要的事情是探索性数据分析(EDA)。EDA 的功能是对数据进行初步调查,在统计摘要和图形表示的帮助下发现模式、发现异常、进行假设测试并检查假设。
系统模型化
罗马卡夫在 Unsplash 上拍摄的照片
这可能是你最期待的部分。在这个阶段,我们会做一个机器学习模型。正如我们在上一篇文章中讨论的那样,机器学习有几种方法,即监督学习、非监督学习和强化学习。我们可以根据之前观察到的数据/问题来确定我们采取的方法。
人工智能、机器学习和深度学习的简单解释以及它们之间的区别
towardsdatascience.com](/artificial-intelligence-machine-learning-and-deep-learning-what-the-difference-8b6367dad790)
我的其他建议是,在建模之前先找出每种机器学习方法的优缺点,因为这样会节省很多时间。对于某些数据特征,每种方法都有优点和缺点。例如,如果首先对输入进行规范化,有些方法可以很好地工作;如果数据太大,有些方法会导致过度拟合;还有一些方法需要非常大的数据。
不要让你花时间去尝试一个又一个的方法来产生最好的结果。因为通常,一个机器学习方法有很多我们可以修改的参数。例如,如果我们想使用神经网络建立一个模型,我们可以改变学习率参数、隐藏层的数量、使用的激活函数等。
也许很多人也建议使用深度学习,因为它在几次实验中一直被证明可以得到很好的结果。但在此之前,先想想案例是否真的需要深度学习。不要用深度学习只是为了跟风。因为需要的成本非常大。
如果有可能使用传统的机器学习方法,那么就使用这种方法。但是,如果案件非常复杂,无法用传统的机器学习方法处理,那么你可以使用深度学习。
评价
最后一个阶段是评估过程。如果你正在训练的模型的性能没有产生好的结果,你当然不希望。尤其是当你的预测模型有很多错误的时候。
来源:https://twitter.com/ipfconline1/status/1261733186087911427
确定我们正在制作的模型是否好的最快方法之一是测量它的性能。有几种方法来计算性能,包括准确性、f1 测量、轮廓得分等。评估你的模型的另一种方法是和他们领域的专家一起验证你的模型。
如何开始一个 NLP 项目
NLP 数据集的注意事项和基本探索性数据分析
自然语言处理是人工智能中一个令人兴奋的领域。它的应用非常广泛,从理解情感到主题分析,甚至生成供人类使用的原始文本等等。然而,在开始实施这些分析之前,为了确保项目的成功,必须做一些基本的准备工作。这包括选择要摄取的文本,以及一些必要的单词转换,以使您的文本为进一步的调查做好准备。
快速提示:这是而不是作为主题的 NLP 介绍,或者如何开始一个基本项目。你可以在这里和这里找到开始学习 NLP 的优秀指南。
首先,人们需要决定他们想要分析什么文本。乍一看,这似乎是显而易见的,但是还需要进行一些更精细的技术考虑。对一些人来说,这些问题的答案将是他们想要的结果所必需的。例如,当检查自由文本调查输入时,很明显调查回答将构成您的语料库。在其他情况下,这可能不太明确。
这里有几个有用的术语需要解释。语料库指在分析中检查的文本集合。这个术语可以从一个句子扩展到每种语言中的每个单词。有时,一个语料库可以细分为文档,这些文档是更小的语料库,通常封装了一个想法或主题。文档可以小到一条推文,也可以大到一本书。将一个语料库划分为多个文档并不是每个 NLP 任务都必须的,但是这对于比较不同的文档很有用。NLP 中最小的测量单位是一个令牌。令牌是文档中的一个单词。一个词汇表是语料库中存在的不同标记的数量。一些技术,例如手套单词嵌入,随着词汇量的增加而增加时间复杂度,而其他技术随着更大的语料库而增加复杂度。一个人的用例将决定哪种分析和语料库规模最有意义。
除非你有一个大的计算集群和无限的时间,否则你不可能查看每一条推文。有意义的是选择一个时间段作为你分析的基础。一个人对时间段的选择将基于几个因素:你的时间窗口的大小和它开始的时间。这两个参数都会影响分析中包含的单词/文档的数量。如果不做一些探索性的数据分析,你很可能不知道单词大小随时间的分布,这些数据分析可以揭示随着你增加分析时间,语料库的大小是如何增长的。一旦你知道了语料库的大小是如何增长的,你就能够根据你可用的计算资源做出明智的决定。
我进行了一个样本分析来衡量语料库和词汇的增长。我挖掘了我最喜欢的宠物项目数据集:Reddit。我使用名为 praw 的库从 Reddit API 获取评论。然后我把增长绘制成一系列。下面是我写的一个要点,以跟踪更多帖子的字数。我还包括了在发布时运行代码时输出的图表。
随着更多帖子的添加,测量语料库和词汇增长的示例分析
我们看到语料库呈线性增长,而词汇库呈对数增长
看上面的图表,我们可以看到语料库以大致线性的方式增长,而词汇则以对数的方式增长。利用这些知识,人们现在可以做出明智的决定,在自己的分析中包括多少 Reddit 帖子。进一步分析的一种方法是计算几个不同子社区的这些值,看看哪个社区的词汇最丰富,哪个最冗长。
一旦确定了创建语料库的参数,在开始分析之前还需要进行预处理。原始的自然语言有许多属性会使分析变得模糊不清。常见的第一步是删除停用词;没有提供丰富语义的常用词,反而添加了比信号更多的噪声。大多数 NLP 库都有一个停用词列表,你可以利用它来清理你的语料库。下面是一个使用空间库移除停用词的例子。
用空格删除停止字
这个例子让 spaCy 接收每个评论,然后将评论转换成包含令牌的 pared 文档。对文档进行迭代会产生单独的标记,我们可以检查这些标记,以确定是否应该在分析中考虑它们。上面的要点删除了停用词,但人们也可以轻松地删除数字或进行基本的文本转换,如引理或词干。SpaCy 在第一次解析每个文档时会执行大部分这种分析。下面是 spaCy 提供的令牌属性列表。
另一个常见的步骤是处理文本中的数字数据。一般来说,删除数字是很常见的,因为它们本身通常不提供任何语义。要删除数字和停用词,可以使用正则表达式 (regexes)或大多数 NLP 库中的内置函数。例如,在 spaCy 中,标记具有可以过滤的属性“is_alpha ”,类似于上面要点中的停止词。
但是,您可能希望保留数字的特定上下文。例如,一些数字序列具有特定的含义,如 IP 地址或 MAC 地址。如果数据集包含这样的信息,可以使用掩码用预先确定的标记(如“IP_ADDRESS”)替换数字实体的所有实例。这将保留数字实体的语义,同时移除噪声数字。在这里,简单的正则表达式替换通常是最好的工具。
屏蔽不仅对数字实体有用。它可以用于任何想要保留语法意义而删除特定细节的实体。这样做可以从您的数据中删除个人身份信息(PII),这可能是法律或法规的要求,具体取决于您的数据集。回头看看 Reddit,我将演示用标记“USERNAME”屏蔽用户名。幸运的是,r/help上的一个帖子解释说,用户名可以由 3 到 20 个字符组成,通常以“u/”为前缀在下面的要点中,我使用 python 内置的正则表达式库来查找所有 Reddit 用户名并用我们的令牌替换它们。
使用正则表达式的屏蔽示例
这些步骤将为成功的 NLP 项目奠定基础。有无数的工具和技术可以用来总结,提取意义,或任何数量的其他 NLP 任务。我已经提供了一个笔记本,上面有 gists 中列出的所有代码。
如何开始学习生物信息学而不被吓倒(带 R)
使用差异基因表达分析的分步示例
介绍
这篇文章的目标读者是那些希望“闯入”生物信息学领域并拥有 R 经验的人(最好使用 tidyverse )。生物信息学可能是一个听起来很可怕的概念(至少对我来说是这样),因为它是一个如此广阔和快速发展的领域,以至于很难准确定义它是什么。我一直认为生物信息学是一个高度先进的领域,超出了我的能力范围——我需要多年的技术培训才能真正开始做这件事。但是就像所有事情一样,开始做某事实际上并不需要太多时间(不用说,掌握某事确实需要很多年)。
承认我过于简单化,生物信息学本质上是回答生物学问题的电子(或基于数据的)方法。随着更先进的测序技术的出现以及随之而来的统计算法的发展,我们现在可以以前所未有的规模和价格获得生物数据,以及从这些数据中提取洞察力的工具。
在这篇文章中,我的目标是提供一个简单的例子,任何喜欢数据、喜欢与 R 一起工作、对这个领域感兴趣的人,都可以开始在生物信息学领域进行分析。
有大量不同类型的问题和不同类型的生物数据,因此在这篇文章中,我们将使用 RNA-Seq 数据进行差异基因表达分析(DGEA)。简而言之,如果你回忆一下高中/大学生物课,DGEA 会回答不同实验条件下基因表达水平是否有变化的问题,RNA-Seq(RNA 测序的缩写)使用下一代测序来量化给定转录组(所有 RNA 转录本的集合)中的 RNA 数量。我们将从 记录 2 *中获取数据。*本质上是一个由约翰霍普金斯维护的数据库,通过他们的包与 R 接口,用户可以从中查询 RNA-seq read count 数据。计数是与基因的特定区域对齐的测序读数的数量。
请注意,这篇文章是针对初学者的,所以关于 DGEA 内部某些分析步骤背后的动机或关于软件包所有功能的许多细节将不包括在内。但是,我希望一旦你能够成功地做某事,你会感到有力量去学习更多!
设置
因此,让我们首先设置我们的工作空间,包括将我们的库和 RNA-Seq 数据加载到 R 中,这是我们从 retrol 查询的。鉴于我的学术兴趣,我将使用与冠状动脉疾病相关的 RNA-Seq 数据集。在这个特定的数据集中,病例指的是带有 TCF21 基因沉默的冠状动脉平滑肌细胞。retrol 附带一个漂亮的闪亮的应用程序用户界面,在这里你可以搜索你感兴趣的项目,并使用相关的项目 ID 查询数据;但是,在重新计数包中也有一些功能,允许您在不使用应用程序界面的情况下搜索项目。
对于大多数数据分析项目,我喜欢考虑 3 个主要步骤:探索性数据分析、分析和可视化。在我们开始之前,重要的是要注意我已经选择使用 DESeq2 进行这个分析,尽管存在其他使用不同方法进行 DGEA 的包。我们首先必须构建一个用于我们分析的 DESeqDataSet 对象。这个对象基本上包含三个部分:colData
包含样本信息,rowRanges
包含基因组范围信息,assay
包含计数矩阵。
图片作者。
我们使用dds <- DESeq2::DESeqDataSet(rse_gene, design = ~ case)
来生成我们的 DESeqDataSet 对象,其中case
指定样本是控制样本还是实验样本。让我们通过做一些探索性的数字来弄脏我们的手。
探索性数据分析
首先,我们可以使用欧几里得距离来评估样本之间的总体相似性。这背后的细节就不在本文讨论了。重要的是澄清计数将仅出于探索目的进行转换。转换的目的是使数据更具同质性,以帮助探索(使用的特定转换是*方差稳定转换,*其细节可在本文中找到)。否则,对于统计分析,应使用原始计数。这是生成距离热图的附带代码。
蓝色阴影越深,一对样本彼此越相似。图片作者。
另一种评估样品间相似性的方法是使用主成分分析(PCA)图。不需要太多的细节,它本质上是一个图,其中 x 轴解释了所有样本之间的大部分差异,y 轴解释了所有样本之间的第二大差异。请注意,这些百分比加起来并不等于 100%,因为有更多的维度包含剩余方差(尽管这些剩余维度中的每一个都比我们看到的两个解释得少)。
观察 PC1 如何很好地分离病例和对照样本。这表明某些基因的表达是不同的。图片作者。
差异表达分析
现在我们已经可视化了我们的数据,让我们运行分析。我们正在使用的软件包使它变得非常简单;我们只要跑dds <- DESeq(dds)
。通过使用 R: ?DESe
中的 help 命令,您可以看到它做了更多的事情,但简单来说,它做了三件事:估计大小因子(控制样本测序深度的差异,但现在不要太担心这意味着什么),估计每个基因的分散值(同样不打算进入技术细节,将分散视为“扩散”的度量),以及拟合一个通用的线性模型。如果这些话对你没有意义,没关系。我的哲学是*先做,后问,*我知道这可能很有争议,但我认为学生经常会陷入所有的理论和技术细节(其中有许多需要真正掌握和理解)中,以至于他们永远不会进步到事情的实际方面。
数据帧中返回的每个基因有两个主要估计值:baseMean
,归一化计数值的平均值除以大小因子,以及log2FoldChange
,效应大小估计值。例如,log2 倍变化 2 意味着基因的表达增加了 2 =4 的倍数。 DESeq2 对每个基因执行假设检验以查看是否有足够的证据来反对无效假设,即处理对基因没有影响,并且处理和控制之间的观察差异仅仅是由实验可变性引起的。
请注意,由于 TCF21 在 10%的 FDR 水平沉默,有许多基因存在差异表达。
形象化
我们可以做的一件有用的事情是可视化模型中所有基因的估计系数的分布。我们可以使用 MA 图。特定比较的 log2 倍变化(LFC)绘制在 y 轴上,通过大小因子标准化的计数平均值显示在 x 轴上。每个基因用一个点表示。在制作 MA 图之前,我们使用 lfcShrink 函数收缩 log2 倍变化,用于病例与对照的比较。 DESeq2 中有三种类型的收缩估计器,在 DESeq2 简介中有所介绍。我们将使用 apeglm 方法来收缩系数,这有利于收缩有噪声的 LFC 估计,同时为真正的大差异提供低偏差 LFC 估计。
y=0 以上的蓝点显示显著上调的基因,而 y=0 以下的蓝点显示显著下调的基因。前 10 个最显著的差异表达基因被标记。图片作者。
对 p 值直方图执行诊断也是一种很好的做法。这篇文章很好地解释了这一点。
res_shrink %>%
filter(baseMean > 1) %>%
ggplot(aes(x = pvalue)) +
geom_histogram(col = "white")
这是一个正常的直方图,峰值在 0 附近,表示差异表达基因的富集。没有迹象表明任何东西是时髦的!图片作者。
结论
那么我们完成了什么?我们进行了第一次差异基因表达分析,我们确定了一些当 TCF21 基因在冠状动脉肌细胞中沉默时上调/下调的候选基因!很酷,对吧?
使用差异表达分析,您可以做更多的事情。我几乎没有触及表面。如果你想更深入地了解,我推荐你看看这篇短文,或者谷歌一下“差异基因表达 R ”,然后进入兔子洞。希望这篇文章能够证明,开始一件全新的事情不应该是一个可怕的折磨,并提醒你,你总是要从某个地方开始。然而,只要有足够的兴趣和动力,一旦你开始,你很快就会搜索你不明白的东西或者需要了解更多的东西,你就会走上精通的道路!
如何从 AI 入手?
不要从 AI 开始
许多公司希望从“人工智能”开始,尽管这听起来像是一个好主意,但出于营销目的,为了让从人工智能中产生商业价值,我推荐一种不同的方法。假设您有可用的数据,您想开始使用这些数据为您的公司造福。你是做什么的?不要从一个随机的机器学习项目开始,而是考虑先做这个。
尽管这个流行词可能已经存在了一段时间,但这个话题对你的公司来说可能是一个新话题。大家可能还不了解 AI(AI 素养),大概有印象就是神奇。一个好的开始方式是让他们熟悉在日常业务中使用数据,使用一些“简单”但非常 重要的数据科学。关于你问的?这里有几个步骤可以遵循。
#1 了解公司的战略
贵公司的关键战略重点领域是什么?他们与战略相关的KPI是什么?查看年度报告、内部门户网站或与您的经理交谈,人们在走廊上谈论的话题是什么?也许你的公司想成长为某个客户群,或者有节约成本的压力。
#2 选择一些话题
现在你已经对你的战略和 KPI 有了深入的了解,选择 3-5 个主题,你可以进一步研究。您可以根据您知道哪里有可用的数据、您在组织中哪里有网络或者人们实际上坐在办公室附近的地方来选择它们。例如,选择与销售和营销相关的主题,其中大多数数据应该可以从您的 CRM 解决方案中获得。
#3 探索性数据分析
现在记住这些话题,开始你的探索性数据分析。针对每个主题,写下 5-10 个问题,你可以询问数据并找到这些问题的答案。问题的例子可以是
- 有多少顾客拥有不止一种产品?
- 销售/营销人员主动接触了多少这样的客户?
现在还不需要任何花哨的东西,一个又快又脏的 Jupyter 笔记本就可以了。
#4 创造可行的见解
现在,针对每个问题浏览一遍你的 EDA,写下你的利益相关者可能感兴趣的五个可操作的点。例如,您发现某个客户群 A 中的销售人员主动接触的客户购买了多种产品。对于另一个客户群 B,营销是成功追加销售不同产品的关键。
可操作的见解是销售应关注客户群 A 进行交叉销售,营销应关注客户群 B 进行追加销售。
#5 出版
你可以用一个你的管理层能够理解的形象化的东西来支持这些信息。以适合贵公司的格式发布。在哪里?你的观众是谁?
发布你的读者在哪里,以获得正确的牵引力。
有内部通讯吗?人们使用松弛渠道吗?或许把它挂在咖啡区的打印输出上?
#6 沟通,沟通,沟通
现在仅仅出版是不够的。与你的利益相关者沟通,安排一次会议,在午休时谈论它,等等。确保人们多次看到这些见解并鼓励他们采取行动。一旦他们从你的见解中看到了价值**,他们会回来索取更多。**
你会看到,可行的见解以人们能够理解的方式展示了数据科学的价值**。一旦他们这样做了,他们会回来要更多。**
你对如何进入 AI 有具体的问题吗?通过 https://aibridge.ch/contact/联系我。
关于我:我是一名分析顾问,也是当地一所商学院“人工智能管理”研究的主任。我的使命是帮助组织利用人工智能创造商业价值,并创造一个数据科学家可以茁壮成长的环境。 报名我的 简讯 这里有关于 AI 管理的新文章、见解和供品。
如何开始写数据科学博客?
想在数据科学上写博客吗?这是给你的。
由 Serghei Trofimov 在 Unsplash 拍摄的照片
当我们想到写博客时,我们大多数人都被写完美的文章来吸引眼球的想法淹没了,对你来说没有足够的知识,缺乏一致性或找到正确的受众。
失败的理由可以有 100 个,但成功的理由有 1 个就够了!
我第一次听说科技博客是在 2016 年的一次会议上。我对把你的想法告诉人们的想法很感兴趣。我最初开始在 WordPress 上写博客——关于我的日子、感受、希望、成就的故事(这很容易)。在最初的三个月里,我有相当不错的收视率,达到了 500 次。然而,我不太喜欢这个过程,于是开始探索 Blogger、Ghost.org、Tumblr 等等。
2017 年,我正在学习用户体验设计的概念,并偶然发现了这个名为 Medium 的平台,在这里我可以找到大量关于技术和个人发展的任何主题的文章——从加密货币到领导力,从数学到迷幻药,Medium 是我的地盘!
我开始阅读大量文章,发现媒体是作家和读者的最佳平台之一。有了 Medium 的政策,基本上,任何有有趣的东西可写的人都可以成为作家。2017 年 7 月 13 日,我在 Medium 上写了我的第一篇文章UX 可用性的销售预测。
虽然我写这篇文章主要是出于实验目的,但当我第一次鼓掌时,我获得的满足感鼓励我继续写作。
我花了一年多的时间来弄清楚媒体上的故事是如何工作的,什么是出版物,如何让更多的观众参与内容,因此从 2019 年 1 月 16 日开始了我作为全职科技博客作者的旅程,没有回头。我有了第一个 1K+浏览量的故事😀
博客对数据科学的优势
有许多初级、中级和专家级的爱好者通过博客与社区分享他们的知识和学习。那么是什么促使他们写作呢?
1.学习和分享
我一直相信学习、探索、体验、分享、重复。
我不断受到激励,致力于具有挑战性的数据科学项目或概念,从而提高我的数据技能。在数据科学博客中,你可以参与到间接指导中。当有人阅读你的博客时,他们从中学习,执行,并对阅读你的内容感到满意。你可能永远不会亲自认识那个人,但是鼓舞人心、教导别人的想法让我很兴奋去付出!
2.建立您的个人资料
博客无疑是你展示数据科学知识和技能的最聪明的手段之一。
在媒体上发表的每一篇文章都可以被视为知识产权——独一无二、独一无二、不可替代。你完全可以在简历中加入这个链接。
当你写作时,你被认为是一个了解数据科学的人,也许不是专家,但阅读你博客的人会把你和你写的东西联系起来。当人们阅读你的内容时,他们从那个角度看你;这对建立你作为数据科学家的品牌来说是一件好事。
对我来说,写数据科学是向世界展示我的能力的一种方式,同时它也是我的一份无声简历!
3.全球风险
媒体上的文章被全球社区阅读。您有机会与全球读者分享您的专业知识、知识、学习成果和经验。当你收到来自世界各地的评论、电子邮件、Twitter 或 LinkedIn DMs 时,那种喜悦是无与伦比的。
4.发展软技能
如果写 1000 到 1500 字的文章不能提高你的沟通技巧,那会怎样呢?写博客,将反馈考虑在内,能让你以一种普通大众能理解的方式传达信息。
如果你不能用简单的术语向某人解释某事,那么这意味着你没有很好地理解这个概念。
当有人向我伸出手,说他们喜欢我解释概念的简单易懂的方式时,这就是博客作者的梦想!
5.向自己介绍大量的机会
当你在 Medium 上写博客时,它为你建立了可信度,同时你的作品会立即为全世界所知。任何人搜索你或谷歌搜索一些关键词,看到你的个人资料,都会看到你所做的工作。
在我写博客的最初几天,我主要写的是用户体验设计。一位来自德国的 UX 设计师在 Twitter 上看到了我的博客,他想知道我是否有兴趣为他们的博客写付费文章。很多人想为付费博客写作,但他们没有作品集可以展示。当机会出现时,你的文章将成为你的简历。
到目前为止,在我的旅程中,我已经有过多次机会从事独立的付费项目,免费参加会议,为一个出版物撰写客座博客。
6.赚钱💰
你知道吗,你可以从你的文章中赚钱(甚至每月约 1000 美元)。通过 Medium Partner 计划,任何在 Medium 上发表文章的人都可以获得赚钱的资格。接下来,这取决于你的文章对观众的吸引力有多大。
该过程
1.选择您的域
即使在数据科学领域,也有很多事情可以写博客。
- 数据科学概念-决策树、随机森林、SVM、kNN、聚类、NLP、深度学习、人工智能等等…
- 数据科学的统计和数学
- 项目—数据清理、数据争论、数据
- 数据分析
- 数据可视化
- 关于数据科学的研究(令人惊讶的验证)
- 一般主题—软件、工具、新闻、编程语言、技能
- 比较—工作角色、库、功能
- 教程
- 案例分析等…
这些是你可以为你的第一个数据科学博客选择的一些主题。
2.研究
如果你想到一个特定的主题,互联网上有大量的文章可能与你想到的标题相同。不只是中等,但你需要注意你的内容不要复制网络上的任何其他文章,至少要试着这样做。
写博客的核心是提供价值。如果你没有教一个人一些以前没有告诉过的东西,读者可能会从你的博客上反弹并接近一个不归路。
特别是在数据科学方面,假设你决定写一篇关于 Random Forest 的文章,在谷歌上大约有 611,000,000 个搜索结果。你的目标是独一无二,用通俗易懂的方式解释概念,迎合更广泛的受众,用优质的内容在谷歌搜索上排名靠前。
我的建议是研究所有与你感兴趣的话题相关的现有内容,做笔记,勾画出你想写的内容的大纲。你读得越多,你对内容就越清楚。
3.了解你的观众
在发布博客之前,一个很好的建议是了解你的受众是什么类型的——初学者、中级、专家。验证你写的东西会被消费是非常重要的。
最初,我常常向一个出版物投稿,即使我会认为这是一部值得骄傲的作品,也不会有很多人阅读。问题:文章写得太超前了,出于某种原因,与读者无关。后来,我不得不停止向那份刊物投稿。
阅读围绕你的主题发表的其他博客,检查内容!
4.提交给出版物
媒体上的出版物是围绕一个共同主题或话题撰写的故事的共享空间。出版物正在寻找作家提出最新和相关的内容,重点是数据科学,机器学习,人工智能,编程等等。
每个出版物都有被接受的指导原则——这意味着如果你的内容质量不够好,或者不符合指导原则,它就不会被出版。提交前请务必阅读指南。
一旦你被接受,一份出版物能让你接触到更广泛的读者,赚更多的钱,得到诚实的反馈。
对于数据科学,您可以将您的文章提交到
5.监控您的指标
我认为这是最大的学习工具——记录你的观点和阅读。你发表的每个故事,都有一个详细的相关统计数据,告诉你你在不同平台上的读者群。
你能得到的最好的反馈是密切监视你的统计数据。有些博客可能会有超过 20 万的浏览量,而有些博客可能仅限于 3K 的浏览量。这就是你自省的时候,发现什么有用,什么没用。仔细阅读关于你的故事的回复:从显示错别字到赞赏吨——回复反映了用户的观点。
然后还有个叫读比的东西。你不仅希望读者看到你的博客,而且希望他们阅读你的博客。一篇阅读时间为 5-7 分钟的文章或故事的中等阅读率在 40% - 70%之间。影响媒介阅读率的因素是你的媒介文章的流量来源和阅读时间。
clickbait 标题的粉丝会围绕阅读率大做文章。但还是那句话,这取决于你写博客的目的。
6.要耐心
忍耐是痛苦的,但它的果实是甜蜜的
增加博客流量的关键是:要有耐心。写博客的成功不会裹着漂亮的蝴蝶结出现在门口。这需要大量的艰苦工作和极大的耐心。优步博主 Chris Brogan 有一句名言,他花了三年时间才吸引了第一批 100 名博客订户。毕竟,不是每个人都能像贾斯汀比伯那样一夜成名😛
- 专注于创造尽可能好的内容;非常棒的内容
- 做你自己——让这成为你的“竞争优势”
- 写作前后一致
- 优雅地对待批评——这是领导者的标志
- 偶尔在你写的东西中冒险。试新失败也没关系!
- 不要害怕。即使你不确定它是否“完美”,也要发表它
感谢您的阅读!我希望你喜欢这篇文章,并从此刻开始用思维导图来写博客。一定要让我知道在你的数据科学博客之旅中什么让你兴奋。
快乐数据 Tenting!
免责声明:本文表达的观点仅代表我个人,不代表严格的观点。
了解你的作者
拉什是芝加哥伊利诺伊大学的研究生。她喜欢将数据可视化,并创造有见地的故事。当她不赶着赶学校的最后期限时,她喜欢喝一杯热巧克力,写一些关于技术、UX 等的东西。
如何开始你的机器学习生涯?
不,它不仅仅是一个大学学位。你变得越好,就越受关注。那么如何开始呢?
伊恩·施耐德在 Unsplash 上拍摄的照片
简介
如今,许多公司都在寻找拥有高水平技术知识的人。即使你被录用了,你也需要不断进步,跟上时代。这是一个常见的过程。
嗯,这是你可以采取的第一个明智的步骤:你需要成为任何公司的一个有价值的资源,而不是一个普通的员工。让我们一起深入了解机器学习的基本核心概念。
你已经知道多少了?
与所有其他人相比,你处于什么位置?你已经知道多少了?你的弱点是什么?强壮的?在进行下一步之前,你需要先了解自己。
即使你有学位也没关系,你知道在你的领域里什么是最重要的吗?以下是一些需要回答的问题:
- 你知道统计与概率吗?多少钱?
- 你用什么语言或者你将开始学习什么语言?Python,R,Scala,Julia…?现在有更多的开始发光。
- 关于所需的库,你有好的背景还是需要马上开始?
- 你要学多少时间?你预计什么时候开始实地工作?你每月能付多少钱来学习?
把你所有的答案写在一个你需要的时候可以快速拿到的地方。
从哪里开始学?
当我开始穿越数据科学领域时,我发现自己迷失了。要学的东西太多了,多种不同的资源——注意——质量差。对我来说,仅仅抛出一堆能帮到你的链接真的很容易,但也许这还不够。我甚至不能注意到你已经知道了多少,那没有意义!
为了达到最好的效果,你需要自己潜水。如果你从未涉足统计学领域,现在是时候了,我将帮助你。数据科学和机器学习也是如此。
Alex Ambedo 在 Unsplash 上拍摄的照片
1)统计和概率
两者都被称为你需要了解的入门领域。你将潜入人工智能海洋的浅水区,稍后能够理解更高级的概念。开始不需要知道太多,基本就行。让我们看看“基础”是什么意思:
- 集中趋势的度量:均值、众数、中位数;
- 价差度量:极差、四分位、方差、标准差;
- 此外,这是一个很好的方法来了解:z 分数,贝叶斯概率,四分位间距等。
有了以上这些东西,你就能:
- 能够发现数据中的异常值以及何时删除它们;
- 对你的数据集有深入的分析;
- 对数据清理和特征工程有一个初步的了解;
但是在哪里可以学习统计和概率呢?
可汗学院提供了关于那个领域的非常好的材料。你首先要了解每一个单词的意思,然后在练习中运用你的新知识。
就那些内容?为什么?
我是一名教师,自 2014 年以来一直与青少年一起表演。我的教学方式真的很简单:边做边学。仅仅通过阅读书籍或观看视频,你什么也学不到,这可能会有所帮助,但你只能通过将你所学的内容融入到你的大脑中来保存这些知识。所以从最基本的开始。
2)数据科学
另一个提示:开始学习数据科学,将统计学和概率结合在一起。两者高度相关,您今天所学的内容肯定可以应用到数据科学中。
数据科学是一个很大的领域。在开始考虑机器学习之前,你需要学习如何获取数据、清理、修改、改进和可视化数据。你有一堆包含多个函数的库,所以有很多工作要做。让我们来看看基本情况:
图书馆:
- 熊猫;
- Numpy
- Matplotlib
- Seaborn(可选)
需要学习的内容:
- 数据清理和扯皮;(熊猫)
- 特征工程;(Numpy)
- 数据可视化;(Matplotlib)
他们已经准备好了,从熊猫图书馆开始,继续。默认情况下,Pandas 库将提供使用 Numpy 所需的所有重要概念,这将扩展您使用 Matplotlib 的查看能力。
你可以从哪里开始学习数据科学?
Coursera 是这里最好的选择!即使你不能获得专业证书,你仍然可以旁听任何你想旁听的课程,这意味着什么?你可以从世界上最著名的大学学到任何东西!
创建您的帐户后,您将能够审核斯坦福、约翰霍普金斯、密歇根、阿姆斯特丹等大学的课程。免费的!点击此处查看可用课程。
重要的是要知道:每门课程将引导你通过一个统计学和概率的介绍性视野,这可能很容易,也可能非常难,选择好。
3)机器学习
有了良好的数据科学背景和良好的统计和概率知识,您就可以开始学习机器学习了!一如既往,从小处着手。当我们谈论这个领域时,线性回归是介绍性的算法。
有一堆指南旨在教你机器学习模型是什么样子的,所以我们不需要在这里深入研究。
在分层模型中,它看起来像这样:
监督学习
- 回归;
- 分类;
无监督学习
- 聚类;
更多学习内容
- 降维;
- 特征选择;
- 模型调整和评估;
我已经删除了一些核心概念,如迁移学习,因为它可以在深度学习中更愉快。不要忘记,随着机器学习,一个新的 Python 库出现了: Scikit-learn 。您可以从头开始创建任何算法,并在了解其工作原理后,从该库中正确地实现它。
此外,在机器学习领域,我们有深度学习,但我将把它留给另一篇文章。不要误解我,也许你正在阅读这篇文章,但如果没有之前对机器学习核心概念的强大知识,现在没有理由学习深度学习。专注于现在重要的事情。
你可以从哪里开始学习机器学习?
Coursera ,又来了!事实上,如果你按照我在数据科学一节中的说明去做,你肯定会学到一些机器学习的知识。你只需要集中精力,开始在 Coursera 上搜索相关课程。
但如果出于某种原因,你正在努力理解大学的艰深语言,YouTube 上有一些更简单的地方可以提供同等质量的内容,看看吧:
好了,现在你已经有了你需要理解的所有基本概念,并且知道在哪里可以得到你需要的材料,你只需要开始学习!祝你学习顺利。
图片来自 Giphy
当我开始的时候,我很难理解,这就是为什么我决定分享我做过的最好的指南,让你的事情变得更容易。请记住,本指南并没有涵盖你在学习过程中的所有基本需求,但我很确定这些问题会在学习过程中得到解决。这就是你学习的目的,解决问题!
在 GitHub 上注册你自己的个人资料,这是托管代码、管理项目和构建软件的最佳地方…
github.com](https://github.com/renfelo)
如何在不牺牲数据的情况下保持在自由层云数据库行限制内
通过仅托管小型汇总表并在本地硬盘上保留精细的历史表,节省资金并改善用户体验
免责声明:这些建议是针对涉及几 GB 数据的低风险项目的。如果你在处理“大数据”,你只能靠自己
如果您正在处理一个需要托管数据库的项目,您可能会担心您会很快超出免费/低成本计划的行限制。即使每月只需花费 9 美元就可以存储 100 倍多的行,这对您来说也不值得,尤其是如果您的项目不会产生收入的话。你可能认为是时候开始删除那些带给你最少快乐的记录了…
但是等等!你可能已经有了另一个免费存储数据的地方,就在你的指尖——你的本地硬盘。
在这一点上,你可能会担心我不知道我在说什么。你不会尝试使用本地数据库来运行一个网站。如果你的猫在你的笔记本电脑上摩擦它的头,并且不小心关上了它或者断网了,你的网站将会变得毫无用处。
我并不是建议你完全替换你的云数据库——只是使用本地数据库来补充它。将详细的历史数据保存在您的计算机上,只在云上托管较小的汇总表。通过这种方式,您的用户仍然可以登录、查看聚合数据、订阅电子邮件(所有这些好的数据库相关的东西),并且如果您以后需要,您将拥有所有旧的/高粒度的数据。
在我的例子中,我制作了一个 web scraper 来收集喜剧场所网站上的表演信息,并使用这些数据在我自己的网站上显示一些统计数据。我平均每天收集 300 行数据(该场所网站上列出的每个节目的每个喜剧演员一行),如果我继续将结果附加到我的表中,这将在一个多月的时间里超过 Heroku 的 10K“hobby-dev”等级行限制。
我只需要向用户显示聚合的历史数据(这个喜剧演员做了多少节目?他们最后一次表演是什么时候?等。)和详细的未来数据(该喜剧演员将很快出现在哪些具体的节目中?还有哪些喜剧演员会出席那场演出?).但是,我并不只是想把详细的史料丢掉。如果我的代码中有一个错误导致了不准确的聚合,我希望有旧的数据,这样我就可以重新生成聚合。更详细的数据可以方便地用于未来的预测建模。
我的表结构如下所示(在大约一年半的数据收集之后,行数为 6/28/20):
紫色的表在 Heroku 上,但是我也保留了本地的备份。完整的历史存储在 fact_shows 表中,该表用于生成较小的表。 Fact_shows 显然超过了行限制,但 Heroku 主持的桌子现在每个只有几百行(注意: dim_upcoming_shows 现在是空的,因为场地因 COVID 限制而关闭)。所有这些表格总共占用了我硬盘上 47MB 的空间。
我的 scraper 每天晚上在本地运行,并将数据附加到 fact_shows 中,如下所示:
在更新了 fact_shows 之后,我生成了 dim 表。我定义了这个通用的 update_dim_table 函数,以避免为我想要创建的每个 dim 表重复代码。它需要表名和查询,以便能够汇总来自 fact_shows 的数据,然后将汇总的表写入本地数据库和(可选)Heroku。
下面是我如何应用该函数创建 dim_comedian_stats 表的示例,该表被写入 Heroku,因为我需要它在我的站点上进行可视化:
更多上下文,完整的 scraper/ fact_shows 文件是这里是,而 dim 表格脚本是这里是。
根据您的特定用例,您可能无法聚合数据。如果您的用户需要深入了解细节,可以考虑其他方法来减少托管数据,比如只显示最近 30 天的数据(同时在您的笔记本电脑上保留更长的历史记录)。总的原则是保持理想的表结构,将全部历史存储在本地,然后计算出满足用户需求所需的最低限度,只将那个小表推送到您的云服务。除了省钱之外,这还可以改善用户体验,因为网站查询是针对更小的表进行的,所以大家都赢了!
Raspberry Pi 上的实时视频对象检测
使用 OpenCV、专用硬件和云技术实现快速检测
最近,一段来自特斯拉 autopilot view 的视频出现在互联网上,并非常受欢迎。我对一个类似的视频流(带有检测到的物体)很感兴趣,这个演示最终让我做了一些工作。
唯一的问题是我想从 Raspberry Pi 流视频,但总的来说,它不够强大,无法执行这样的任务。
检测到物体的图像
树莓上的 OpenCV
最直接的实现是通过 OpenCV-DNN 在 Raspberry Pi 上运行一个检测器。
OpenCV-DNN 支持多种网络和格式,但我以前用的是 Google 的MobileSSD(11 _ 06 _ 2017 版本,最新的不兼容 OpenCV 4.2)。
首先,读取类名并加载模型:
tf_labels.initLabels(dnn_conf.DNN_LABELS_PATH)net = cv.dnn.readNetFromTensorflow(dnn_conf.DNN_PATH, dnn_conf.DNN_TXT_PATH)
然后对一个图像运行推理:def 推理(img):
net . set input(cv . dnn . blobfromimage(img,1.0/127.5,(300,300),(127.5,127.5,127.5),swapRB=True,crop = False))
return net . forward()
这个操作在树莓上需要 1.7 秒。例如,我的漂亮的旧笔记本电脑在 0.2 秒内完成同样的工作。
将输出张量转换为人类友好的 JSON:
def build_detection(data, thr, rows, cols):
ret = []
for detection in data[0,0,:,:]:
score = float(detection[2])
if score > thr:
cls = int(detection[1])
a = {"class" : cls, "name" : tf_labels.getLabel(cls), "score" : score}
a["x"] = int(detection[3] * cols)
a["y"] = int(detection[4] * rows)
a["w"] = int(detection[5] * cols ) - a["x"] a["h"] = int(detection[6] * rows) - a["y"]
ret.append(a)
return ret
考虑到测量,很明显原生树莓性能(1.7 秒)对于任何视频都是不够的。
但是让 Raspberry 与笔记本电脑配合使用应该会提高处理帧的整体能力。
笔记本电脑原型
现在用一个 REST 接口把检测器包起来。
为此,我通常使用烧瓶。获得服务有两个切入点:
- 第一个返回 JSON 中的检测
- 第二个返回带有检测到的矩形和标签的图像
第二种方法给出了检测结果,简单明了:
curl -X POST -F "file=@pic.jpg" [h](http://192.168.1.243/)ost:80/ddetect --output a.jpg
码头工人
我们想要一个可扩展和可移植的解决方案,然后将服务打包到 docker 映像中。
选择 Debian Stretch + Python 作为基础映像,保留与 Raspbian 类似的堆栈。
需要设置 flask,protobuf,requests,opencv_python,从 GitHub 下载移动 SSD 和服务器代码。
FROM python:3.7-stretchRUN pip3 install flask
RUN pip3 install protobuf
RUN pip3 install requests
RUN pip3 install opencv_pythonADD [http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_11_06_2017.tar.gz](http://download.tensorflow.org/models/object_detection/ssd_mobilenet_v1_coco_11_06_2017.tar.gz) /
RUN tar -xvf /ssd_mobilenet_v1_coco_11_06_2017.tar.gzADD [https://github.com/tprlab/docker-detect/archive/master.zip](https://github.com/tprlab/docker-detect/archive/master.zip) /
RUN unzip /master.zipEXPOSE 80CMD ["python3", "/docker-detect-master/detect-app/app.py"]
为了与第三方提供商一起使用该图像,需要将其发布到一些公共 docker 注册表上。
我决定用传统的方式使用 Docker Hub。
- 创建一个帐户
- 使用 DockerHub: docker 登录授权本地 docker
- 给图像命名: docker 标签TPR lab/opencv-detect-SSD
- 上传图片: docker 推送 tprlab/opencv-detect-ssd
现在,该映像可以用于许多容器提供商,如 Google Cloud、Microsoft Azure、Amazon Web Services、Digital Ocean、Heroku 等。
录像
使用 OpenCV 示例,制作一个基本服务器:
def handle_frame(frame):
return detect.detect_draw_img(frame)
def generate():
while True:
rc, frame = vs.read()
outFrame = handle_frame(frame)
if outFrame is None:
(rc, outFrame) = cv.imencode(".jpg", frame)
yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + bytearray(outFrame) + b'\r\n')[@app](http://twitter.com/app).route("/stream")
def video_feed():
return Response(generate(), mimetype = "multipart/x-mixed-replace; boundary=frame")
随着 docker 部署在笔记本电脑上,视频以慢动作播放。
谷歌云
到目前为止,单个码头工人是不够的。让它伸缩——在这种情况下,我们将能够同时处理多个帧。
我选择 GCloud 作为 Kubernetes 的服务提供商,并在 5 个实例中运行我的映像。
服务器代码变得更加复杂:
def generate():
while True:
rc, frame = vs.read()
if frame is not None:
future = executor.submit(handle_frame, (frame.copy()))
Q.append(future)
keep_polling = len(Q) > 0
while(keep_polling):
top = Q[0]
if top.done():
outFrame = top.result()
Q.popleft()
if outFrame:
print("Frame", datetime.datetime.now())
yield(b'--frame\r\n' b'Content-Type: image/jpeg\r\n\r\n' + bytearray(outFrame) + b'\r\n')
keep_polling = len(Q) > 0
else:
keep_polling = len(Q) >= M
这种方法有助于以大约 10 fps 的速度传输检测到的视频。
还有提高速度的空间——只需在我们的 Kubernetes 集群中添加更多节点。
英特尔神经计算棒
在进行了远程检测实验后,我决定尝试本地硬件解决方案。
我有一台英特尔 NCS,已经在类似任务中使用过。
所以我把 MobileSSD 转换成 OpenVino 格式,用 NCS 检测器运行视频流。
NCS 很好地完成了这项工作——FPS 略高于 10,优于 5 节点 Kubernetes 集群。
结论
最终,使用外部电源进行接近实时的检测被证明是可能的。
使用 NCS 是最简单(也是最便宜)的方法——一次性购买,用最简单的代码工作很长时间。
docker 方式更复杂,但也更具可伸缩性、可移植性和可重用性。
链接
- 带有 docker 文件和源代码的 GitHub repo
- Docker Hub 上准备就绪的 docker 图像
如何用 Python 为 Excel 增压
如何用 xlwings 集成 Python 和 Excel
由 Unsplash 上的émile Perron拍摄的照片
Excel 既是一种祝福,也是一种诅咒。当谈到足够小的数据和足够简单的操作时 Excel 是王者。然而,一旦你发现自己在那些区域之外努力,它就变成了一种痛苦。当然,你可以使用 Excel VBA 来解决这些问题,但是在 2020 年,你可以感谢你的幸运星,因为你不需要这么做!
如果有一种方法能把 Excel 和 Python 集成在一起,给 Excel 插上翅膀就好了!现在有了。一个名为 xlwings 的 python 库允许你通过 VBA 调用 Python 脚本,并在两者之间传递数据。
为什么要集成 Python 和 Excel VBA?
事实是,在 VBA 你几乎可以做任何事情。那么,如果是这样的话,为什么要使用 Python 呢?嗯,有很多原因。
- 您可以在 Excel 中创建自定义函数,而无需学习 VBA(如果您还不知道的话)
- 您的用户可以轻松使用 Excel
- 使用 Python 可以显著加快数据操作的速度
- Python 中几乎有任何东西的库(机器学习、数据科学等)
- 因为你可以!!!
设置使用 xlwings
与我们想要使用的任何新库一样,我们需要做的第一件事是安装它。做起来超级简单;有了这两条命令,我们马上就可以设置好了。所以,继续输入您的终端:
一旦下载并安装了库,我们需要安装 Excel 集成部分。确保您已经关闭了所有 Excel 实例和任何终端类型:
假设您没有遇到错误,您应该能够继续。然而,在 Win10 和 Excel 2016 上,人们经常会看到以下错误:
xlwings 0.17.0
[Errno 2] No such file or directory: 'C:\\Users\\costa\\AppData\\Roaming\\Microsoft\\Excel\\XLSTART\\xlwings.xlam'
如果你是遇到上述错误的幸运儿之一,你需要做的就是创建丢失的目录。使用 mkdir 命令可以很容易地做到这一点。就我而言,我做到了:
mkdir C:\\Users\\costa\\AppData\\Roaming\\Microsoft\\Excel\\XLSTART
假设成功安装了 excel 与 python 库的集成,您会立即注意到 Excel 中的主要差异:
为 xlwings 启用用户定义的功能
首先,我们需要加载 Excel 插件。你可以点击 Alt,L,H,然后导航到上面的目录来加载插件。完成后,您应该能够看到以下内容:
最后,您需要启用对 VBA 项目对象模型的信任访问。为此,您可以导航至文件>选项>信任中心>信任中心设置>宏设置:
由 Pakata Goh 在 Unsplash 上拍摄的照片
xlwings 入门
从 Excel 到 Python(以及从 Python 到 Excel)有两种主要方式。第一种是直接从 VBA 调用 Python 脚本,而另一种是通过用户定义的函数。让我们快速浏览一下这两者。
为了避免任何混淆和每次都有正确的设置,xlwings 提供创建您的 Excel 电子表格,随时可用。然后让我们使用这个功能。使用终端,我们导航到我们喜欢的目录并键入:
xlwings quickstart ProjectName
我称之为 MyFirstPythonXL。上述命令将在您预先导航的目录中创建一个新文件夹,其中包含一个 Excel 工作表和一个 python 文件。
正在打开。xlsm 文件,您会立即注意到一个名为 _xlwings.conf 的新 Excel 表格。如果您希望覆盖 xlwings 的默认设置,您所要做的就是重命名该工作表并删除起始下划线。至此,我们已经准备好开始使用 xlwings 了。
VBA 到 Python
在我们开始编码之前,让我们首先确保我们都在同一页上。要打开我们的 Excel VBA 编辑器,点击 Alt + F11 。这将返回以下屏幕:
xlwings 的 VBA 编辑器
这里需要注意的关键点是,该代码将执行以下操作:
- 在电子表格所在的位置查找 Python 脚本
- 查找与电子表格同名的 Python 脚本(但扩展名为. py)
- 在 Python 脚本中,调用函数“main()”
事不宜迟,让我们看几个如何使用它的例子。
示例 1:在 Excel 之外操作,并返回输出
在这个例子中,我们将看到如何在 Excel 之外执行操作,然后在电子表格中返回结果。这可以有无限多的用例。
我们将从 CSV 文件中获取数据,对所述数据进行修改,然后将输出传递到 Excel。让我们回顾一下它有多简单:
首先,VBA 密码:
我完全没有改变默认设置。
然后,Python 代码:
这会导致以下结果:
xlwings 在行动
示例 2:使用 Excel 输入来驱动操作
在本例中,我们将从 Excel 中读取输入,用 Python 对其进行处理,然后将结果传回 Excel。
更具体地说,我们将读出一个问候语、一个名字和一个我们可以找到笑话的文件位置。我们的 Python 脚本将从文件中随机抽取一行,并返回一个笑话给我们。
首先,VBA 电码:
我完全没有改变默认设置。
然后,的 Python 代码:
这给了我们:
使用 xlwings 的用户定义函数
和以前一样,我们将改变 python 文件中的代码。为了将一些东西转换成 Excel 用户定义的函数,我们需要做的就是在函数所在的行之前包含“@xw.func ”:
Python 代码:
结果是:
结论
我想你会同意这是一个漂亮的小图书馆。如果你像我一样,你更喜欢用 Python 而不是 VBA 工作,但需要在电子表格中工作,那么这可能是一个非常好的工具。
想了解我博客的最新动态吗?别忘了跟着我!
以下是其他一些你可能会感兴趣的文章:
了解如何使用 Python 进行快速数据分析
medium.com](https://medium.com/financeexplained/from-excel-to-databases-with-python-c6f70bdc509b) [## 从 XML 到 Excel 进行数据分析
Python 中处理 XML 的介绍
towardsdatascience.com](/from-xml-to-excel-for-data-analysis-ac0c0c765b7d)
如何在充满挑战的时期从裁员中幸存下来并茁壮成长
2020 年5 月 5 日,我从之前的公司下岗了。2020 年 6 月 30 日,我签下了另一家让我非常兴奋的公司的聘书。我写这篇文章是为了分享我和我的一些同事在全球疫情中从被解雇到找到一份新工作的经历。我希望它能对正在经历裁员的人有所帮助和鼓励。
由 Patrick Fore 在 Unsplash 上拍摄
从被解雇到在全球疫情期间找到一份新工作
由于全球疫情,旧金山湾区的许多科技公司在 2020 年早春开始裁员。5 月 5 日,Airbnb 裁员 1900 人,25%的员工,我是其中之一。
除了大规模裁员,许多公司冻结了招聘,因为没有人知道他们的业务未来会是什么样子。对于那些仍在招聘的公司来说,门槛越来越高,许多公司现在只对非常有经验的候选人开放职位。2020 年 4 月,美国官方失业率上升 10.3%,至 14.7%,这是该数据历史上(可追溯至 1948 年 1 月)的最高水平和最大月度增幅。你可以想象那段时间就业市场的竞争有多激烈。
紧张的就业市场只是失业者不得不面对的困难之一。虽然人们说“被解雇与你的表现无关”,但很难不怀疑我是否不够好。作为 H-1B 签证持有人,我也担心我是否能在很短的时间内找到工作,这样美国政府就不会强迫我离开这个国家。此外,我非常喜欢我以前的公司和那里的人,以至于我很难过我不得不离开。
现在我回头看看我的朋友和我自己的经历,通过裁员和求职,我意识到没有什么是不能解决的。如果人们足够强大,准备充分,他们仍然会是决定他们想去哪家公司工作的人,我想和你分享几个故事。
第一个故事是关于我的同事蒂娜。蒂娜参加了 5 次最后的现场面试,得到了 5 份工作机会,通过率 100%。
她收到的第一份工作邀请来自一家中型公司。那家公司的招聘人员在他们的第一次对话中问她是不是被 Airbnb 裁员了。
一个候选人被解雇的事实和你公司的面试过程有什么关系?或者你认为你可以得到一笔“好交易”,因为他们需要一份工作?
果然,公司给 Tina 开出了比她现在水平更低的级别和更低的薪酬待遇。Tina 问招聘人员他们是否可以重新进行调配。招聘人员告诉她,“我们决定不改变你的级别。我们期待看到您在我们公司的长期发展”。
我觉得这家公司认为失业的人是在求工作。他们认为他们可以利用那些受到裁员影响的人,给他们提供低于他们价值的报酬。然而,你不应该指望以这种方式雇佣的员工会忠诚,更不要说对为你工作感到兴奋了。他们不会逗留。危机一结束,他们很可能会立刻离开你,去找一家更好的公司。
幸运的是,Tina 做了充分的准备,她参加了另外 4 个现场面试,并获得了 4 个 offers,包括 Google、脸书、抖音等。由于被解雇,她加入了另一家优秀的公司,与一个聪明的团队一起工作,并获得了晋升,获得了比以前更好的薪酬待遇。
第二个故事是关于我的同事伊恩。伊恩刚刚赢得了今年的 H-1B 签证彩票。他认为他会在我们之前的公司工作,直到 H-1B 签证生效。他从来不知道他会被解雇。
当他被解雇时,他的 H-1B 签证也没了。更糟糕的是,他目前的 J-1 签证没有任何宽限期,这意味着他需要在我们正式的最后一天之前加入另一家公司,这给他只有两个月的时间找到工作。
尽管他的 H-1B 签证被吊销了,而且他找工作的时间比任何人都短,但他从未向我抱怨过。在整个求职过程中,他一直保持乐观和冷静。
仅仅面试了几个星期,伊恩就得到了他的第一份口头聘用。看来公司很喜欢他。他们安排了几个人和他谈论他将要从事的项目,但是他们没有给他正式的签约机会。伊恩认为他可以很快加入一家公司;然而,该公司决定不给他正式报价。
伊恩和我认为原因是该公司也向另一位候选人发出了邀请,而伊恩只是那个职位的 B 计划。如果另一个候选人拒绝了这个提议,伊恩就会得到这份工作。但是看起来另一个候选人已经接受了邀请。
即使在这种情况下,伊恩仍然没有抱怨,他简要地告诉我发生了什么,并继续准备其他采访。
在我认识的人里,Ian 的面试日程最紧张,压力也最大。他将在一周内进行 5 次最终的现场面试,外加几次电话面试。
在如此疯狂的生活了几个星期后,他收到了多份工作邀请,在两个月的时间内加入了新公司,并获得了晋升。
与 Tina 和 Ian 类似,我的许多其他同事也取得了类似的结果。如果没有裁员,他们可能没有动力这么紧张高效地准备面试,也不会这么快升职,包括我。
虽然我不像我的许多同事那样有经验,但我至少有一个非常明确的目标,那就是我在寻找什么类型的数据科学家工作:我想成为一名产品数据科学家,主要从事产品分析和实验,并能对产品产生直接影响。
由于目标明确,我分析了我需要做些什么来获得最好的结果。我重点复习了统计学和实验设计,没有花时间练习 LeetCode 编程题。
经过几周的密集学习和面试,我参加了 6 次现场面试,收到了 3 份聘书,都来自产品数据科学家职位。我也得到了晋升和更好的薪酬待遇,而且我将加入一家我非常喜欢的公司。
(蒂娜和伊恩不是真名)
我想要你知道的是
1.被解雇并不意味着你不够好
首先,你必须调整心态。下岗不代表你不够优秀,也不代表你在乞求工作机会。你必须记住这一点。
即使在美国失业率飙升至历史最高纪录的时候,如果你做好了充分的准备,你仍然可以在多个机会中做出选择。
有些公司可能会认为现在求职者多了,职位空缺少了,可以花更少的钱招聘出类拔萃的人才。我想说,如果你相信你应该得到更好的机会和更高的薪水,那你就应该得到。你不需要满足于更低的要求。你必须相信自己的价值,因为没有人比你自己更了解你。
2.为面试做好充分准备
在准备数据科学或软件工程面试时,人们通常需要花几周到几个月的时间来复习技术知识。比如你在面试数据科学岗位,需要复习:高级 SQL、基础 Python/R 数据操纵、统计学、实验设计、机器学习算法、产品/案例分析知识。如果你在面试机器学习工程职位,你还需要通过 Leetcode 编码问题。
我通常一决定找工作就开始面试,因为我把参加面试作为评估自己对面试准备程度的一种方式。然而,在这个充满挑战的时期,仍然在招聘的公司越来越少。在这些时候,更好的策略是花些时间复习所有需要的知识,然后参加面试,以免浪费面试机会。
但是请记住,你永远不会 100%准备好,不要等到你觉得自己 100%准备好了,因为那一天永远不会到来。
3.优化你的求职转换漏斗
诚然,有工作经验的人和没有工作经验的人之间的求职转换漏斗是不同的。然而,我认为差别在于找工作的难易程度,而不是一个人能否找到工作的决定性因素。
两年前我转行做数据科学家时,我的求职转换漏斗是:
475 份申请→ 50 次面试→ 8 次现场面试→ 2 次录用
我今年的求职转换漏斗是:
30 份申请→ 13 次面试→ 6 次现场面试→ 3 次录用
每两步之间的转换率如下所示:
2018 年和 2020 年我的求职转换漏斗
分析求职转换漏斗就像数据科学面试中的典型案例研究问题。目标是增加报价的数量。该指标是面试流程中每两步之间的转换率。对你来说,告诉你需要优化哪些步骤应该是简单明了的。
如果面试总数低,你应该尝试优化漏斗顶部。例如修改简历,申请更多的工作,寻找更多的推荐人,在尽可能多的平台上发布你的信息,让更多的人知道你在找工作等等。
如果你多次面试失败,你应该根据面试类型进行细分,以便进行更深入的分析。以数据科学面试为例,你可以分解一下,看看自己是不是需要去温习统计学知识或者案例研究知识,多练习 SQL 或者 Python 等。在你理解了哪些步骤在转化漏斗中下降最大后,集中精力改进这些步骤。
4.只关注你能控制的事情
人们谈论找工作有多难,因为公司提高了门槛。人们抱怨一些公司在他们的网站上发布招聘信息,但他们并不认真招聘。是的,他们可能是正确的。但我认为不值得花时间抱怨这些外部因素。
如果招聘门槛越来越高,你会停止找工作吗?
在你递交申请之前,你会仔细检查每一家公司,看看他们是否真的在招聘吗?
与其花时间担心你无法控制的事情,你可以用这些时间来研究更多的面试问题。如果你多研究一个问题,你可能会到达一家公司的招聘栏。如果你抱怨事情超出你的控制,你只是在为自己的失败找借口。
同样的逻辑也适用于你如何对待失败的面试。当你面试失败的时候,难过几分钟是可以的,但是不值得超过几分钟。当你面试失败时,你应该想想你失败的原因。是因为你给的一些答案不够好吗?或者你只是运气不好?如果你认为你失败是因为你没有回答好一些问题,下次试着在那些问题上做得更好。如果你觉得自己倒霉了,那就更好了,你根本不需要去想它!
永远不要因为面试失败而失去自信。你要相信自己很了不起。任何你做得不好的地方都可以改进。随着练习的增多,你会越来越好。
与其因为一些公司拒绝了你而怀疑自己,不如感谢他们给了你面试的机会,让你得到了锻炼面试技巧的机会。有了更好的面试技巧,当工作机会来找你的时候,你就能抓住更好的机会。
5.别人多快找到工作并不重要
有些人更喜欢高强度的求职过程,他们喜欢从早到晚只花几周时间做面试。有些人更喜欢平衡面试和他们的个人生活,所以他们准备得更慢。
有的人有多年的工作经验,基础知识过硬;因此,他们不需要花太多时间就能找到一份新工作。有的人经验少,或者需要更多的时间来夯实基础知识;因此他们需要更多的时间来准备。
每个人都有自己的节奏和时机。你只需要在你的轨道上稳步前进。没有必要拿自己和别人比较,或者被别人的成就所影响。你的最终目标是找到一份你愿意呆上几年的工作,而不是抓住任何一根稻草不放。
6.黑暗中总有一丝光明
我的同事和我的经历表明,裁员可以带来更好的工作机会,甚至升职。这次经历坚定了我的信念:生活中一切看似不幸的事情都是塞翁失马焉知非福。让转变发生的最重要的因素是 知道自己的价值,拥有自信,专注于你能控制的事情。"艰难的日子不会长久,但坚强的人会长久。"我希望你能站得更高,对抗试图把你拉下来的东西,我知道如果你想,你能做到。干杯。
安德里亚斯·楚在 Unsplash 上的照片
如何在 6 种想象中作为罗马皇帝生存
Jaime Spaniol 在 Unsplash 上拍摄的照片
去古罗马旅行,不用担心保险。
好吧,你在你的阁楼里发现了一个生锈的金属盒子,它属于你刚刚过世的祖父。你把它带到你的客厅,在你有机会把灰尘从顶部闪烁的红色按钮上吹出来之前,一道蓝光吞没了你的身体,突然你被加冕为罗马帝国的凯撒。你的 200 个小时的人对野对你在这里生存没有帮助,所以让我给你一些建议。
在一周的时间里,我探索了自凯撒的养子屋大维(因其头衔而被称为奥古斯都)于公元前 27 年夺取政权至 1453 年东罗马帝国灭亡期间,所有罗马皇帝的生活和(主要是)死亡。这些数据是从维基百科的罗马皇帝列表中刮出来的,并使用 Python(主要是 pandas 用于操纵数据,matplotlib/seaborn 用于绘图)进行分析。你可以在这里看到所有的代码。
经过紧张的研究,我整理了一些你去古罗马旅行前需要知道的基本知识。时间旅行公司有一个严格的不退款政策,以防在停留期间不幸死亡,所以如果你想节省那些宝贵的美元,请一起阅读。
当皇帝能有多危险?
好吧,我明白了。你在想,“当皇帝没那么糟糕。他们是地球上最强大的生物;甚至克娄巴特拉也没有惹他们。”你是对的,我们都听说过这些近乎神话的人物的事迹和荣耀。这种赞扬并不是不公平的;这些人是地球上最有权力的人之一。然而,强大的力量带来了巨大的嫉妒,我们都知道当时的叛逆兄弟关系(是的,布鲁图斯,我说的就是你)。
让我们通过绘制罗马皇帝死亡时的年龄和他们掌权的一段时间的直方图来进一步了解你的生存机会:
从直方图中,我们可以看到,与同时代的其他人相比,他们的寿命很长,预期寿命约为 51 岁(罗马帝国的预期寿命约为 25 岁)。起初,这可能证实了我们的期望,即出生在皇室中对这些幸运的私生子来说确实有所回报。然而,该分析忽略了一个事实,即婴儿死亡率是当时的主要死亡原因(大约一半的人口在 5 岁之前死亡),我们的样本只包含那些年龄足够成为皇帝的人。我们考虑的是那些度过了生命中最危险时期的人,但是谁知道有多少皇室婴儿在加冕前就死去了呢?如果我们把婴儿死亡率排除在外,当时的罗马人口实际上活到 50 多岁,这意味着我们的皇帝寿命一样长,如果不是更短的话。
直方图中第二个有趣的发现是,尽管皇帝们拥有永久的职位,但他们掌权的时间并不长。平均执政时间为 10 年,但一半以上的人执政时间只有 6 年或更短。让我们来比较一下美国总统:自 1789 年以来,共有 44 位总统,这意味着每一位总统平均在任时间为(2020–1789)/44 = 5.25 年,其中超过一半的总统在任时间不超过 4 年。没什么不同吧?
让我们试着想象一下这些皇帝掌权的时间,以及他们退休后是否过得很好。(图有些长)。
这个情节似乎证实了我们的怀疑。除了少数例外,大多数皇帝在掌权后就去世了,尤其是在帝国的最初几年。似乎完全控制地球上最强大的文明是一种诅咒。我们来调查一下这些帝王的死因;也许他们能对此事有所帮助。
正如我所料,暴力在地中海地区蔓延。在我能够获得死亡原因信息的 121 个皇帝中,74 个死于暴力——占 61%!
如果你成为罗马皇帝,如何生存-初学者指南。
让我们利用这张图表,通过采用预防生命每个阶段最常见死亡原因的技术,最大限度地提高你的生存机会。
如果你是 20 岁或更小,就要警惕了!篡位者会试图利用你的天真来对付你,所以要小心可疑的邀请,邀请你参加以战斗为主题的睡衣派对或者私人教练不断建议你和他们一起洗澡。
到了 30 岁,你的优先事项改变了:开始关注你的身体和精神健康。保持一个健康的身体会避免常见的疾病,并使凶手在与你的体质决斗前三思。
暴力的暂停是理所应当的,但不会持续太久,因为你 40 多岁的时候会提醒你永远不要放松警惕。此外,千万不要在没有阅读的情况下签署文件——罗马司法系统是无情的,你也不想最终站在斗兽场阳台的错误一边。
如果你活到 70 岁,干得好。尽管困难重重,你还是挺过了历史上最危险的工作之一(而且如此优雅!).当你从浴室的窗户面对你的帝国的广阔土地,回忆起黄金时代,你可以头脑风暴一些你名字的衍生词,给你上周末去过的那个迷人的小镇。
西罗马帝国有流行的死法吗?
下面的彩色条是这一时期暴力死亡的热图。
根据这个图表,是的。当谈到早期罗马帝国的死亡趋势时,暗杀是明显的赢家,特别是从公元 150 年到 300 年——我们在短短 50 年内就发生了 17 起谋杀。在暴力不再成为主流后,我们看到了自然死亡的回归,以及对斩首的少量但有意义的偏好。在过去的 50 年里,帝国的衰落激发了一场反文化运动,每个皇帝都开始尝试自己的死亡方式。
让我们尝试使用 Bokeh——Python 中的一个绘图工具——将前面图形中的所有信息浓缩成一个图形。
点数的大小与死亡时的年龄相对应。
重要提示
各位,今天的生存(和一些历史)课到此结束。从这些简单的图表中,我们了解到几件重要的事情:
- 当皇帝是一件很酷但可悲的短暂工作。
- 如果你想让你的孩子成为无情的独裁者,帕里奥洛戈斯是一个很好的名字。
- 如果你在时间和空间中回到罗马皇帝的身体,你生存的优先事项应该是(按照这个特定的顺序):不被谋杀,不进行无保护的性行为(性病和你的孩子都可能杀了你),让军队吃饱,避免参军(超过 60 岁在当时不是一个有效的借口),雇佣一名治疗师。
感谢您的阅读!
**免责声明:**本文为娱乐目的而写。我不能证明所讨论的信息的准确性。
如何用 MySQL 同步 Elasticsearch
使用 Logstash 创建一个连接 Elasticsearch 和 MySQL 的数据管道,以便从零开始建立一个索引,并将数据库记录上发生的任何变化复制到 Elasticsearch 中
快速访问链接
- GitHub 上的资源库: sync-elasticsearch-mysql 。
技术栈
- MySQL 作为主数据库(版本 8.0.22)
- 作为文本搜索引擎的弹性搜索(版本 7.9.3)
- Logstash 作为从 MySQL 到 Elasticsearch 的连接器或数据管道(7.9.3 版)
- 用于监控和数据可视化的 Kibana(版本 7.9.3)
- JDBC 连接器/J(版本 8.0.22)
内容
- 问题陈述
- 解决方案
-使用 Logstash 的好处
-用例 - 实施概念验证
-为项目创建主机目录
-设置 MySQL 数据库
-设置 Elasticsearch 和 Kibana
-设置 Logstash 将数据从 MySQL 传输到 Elasticsearch:
*第一个场景—从头开始创建 Elasticsearch 索引
*第二个场景—将数据库记录的更改复制到 Elasticsearch - 结论
- 资源
照片由 Sébastien Jermer 在 Unsplash 上拍摄
问题陈述
科技公司的一个常见场景是开始围绕一个或多个数据库构建其核心业务功能,然后开始将服务连接到这些数据库,以对文本数据执行搜索,例如在用户表的用户地址列中搜索街道名称,或者在图书馆的目录中搜索书名和作者姓名。
到目前为止一切都很好。公司不断发展壮大,获得了越来越多的客户。但随后搜索速度开始变得越来越慢,这往往会激怒他们的客户,并很难说服新的潜在客户购买。
从本质上看,工程师们意识到 MySQL 的FULLTEXT
索引对于在大型数据集上进行文本查找并不理想,为了扩大他们的业务,工程师们决定转向更专用的、经过实战检验的文本搜索引擎。
进入 Elasticsearch 及其底层 Lucene 搜索引擎。Elasticsearch 使用一个倒排文档索引来索引数据,这导致了极快的全文搜索。
一个新的挑战随之而来:如何将 MySQL 数据库中的数据放入 Elasticsearch 索引,以及如何保持后者与前者同步?
解决办法
现代数据管道工的工具包中包含了大量的软件,可用于任何数据操作任务。在本文中,我们将关注来自 ELK stack 的 Logstash,以便定期从 MySQL 获取数据,并将其镜像到 Elasticsearch 上。这将考虑到 MySQL 数据记录的任何变化,如create
、update
和delete
,并在 Elasticsearch 文档中复制相同的内容。
使用 Logstash 的好处
我们在这里试图解决的问题——定期从 MySQL 向 Elasticsearch 发送数据以同步两者——可以通过 cron 作业或任何作业调度程序运行的 Shell 或 Python 脚本来解决,但这将剥夺我们通过配置 Logstash 及其基于插件的设置所获得的好处:
- 虽然我们在这里主要关注 MySQL, Logstash 可以从许多来源获取数据,使它成为一个集中式数据输入节点。
- 当数据从源传递到目的地时,Logstash 提供了动态解析、转换和过滤数据的可能性。
- 至于输入源,有许多输出目的地可用——elastic search 是首选输出。
- 作为 ELK 堆栈的一部分,稍后,Elasticsearch 和 Kibana 将为度量和可视化提供很好的整合。
用例
我们将在以下步骤中介绍两种情况:
- 从头开始创建弹性搜索索引和索引数据库记录*。*
- 增量 根据数据库记录发生的变化(创建、更新、删除)更新弹性搜索索引的。
实施概念验证
想象一下,你正在开一个在线图书馆,热心的读者可以在那里搜索你的图书目录,找到他们的下一本书。您的目录包含数百万个标题,从科学文献卷到有关异国冒险的小册子。
我们将创建一个初始数据库表books
,其中有几千条记录,包括书名、作者、ISBN 和出版日期。我们将使用可以在 Kaggle 上找到的 Goodreads 图书目录。这个初始表将用于构建用例的原型(1)从零开始构建索引。
我们将在表books
上创建触发器,该触发器将用books
表上的所有更改填充日志表books_journal
(例如create
、update
、delete
)。这意味着无论何时在books
表上创建、更新或删除一条记录,该操作都将被记录在books_journal
表上,同样的操作也将在相应的 Elasticsearch 文档上执行。这将用于原型用例(2)弹性搜索指数的增量更新。
我们将通过使用 docker-compose 定义微服务架构来原型化和测试上述概念。
该项目的建筑——作者图片
先决条件
步骤
完整的源代码可以在 GitHub 的sync-elastic search-MySQL找到。
- 首先创建一个目录来托管这个项目(命名为
sync-elasticsearch-mysql
),并在该目录中创建一个 docker-compose.yaml 文件,初始设置如下:
version: "3"
services:
...
# Here will come the services definition
...
**2。设置一个 MySQL 数据库:**创建一个目录data/
,我们将在其中存储 MySQL 转储文件,这些文件包含books
表的预清理图书数据,以及books
表的触发器(关于创建、更新和删除),还有一个new_arrivals
表,其中包含我们将添加到目录中以模拟新记录的图书,以及表books_journal
。
您可以在项目资源库中找到这些转储文件。请将它们复制到data/
目录,以便 MySQL 容器在启动过程中将它们添加到books
数据库中。
version: "3"
services:
# add this:
mysql:
image: mysql:8
container_name: sem_mysql
ports:
- 3306:3306
environment:
MYSQL_RANDOM_ROOT_PASSWORD: "yes"
MYSQL_DATABASE: books
MYSQL_USER: avid_reader
MYSQL_PASSWORD: i_love_books
volumes:
# Dump files for initiating tables
- ./data/:/docker-entrypoint-initdb.d/
请注意,不建议在源代码中以纯文本形式存储用户名和密码。以上只是为了建立这个项目的原型,在任何情况下都不是推荐的做法。
要启动 MySQL 并检查数据是否已成功添加,请在终端上运行项目目录:
docker-compose up -d mysql # -d is for detached mode# Once container started, log into the MySQL container
docker exec -it sem_mysql bash# Start a MySQL prompt
mysql -uavid_reader -pi_love_books# Check that tables have been loaded from dump files
use books;
show tables;
可用表格列表和数据示例—按作者分类的图片
要以类似 JSON 的格式显示触发器,请使用命令:
SHOW TRIGGERS \G;# To exit the MySQL prompt press CTRL+D
# To logout from the MySQL container, press CTRL+D
既然我们已经正确地建立了数据库,我们就可以继续进行这个项目的实质性工作了。
3。设置 Elasticsearch 和 Kibana: 要设置 Elasticsearch(还没有索引任何文档),请将其添加到 docker-compose.yaml 文件中:
version: "3"
services:
...
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.9.3
container_name: sem_elasticsearch
environment:
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
volumes:
- ./volumes/elasticsearch:/usr/share/elasticsearch/data
logging:
driver: "json-file"
options:
max-size: "10k"
max-file: "10"
kibana:
image: docker.elastic.co/kibana/kibana:7.9.3
container_name: sem_kibana
environment:
- "ELASTICSEARCH_URL=[http://elasticsearch:9200](http://elasticsearch:9200)"
- "SERVER_NAME=127.0.0.1"
ports:
- 5601:5601
depends_on:
- elasticsearch
请注意,为了将弹性搜索索引数据从 docker 卷挂载到您的目录文件系统,建议使用卷定义。
要启动 Elasticsearch 和 Kibana,请从您的项目目录运行以下命令:
docker-compose up -d elasticsearch kibana # -d is for detached mode# To check if everything so far is running as it should, run:
docker-compose ps
在执行上述命令后,3 个容器应该启动并运行——Image by Author
让我们检查到目前为止我们的 Elasticsearch 节点中是否有任何索引:
# On your terminal, log into the Elasticsearch container
docker exec -it sem_elasticsearch bash# Once logged in, use curl to request a listing of the indexes
curl localhost:9200/_cat/indices
如果 Kibana 已经启动并运行,您将看到一个用于度量和可视化的索引列表,但是还没有与我们的书相关的内容——如果 Kibana 还没有启动,索引列表将是空的。
由 Kibana 创建的索引列表—图片由作者提供
4。设置 Logstash 将数据从 MySQL 传输到 Elasticsearch:
为了将 Logstash 连接到 MySQL,我们将使用官方的 JDBC 驱动程序,该驱动程序可以在这个地址获得。
让我们创建一个 Dockerfile(在同一个目录中命名为Dockerfile-logstash
)来提取一个 Logstash 映像,下载 JDBC 连接器,并启动一个 Logstash 容器。将这些行添加到您的 docker 文件中:
FROM docker.elastic.co/logstash/logstash:7.9.3# Download JDBC connector for Logstash
RUN curl -L --output "mysql-connector-java-8.0.22.tar.gz" "[https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.22.tar.gz](https://dev.mysql.com/get/Downloads/Connector-J/mysql-connector-java-8.0.22.tar.gz)" \
&& tar -xf "mysql-connector-java-8.0.22.tar.gz" "mysql-connector-java-8.0.22/mysql-connector-java-8.0.22.jar" \
&& mv "mysql-connector-java-8.0.22/mysql-connector-java-8.0.22.jar" "mysql-connector-java-8.0.22.jar" \
&& rm -r "mysql-connector-java-8.0.22" "mysql-connector-java-8.0.22.tar.gz"ENTRYPOINT ["/usr/local/bin/docker-entrypoint"]
然后将下面的代码片段添加到 docker-compose.yaml 文件中:
version: "3"
services:
...
logstash:
build:
context: .
dockerfile: Dockerfile-logstash
container_name: sem_logstash
depends_on:
- mysql
- elasticsearch
volumes:
# We will explain why and how to add volumes below
Logstash 使用定义的管道来知道从哪里获取数据,如何过滤数据,以及数据应该去往哪里。我们将定义两个管道:一个用于从头创建一个 Elasticsearch 索引(第一个场景),另一个用于数据库记录变更的增量更新(第二个场景)。
有关管道定义中使用的每个字段的解释,请查看文档:
- 输入: JDBC 输入插件
- 过滤:变异
[remove_field](https://www.elastic.co/guide/en/logstash/current/plugins-filters-mutate.html#plugins-filters-mutate-remove_field)
- 输出: Elasticsearch 输出插件
4.a .第一个场景——从头开始创建弹性搜索指数:
在您的项目目录中,创建一个volumes
文件夹(如果还没有创建的话),然后创建一个目录来托管我们的 Logstash 配置:
mkdir -p volumes/logstash/config
然后在这个配置目录下,创建一个文件pipelines.yml
,包含:
- pipeline.id: from-scratch-pipeline
path.config: "/usr/share/logstash/pipeline/from-scratch.conf"
然后,我们创建一个文件夹pipeline
来存放我们的管道定义:
mkdir volumes/logstash/pipeline
并在那里创建一个文件from-scratch.conf
,内容如下:
input {
jdbc {
jdbc_driver_library => "/usr/share/logstash/mysql-connector-java-8.0.22.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_connection_string => "jdbc:mysql://mysql:3306"
jdbc_user => "avid_reader"
jdbc_password => "i_love_books"
clean_run => true
record_last_run => false
statement_filepath => "/usr/share/logstash/config/queries/from-scratch.sql"
}
}filter {
mutate {
remove_field => ["[@version](http://twitter.com/version)", "[@timestamp](http://twitter.com/timestamp)"]
}
}output {
# stdout { codec => rubydebug { metadata => true } }
elasticsearch {
hosts => ["[http://elasticsearch:9200](http://elasticsearch:9200)"]
index => "books"
action => "index"
document_id => "%{isbn}"
}
}
我们在jdbc_driver_library
中定义了在哪里找到 JDBC 连接器,在jdbc_connection_string
中设置了在哪里找到 MySQL,在clean_run
中指示插件从头开始运行,并且我们在statement_filepath
中定义了在哪里找到 SQL 语句来获取和格式化数据记录。
过滤器基本上删除了插件添加的额外字段。
在输出中,我们定义在哪里找到 Elasticsearch 主机,将索引的名称设置为books
(可以是新的或现有的索引),定义要执行的操作(可以是index
、create
、update
、delete
— 参见文档,并设置哪个字段将作为books
索引中的唯一 ID—ISBN 是图书的国际唯一 ID。
为了添加由statement_filepath
引用的 SQL 查询,让我们创建一个文件夹queries
:
mkdir volumes/logstash/config/queries/
然后添加文件from-scratch.sql
,只有:
SELECT * FROM books.books
用到目前为止我们的books
表中所有可用的记录构建我们的索引。注意,查询不应该以分号(;).
现在,要挂载上面创建的配置文件和定义,请将以下内容添加到 docker-compose.yaml 文件中:
version: "3"
services:
...
logstash:
...
volumes:
- ./volumes/logstash/pipeline/:/usr/share/logstash/pipeline/
- ./volumes/logstash/config/pipelines.yml:/usr/share/logstash/config/pipelines.yml
- ./volumes/logstash/config/queries/:/usr/share/logstash/config/queries/
请注意,
volumes
指令是一种告诉 Docker 将容器内的目录或文件(的右侧)挂载到您的机器或服务器上的目录或文件(的左侧)的方式。在volumes
上查看官方 Docker 撰写文档。
测试
为了测试第一个场景的实现,在您的终端上运行:
docker-compose up logstash
如果运行成功,您将看到类似于Logstash shut down
的消息,容器将退出,并返回错误代码 0。
现在在你的浏览器上打开 Kibana(例如这个链接,让我们开始尝试看看我们是否有一个books
索引,以及我们如何搜索书籍。
图书索引已成功创建,包含 1k 个文档—图片由作者提供
在 Dev Tools 面板中,您可以运行定制查询来通过字段值获取文档。例如,让我们搜索标题中带有“魔法”一词的书籍。将此查询粘贴到开发工具控制台上:
GET books/_search
{
"query": {
"match": {
"title": "magic"
}
}
}
我们得到 9 份文件:
搜索标题中包含“魔法”一词的书籍-作者图片
图片由 Giphy 提供
4.b .第二个场景—将数据库记录上的更改复制到 Elasticsearch:
大部分配置和调整已经在前一部分完成。我们将简单地添加另一个管道来负责增量更新(复制)。
在文件volumes/logstash/config/pipelines.yml
中,添加这两行:
- pipeline.id: incremental-pipeline
path.config: "/usr/share/logstash/pipeline/incremental.conf"
在同一个文件中,您可能想要注释掉与“从头开始”部分(第一个场景)相关的前两行,以便指示 Logstash 只运行这个增量管道。
让我们在目录volumes/logstash/pipeline/
中创建一个文件incremental.conf
,内容如下:
input {
jdbc {
jdbc_driver_library => "/usr/share/logstash/mysql-connector-java-8.0.22.jar"
jdbc_driver_class => "com.mysql.jdbc.Driver"
jdbc_connection_string => "jdbc:mysql://mysql:3306"
jdbc_user => "avid_reader"
jdbc_password => "i_love_books"
statement_filepath => "/usr/share/logstash/config/queries/incremental.sql"
use_column_value => true
tracking_column => "journal_id"
tracking_column_type => "numeric"
schedule => "*/5 * * * * *"
}
}filter {
if [action_type] == "create" or [action_type] == "update" {
mutate { add_field => { "[[@metadata](http://twitter.com/metadata)][action]" => "index" } }
} else if [action_type] == "delete" {
mutate { add_field => { "[[@metadata](http://twitter.com/metadata)][action]" => "delete" } }
}mutate {
remove_field => ["[@version](http://twitter.com/version)", "[@timestamp](http://twitter.com/timestamp)", "action_type"]
}
}output {
# stdout { codec => rubydebug { metadata => true } }
elasticsearch {
hosts => ["[http://elasticsearch:9200](http://elasticsearch:9200)"]
index => "books"
action => "%{[[@metadata](http://twitter.com/metadata)][action]}"
document_id => "%{isbn}"
}
}
与之前的管道定义相比,我们看到了一些额外的参数。
schedule
参数有一个类似 cron 的语法(当左边增加一个值时,分辨率下降到秒),并在后台使用 Rufus 调度器。这里我们用*/5 * * * * *
指示 Logstash 每 5 秒运行一次这个管道。
网站 crontab.guru 可以帮你读懂 crontab 表达式。
在每次定期运行期间,参数tracking_column
指示 Logstash 存储获取的最后一条记录的journal_id
值,并将其存储在文件系统上的某个位置(参见文档,此处用于last_run_metadata_path
)。在接下来的运行中,Logstash 将从journal_id + 1
开始获取记录,其中journal_id
是当前运行中存储的值。
在filter
部分中,当数据库操作类型为“创建”或“更新”时,我们将 Elasticsearch 操作设置为“索引”,这样新文档就会被索引,现有文档也会被重新索引以更新它们的值。避免重新索引现有文档的另一种方法是编写一个定制的“更新”脚本,并使用“更新”动作。对于“删除”操作,Elasticsearch 上的文档会被删除。
让我们使用以下查询创建并填充目录volumes/logstash/config/queries/
中的文件incremental.sql
:
SELECT
j.journal_id, j.action_type, j.isbn,
b.title, b.authors, b.publication_date
FROM books.books_journal j
LEFT JOIN books.books b ON b.isbn = j.isbn
WHERE j.journal_id > :sql_last_value
AND j.action_time < NOW()
ORDER BY j.journal_id
测试
我们来看看表books.new_arrival
。它包含刚刚交付给我们的书籍,我们没有时间将它们添加到主books.books
表中。
“SELECT * FROM books.new _ arrival”—作者图片
如我们所见,该表中没有一本书在我们的 Elasticsearch 索引中。让我们试试上表中的第三本书《浪漫之路(艾尔西·霍金斯#4)》,ISBN 9780060598891:
搜索 ISBN 9780060598891 返回空结果—作者图片
现在,让我们将图书从新到货表转移到我们的主books
表:
INSERT INTO books
SELECT * FROM new_arrival WHERE isbn = 9780060598891;
在 Elasticsearch 上运行相同的搜索,我们很高兴地看到该文档现已可用:
现在 ISBN 9780060598891 可以在弹性搜索索引上找到——作者图片
同步成功了!
让我们测试同一个 ISBN 的更新:
UPDATE books
SET title = "The Rocky what ??"
WHERE isbn = 9780060598891;
数据库记录的更新被成功复制到 Elasticsearch 文档——按作者分类的图片
…以及删除相同的 ISBN:
DELETE from books WHERE isbn = 9780060598891;
从数据库中删除的记录也将从 elastic search index-Image by Author 中删除
图片由 Giphy 提供
结论
我们设法在很短的时间内获得了一个概念证明,即如何从 MySQL 数据库将数据索引到 Elasticsearch 中,以及如何使 Elasticsearch 与数据库保持同步。
我们使用的技术是业内的黄金标准,许多企业每天都依赖这些技术来服务他们的客户,很可能许多企业已经遇到或将会遇到我们在这个项目中解决的相同问题。
取得联系
如果你想联系我,或者你只是想让我知道你对这个项目的想法,不要犹豫,留下评论,或者通过电子邮件或 LinkedIn 联系我。
如果你觉得这个教程有用,并且你想支持高质量文章的制作,考虑给我买杯咖啡!
你可以点击“关注”按钮来获取我的最新文章和帖子!
资源
- 首次尝试建立倒排索引
- 数据输入:文件和索引
- 如何使用 Logstash 和 JDBC 保持 Elasticsearch 与关系数据库同步。这篇文章很有启发性,但是它并不涉及从零开始索引和删除记录。
- 本项目使用的数据可在 Kaggle 数据集 Goodreads-books 中获得。
- 日志 JDBC 输入插件
- 日志隐藏变异过滤器插件
- Logstash Elasticsearch 输出插件