熟悉 Rmarkdown Stargazer
R 的 Stargazer 库
ksen ia Samoylenko 在 Unsplash 上拍摄的照片
现在的幸福只会因为与过去的比较而破灭。~道格拉斯·霍顿
简介
回归分析今天不需要单独介绍。事实上,很难找到一个研究领域可以打赌在他们的生命周期中不使用这种技术至少一次就能赢。存在一种关系,等待某人通过某种回归技术的变体来探索。自从数学家阿德里安-玛丽·勒让德(Adrien-Marie Legendre)和卡尔·弗里德里希·高斯(Carl Friedrich Gauss)在 19 世纪初发明了这项技术以来,世界每天都在经历至少一个用例;被活在世上的某个人。想象一下如果人类无法获得这项技术会发生什么是很可怕的。如果这项技术没有公开,世界大战会如何发展?
在过去的十年中,随着开源平台和维护良好的统计估计库的出现,执行回归分析已经成为一项琐碎的任务。然而,比较不同条件和解释统计输出以解释潜在假设的性质的艺术将要求相关从业者通过公平的手段进行探究,直到永恒。人工智能算法旨在复制无错误的高效人类执行,然而,它可以像创建算法的开发人员一样学习表示艺术。
Stargazer 是一个最初为 R 平台开发的库,用于增强 R Markdown 文档中回归表的表示。作为一个用户,我们不能否认 stargazer 的结果在 pdf 文档中使用时非常类似于科学杂志或统计教科书的外观和感觉。
上面的文章试图鼓励读者积极考虑 R Markdown PDF。但是,这里说的是元数据和参考书目部分。stargazer 的使用在元数据之后,书目之前。
注意:如果读者有过一些学术论文的经历,那么本文并不打算区分作者的感知能力和实际能力。欢迎您的建议和经验。
议程
目的是分享一些可用于生成 PDF 输出格式的基本和扩展元素。我的目标不是出版一本有效的手册或食谱给读者,而是分享我在过去几周收集的快乐和挑战。不过在 RStudio 编辑器中使用 install.packages()函数预装这些包就好了;“rmarkdown”、“tinytex”、“gridExtra”、“kableExtra”、“stargazer”。首先,无论如何,我们都将依赖这些实用程序来完成本文。
包观星器
图-1 结构,表示在独立属性上逐一回归的同一响应变量的不同关键迭代。(图片来源) :图片来自作者
图 2 代表不同响应变量的结构,这些变量是在一组共同的独立属性上回归的。(图片来源) :图片来自作者
图 1 显示了线性回归模型的基本结构,其中研究人员或分析人员希望比较最重要的迭代,同时用一组独立属性回归相同的响应变量。然而,在每次迭代中,独立属性都是在考虑一些假设的情况下逐一引入的。这在因果分析和实验中特别有用,因为需要检查每个阶段独立属性的调节效果,以解释关键独立变量之一对响应变量的因果影响。
图-2 表示多元线性回归的基本结构,用于表示独立模型,用于比较数据集的不同响应变量在一组公共独立变量上回归时的结果。这对于比较一项研究中一组常见预测因子或因素对不同反应属性的影响特别有用。这种结构在基于关系的研究中很常见,是记录结论的有用快照。
Stargazer 还可以显示“lm”、“glm”和其他类型模型族的稳健标准误差。它同样有助于显示 logit 家族的β系数和指数标准差的比值比。本文中提到了一些有用的参考资料。如果有人想用 stargazer 做他们的论文或主要项目提交的实验,它们是重要的访问目的地,所以要求将它们放在手边。可以从 这里 和 这里 访问几种 pdf 格式。
需要注意的是,尽管回归的基本本质由于基于树或基于提升的算法迎合大数据的纯粹计算能力而变得成熟,但是涉及不同回归技术的基于关系的研究对于识别重要驱动因素总是有效且必要的。
本文后面的第一个代码片段使用了免费提供的 R datasets 包中的" freeny "数据集。关于……的讨论。bib 文件以及如何为书目创建它们可以在本文开头的链接中找到。使用 stargazer pdf 文档时,必须使用块集中的 results = 'asis '和 stargazer 函数中的 type = “latex”。如果我们处理的因子少于 40 个(在这个数据集中有 4 个),那么 single.row=TRUE 选项会很有帮助。此选项删除两个连续行之间的间距。intercept.bottom=FALSE 选项允许在线性模型中从 intercept 开始(除非我们明确地希望省略 intercept )。pdf 输出文档的快照也显示在代码片段之后。每列代表每次迭代的 beta 值及其相应的稳健标准误差(在括号内)。
图 freeny 数据集上的关键迭代。(图片来源) :图片来自作者
在第二段代码中,我们将处理免费提供的 R datasets 包中的"瑞士 " 数据集。数据帧中每个属性的描述可以在 这里 找到。使用 single.row=FALSE 并从报告中省略 F-statistics(omit . stat = c(" F "))允许在边距内拟合宽表。确保该函数生成的表格适合 PDF 页面的页边距是一项常见任务。与 HTML 不同,HTML 对于作者来说相对容易,并且避免了对边距的详细关注,PDF 输出需要一些额外的努力来遵守边距。
图 4 瑞士数据集上的关键迭代。(图片来源) :图片来自作者
在本文的第三个也是最后一个代码片段中,我们将处理免费提供的 R datasets 包中的" mtcars "数据集。协变量标签选项允许重新标记独立属性。
图 mtcars 数据集上的独立模型。(图片来源) :图片来自作者
结论
使用观星器无疑是很累的,因为需要注意的不仅仅是观星器的功能。作者必须同时考虑页边距、图形宽度、统计模型的整体结构、标题、脚注和字体大小。但是,这是对相关文档的一次性练习。一旦作者创建了一个适合分析的品味和本质的结构,那么为更大的目标修改微小的部分就变得微不足道了。尽管为一个格式良好的 R Markdown PDF 投入了所有的代码编辑、StackOverflow 搜索和自学时间,但结果是短暂而美好的,并且更容易专注于结果的详细解释。虽然不要求必须驻留在这些工具中以生成 PDF 格式的科学文档,但是在旅程结束时,这些亲身经历的记忆并不完全值得删除。这篇文章的意图并不是给人一种作者呼吁读者用半心半意的知识编写代码的印象。这纯粹是为了尊重研究人员、开发人员的辛勤工作,以及 StackOverflow 程序员的贡献,他们让这个 R Markdown 世界变得足够好,足以供基本的论文和报告创作探索和享受。还要注意的是,stargazer 也有一个 python 版本,在这里可以找到,但是到目前为止,如果读者想要估计 R 中的模型,并通过 R Markdown 来表示它们,那么采用 R 版本的 stargazer 将会获得比 Python 多得多的支持文档。原因是它最初是在 R 平台上开发的,随着最新版本的出现;用 Python 来处理数据工程工作,并用 R 来估算它们,变得越来越流行。
谢谢你。
熟悉 Tweepy、NLP 和 Seaborn - Job 招聘
轻松提取、处理、分析和可视化您的推文
Joshua Hoehne 在 Unsplash 上拍摄的照片
Twitter 是向观众分享新闻、信息和情感的最大平台之一。在这个前所未有的时期,许多人失去了工作。在这篇文章中,我们将尝试浏览过去的推文,通过这些推文了解人们对工作的思维过程。我们将从赞和转发的角度来看推文的趋势。我们还将根据它们的位置对它们进行可视化。最后,我们将根据 tweets 中的关键字搜索,根据招聘人员和被招聘人员对他们进行分类。
我们将使用 python 作为我们的编程语言,tweepy 从 Twitter 中提取 tweets。我们将尝试从公司获得一些关于人们工作要求和招聘更新的某些趋势的见解。所以让我们开始导入库。
import csv
import pandas as pd
import csv
import re
import string
import tweepy
import time
import ast
from nltk.corpus import stopwords
from wordcloud import WordCloud
from textblob import TextBlob
import seaborn as sns
import matplotlib.pyplot as plt
%matplotlib inline
所有这些库都会在编写代码的某个时候帮助我们。当我们遇到这些细节时,我们会着手处理的。
我们的第二步将是从 Twitter 中提取推文,并将其保存在 CSV 文件中。一个人必须有一个 Twitter 开发者帐户,才能使用 Twitter api 访问推文。下面是创建开发者帐户的链接。
申请接入——Twitter 开发者| Twitter 开发者
def extract_tweets():
auth = tweepy.OAuthHandler(‘xxxxxxxxxx’, ‘xxxxxxxxxx’)
auth.set_access_token(‘xxxxxxx–xxxxxxxx’, ‘xxxxxxxxxx’)
api = tweepy.API(auth)
search_words = “jobs” #enter your words
new_search = search_words + “ -filter:retweets”
csvFile = open(‘jobs1.csv’, ‘a’)
csvWriter = csv.writer(csvFile)
for tweet in tweepy.Cursor(api.search,q=new_search,tweet_mode=’extended’,count=100,
lang=”en”,
since_id=0).items():
csvWriter.writerow([tweet.created_at, tweet.full_text.encode(‘utf-8’),tweet.user.screen_name.encode(‘utf-8’),
tweet.favorite_count,tweet.retweet_count,tweet.truncated,
tweet.user.location.encode(‘utf-8’)])
return
在上面的代码中,我们使用 tweepy 模块初始化 twitter api。在与我们的 twitter 帐户建立连接之后,我们将提取的 twitter 数据添加到 csv 文件中,并开始向其中追加 twitter 数据。我们的数据将包含日期,文本,姓名,喜欢,转发,截断和位置。
注意:提取的推文必须进行编码,因为它们的格式不可读。我们将在接下来的步骤中解码推文。
def read_data():
df=pd.DataFrame()
df=pd.read_csv('jobs1.csv')
df.head()
return df
使用这个函数,我们只需读取我们成功创建的数据。
def pre_processing(df):
df.columns=['Date','Tweet','Name','Likes','Retweet','Truncated','Location']
df['Tweet']=df['Tweet'].apply(lambda x:ast.literal_eval(x).decode('utf-8'))
df['Location']=df['Location'].apply(lambda x:ast.literal_eval(x).decode('utf-8'))
df['Name']=df['Name'].apply(lambda x:ast.literal_eval(x).decode('utf-8'))
df.drop(['Truncated'],inplace=True,axis=1)
return df
现在我们命名这些列,并使用 ast 库将 tweets 解码成可读的格式。
def assorted_tweets(df):
location=['Atlanta, GA','Washington, DC','Los Angeles, CA', 'New York, NY', 'Chicago, IL', 'California, USA', 'Houston, TX',
'San Francisco, CA','New Jersey, USA','Boston, MA','Raleigh, NC','Nashville, TN','Seattle, WA','Pittsburgh, PA',
'Austin, TX','Dallas, TX','California','Portland, OR','Texas', 'Toronto','Phoenix, AZ','New York, USA','Toronto, Ontario', 'Texas, USA','Philadelphia, PA','Denver, CO','New York','Florida, USA','Manchester & San Francisco','Charlotte, NC','Las Vegas, NV','Cleveland, OH','Florida','Pennsylvania, USA','Maryland, USA','Louisville, KY','San Antonio, TX','Brooklyn, NY','Orlando, FL','Washington, D.C.','Miami, FL','Lagos, Nigeria','San Diego, CA',
'Detroit, MI','Colorado, USA','Michigan','Columbus, OH','Los Angeles','Sacramento, CA','New Jersey','Winchester, VA',
'Baltimore, MD','Pennsylvania','Providence, RI','Indianapolis, IN','North Carolina','Virginia, USA','Indiana','Colorado', 'Illinois, USA','St. Paul, MN','Buffalo, NY','North Carolina, USA','Calgary, Alberta']
df_new= df[df['Location'].isin(location)]
df_new.reset_index(inplace=True)
df_new.drop(['index'],inplace=True,axis=1)
return df_new
我们将只考虑美国的数据,因为最多的推文来自该国。这可以通过对数据帧中的“位置”列应用 value_counts 函数来解决。
def view_data():
pd.set_option(‘display.max_rows’, None)
pd.set_option(‘display.max_columns’, None)
pd.set_option(‘display.width’, None)
pd.set_option(‘display.max_colwidth’, None)
return
重要的是,我们能够完整地看到我们的数据,因此我们调用上面的函数,这样可以方便地通过 dataframe 读取 tweets。
def mention_data(df_new):
mention=[]
for i in df_new['Tweet']:
txt=i
x = re.findall("@", txt)
mention.append(x)
df_new['Mentions']=mention
df_new['len']=df_new['Mentions'].map(lambda x: len(x))
mentions['Total']=df_new['len'].groupby(df_new['Location']).sum()
df_new.drop(['Mentions'],inplace=True,axis=1)
return df_new, mentions
我们从统计每条推文的提及次数开始分析。我们还创建了一个提及表,用于将来的广泛分析。
def clean_tweets(df_new):
stop = stopwords.words('english')
df_new['Tweet'] = df_new['Tweet'].apply(lambda x: ' '.join([word for word in x.split() if word not in (stop)]))
df_new['Tweet']=df_new['Tweet'].apply(lambda x: str(x).split('http')[0])
for i in range(len(df_new['Tweet'])):
v = df_new['Tweet'][i]
v = re.sub(r"@[A-Za-z0-9]+", "", v)
df_new['Tweet'][i]=v
return df_new
我们开始使用停用词模块清理我们的推文,并从推文中删除停用词。除此之外,我们删除了标签以及与每条推文相关的“http”链接。我们使用 regex 模块删除 tweets 中的标签和链接。
def create_wordcloud(df_new):
words=''.join(list(df_new['Tweet']))
spam_wc=WordCloud(width=512,height=512).generate(words)
plt.figure(figsize=(8,6),facecolor='k')
plt.imshow(spam_wc)
plt.axis('off')
plt.tight_layout(pad=0)
plt.show()
return
我们创建了一个 tweets 的词云,它给我们提供了所有使用最频繁或不经常出现的词的要点。
def sentiment_analysis(df_new):
sentiment=[]
Type=[]
polarity=0
for i in df_new['Tweet']:
sentiments=TextBlob(i)
sentiment.append(sentiments)
tweet_polarity=sentiments.polarity
if tweet_polarity>0.00:
Type.append('Positive') elif tweet_polarity<0.00:
Type.append('Negative') elif tweet_polarity==0.00:
Type.append('Neutral')
polarity+=tweet_polarity
df_new['Sentiment']=Type
return df_new
我们对我们的推文进行一个非常简单的情感分析。情感是基于极性而被划分的。推文分为正面、负面或中性。我们使用“Textblob”作为我们的 python 模块来帮助我们找到推文的极性。
def recruiter_recruitee(df_new):
df_recruitee = df_new[df_new['Tweet'].str.contains('need')|df_new['Tweet'].str.contains('want work')|
df_new['Tweet'].str.contains('help')|df_new['Tweet'].str.contains('new job')|
df_new['Tweet'].str.contains('looking')|df_new['Tweet'].str.contains('support')]
df_recruitee.drop_duplicates(inplace=True)
df_recruiter = df_new[df_new['Tweet'].str.contains('link bio')|df_new['Tweet'].str.contains('hiring')|
df_new['Tweet'].str.contains('looking')|df_new['Tweet'].str.contains('job opening')|
df_new['Tweet'].str.contains('recommend')]
df_recruitee.drop_duplicates(inplace=True)
return df_recruitee,df_recruiter
我们现在把我们的推文分成 2 个数据帧。我们的第一个数据框架将是招聘人员,第二个将是招聘人员。我们根据单词云中最明显的关键词对它们进行分类。例如,recruitee 中的推文将包含诸如支持、帮助、新工作等词语,而招聘人员的推文包含诸如开放、寻找、推荐等词语。
if __name__ == '__main__':
extract_tweets()
view_data()
df=read_data()
df=pre_processing(df)
df_new=assorted_tweets(df)
mentions=pd.DataFrame()
df_new,mentions=mention_data(df_new)
df_new=clean_tweets(df_new)
df_new=sentiment_analysis(df_new)
df_recruitee,df_recruiter=recruiter_recruitee(df_new)
我们现在可以继续进行可视化。
if __name__ == '__main__':
create_wordcloud(df_new)
我们创建了一个词云来检查我们推文中的常用词。
mentions.reset_index().sort_values(by='Total',ascending=False).head(7)
我们检查在哪个州的人们倾向于在他们的推文中提到其他人。
plt.subplot(121)
df1=df_new[‘Likes’].groupby(df_new[‘Location’]).mean().sort_values(ascending=False).head(7)
df1.plot(kind=’bar’,colormap=’viridis’,figsize=(7,5))
plt.xticks(rotation=45)
plt.subplot(122)
df2=df_new[‘Retweet’].groupby(df_new[‘Location’]).mean().sort_values(ascending=False).head(7)
df2.plot(kind=’bar’,figsize=(12,5))
plt.xticks(rotation=45)
plt.show()
我们创建了一个关于地点的赞和转发的柱状图。我们可以看到,与其他推文相比,来自华盛顿、迈阿密和纽约等大城市的推文产生了更多的影响。
plt.subplot(121)
df1=df_new['Likes'].groupby(df_new['Sentiment']).sum().sort_values(ascending=False).head(7)
df1.plot(kind='bar',colormap='viridis',figsize=(7,5))
plt.xticks(rotation=45)
plt.subplot(122)
df2=df_new['Retweet'].groupby(df_new['Sentiment']).sum().sort_values(ascending=False).head(7)
df2.plot(kind='bar',figsize=(12,5))
plt.xticks(rotation=45)
plt.show()
我们检查哪种类型的情绪获得了最多的喜欢和转发。显然,积极的推文在这方面有优势。
plt.subplot(121)
df1=df_new['Likes'].groupby(df_new['Sentiment']).mean().sort_values(ascending=False).head(7)
df1.plot(kind='bar',colormap='viridis',figsize=(7,5))
plt.xticks(rotation=45)
plt.subplot(122)
df2=df_new['Retweet'].groupby(df_new['Sentiment']).mean().sort_values(ascending=False).head(7)
df2.plot(kind='bar',figsize=(12,5))
plt.xticks(rotation=45)
plt.show()
令人惊讶的是,负面推文平均获得更多的喜欢和转发。
plt.subplot(121)
df1=df_recruitee['Sentiment'].value_counts()
df1.plot(kind='bar',colormap='viridis',figsize=(7,5))
plt.xticks(rotation=45)
plt.subplot(122)
df2=df_recruiter['Sentiment'].value_counts()
df2.plot(kind='bar',figsize=(12,5))
plt.xticks(rotation=45)
plt.show()
我们检查招聘人员和被招聘人员表中的情绪分布。
plt.figure(figsize=(12,5))
plt.subplot(121)
df1=df_recruitee['Likes'].groupby(df_new['Sentiment']).mean()
plt.pie(df1,labels=df1.index,autopct='%1.1f%%',shadow=True)
plt.subplot(122)
df2=df_recruiter['Likes'].groupby(df_new['Sentiment']).mean()
plt.pie(df2,labels=df2.index,autopct='%1.1f%%',shadow=True)
plt.figure(figsize=(12,5))
plt.show()
我们使用饼图来检查喜欢和转发的情绪分布。我们可以看到,中性的推文往往比其他推文产生更多的喜欢。
plt.subplot(131)
a=df_recruitee[df_recruitee['Sentiment']=='Positive']['Location'].value_counts().head(5)
a.plot(kind='bar',colormap='viridis',figsize=(14,6))
plt.xticks(rotation=45)
plt.subplot(132)
b=df_recruitee[df_recruitee['Sentiment']=='Negative']['Location'].value_counts().head(5)
b.plot(kind='bar',colormap='cividis',figsize=(14,6))
plt.xticks(rotation=45)
plt.subplot(133)
b=df_recruitee[df_recruitee['Sentiment']=='Neutral']['Location'].value_counts().head(5)
b.plot(kind='bar',colormap='plasma',figsize=(14,6))
plt.xticks(rotation=45)
plt.show()
与被招聘者表中的位置相关的正面、负面和中性推文。
我们可以看到,与洛杉矶和德克萨斯州的人相比,华盛顿和旧金山的被招聘者更积极。
plt.subplot(131)
a=df_recruiter[df_recruiter['Sentiment']=='Positive']['Location'].value_counts().head(5)
a.plot(kind='bar',colormap='viridis',figsize=(14,6))
plt.xticks(rotation=45)
plt.subplot(132)
b=df_recruiter[df_recruiter['Sentiment']=='Negative']['Location'].value_counts().head(5)
b.plot(kind='bar',colormap='cividis',figsize=(14,6))
plt.xticks(rotation=45)
plt.subplot(133)
b=df_recruiter[df_recruiter['Sentiment']=='Neutral']['Location'].value_counts().head(5)
b.plot(kind='bar',colormap='plasma',figsize=(14,6))
plt.xticks(rotation=45)
plt.show()
关于招聘人员表中位置的正面、负面和中性推文。
同样,我们可以看到,与丹佛和新泽西相比,亚特兰大和芝加哥的招聘人员更加积极。
就这样结束了。我们成功地浏览了我们的推文。我们设法深入了解了不同城市人们对于工作的思维过程。我们还看到了哪些推文在点赞和转发方面更具吸引力。
欢迎留下任何问题或评论!
获得反馈在没有教师的情况下在线学习数据科学
米利安·耶西耶在 Unsplash 上拍摄的照片
当你编码时,你有时会从另一双眼睛那里学到很多东西,那双眼睛会阅读你的工作,捕捉你的错误,并告诉你怎样做得更好。在许多课程中,教师或至少助教会手动阅读你的代码并提供反馈。但是,有些课程是自定进度的课程,您不会从讲师那里获得定制的反馈。即使在这些类型的课程中,你也有向他人学习的方法。
查看相关的问答网站
即使是一个非常有天赋的懂文档的程序员也会经常犯编程错误,尤其是在开始的时候。他们可能不会马上意识到为什么。当我在一个特定的问题上需要帮助时,我的第一站通常是堆栈溢出,有时我会在查看标准文档之前先查看一下。那是一个很受欢迎的问答网站,专注于编程问题的答案。
截图我的。
如果你有一个编程问题,很可能——特别是如果你刚刚开始——许多其他人也有一个非常相似的问题。这些问题和其他人对它们的回答可能已经在网站上分享了。如果你的问题与堆栈溢出略有跑题,同一公司的其他网站 Stack Exchange 涵盖了相关的技术主题。
数据科学不仅是编程,还包括许多其他领域。像 Quora这样的问答网站可以在数据科学的其他领域给你更多的建议,比如分析数据的策略。如果你在某个网站上找不到你的问题,问这个问题,寻求答案,帮助下一个出现的人并不丢人。
开始或加入一个学习小组
你可能还想组织一群人一起学习这门课程。如果你还没有感兴趣的朋友,在社交媒体上发布你对这门课程的兴趣。您还可以加入 Meetup 群组,并将课程作为事件发布在那里。Meetup 是一个为有特殊兴趣的人宣传事件的社交网络。在新冠肺炎登陆之前,它是现场技术活动的主要推广地之一。现在,许多活动都转移到了网上。这可能对你有利,因为你可以在更大的地理范围内吸引同学。
在某些情况下,对你有帮助的事件已经被安排好了。专注于特定技术或更广泛的数据科学的 Meetup 小组可能有办公时间。我所知道的,来自纽约的,可以推荐的团体包括黑客小时、纽约女性编码和纽约 Python Meetup 团体。所有人都至少部分搬到了网上,所以你可以从世界任何地方加入。类似的聚会团体存在于大多数拥有相当规模的技术社区的城市。
如果你经常参加科技活动,你也会接触到一群与你水平相当或略高的人。这个挺有用的。你的朋友可以给你出主意去哪里,如何规划你的职业道路。我在这些活动中遇到的一些朋友已经成为非常成功的技术专家。我仍然和他们保持联系,甚至在他们结婚、有了孩子并搬离纽约多年以后。
寻找你的支持网络
图片来自 nytech.org
一般用途的社交活动大多会吸引那些刚刚开始职业生涯的人。纽约技术联盟组织的纽约技术聚会是吸引更有经验者的一个团体。它的重点是展示崭露头角的纽约科技公司和有趣的项目。它还举办网络会议,让整个技术行业处于职业生涯各个阶段的专业人士和学生能够交流。纽约是世界顶级技术中心之一,即使你在另一个城市,这个团体的在线活动也值得参加。
然而,对你的工作获得个性化反馈的最好方法是多付一点钱,聘请一位行业经验丰富的导师。如果你能找到一个专业数据科学家的好导师,我建议你雇佣他们每周一次或两次,每次一两个小时的指导。这几乎可以像一个现场编码训练营一样教你很多东西,而且价格要低得多。对于美国家教来说,每小时 50-100 美元是合理的。你可以在 Meetup 群和工作论坛上发布你的家教职位,比如说zipcruiter、、Angel.co和。这是一份相当不错的技术职位列表。这里有一些在 Indeed 上辅导工作岗位的例子。
也有可能以更低的价格获得几乎同样质量的教学。如果你有联系大学部门和校友网络的关系,你很可能能够以接近每小时 30-50 美元的价格雇佣一名研究生或高级本科生。这些学生中的一些人在该领域知识渊博,在教学方面很有天赋,他们的辅导质量可以接近专业人士的辅导。或者你可以用更低的价格外包一个家教,可能是外包到国外,使用像 Upwork 这样的平台。尤其是印度是一个讲英语的地方,许多人懂技术,劳动力成本也更低。另一个降低成本的方法是和你的同学分享一个家教的价格。
即使是专业人士也需要知道向哪些专家询问他们专业领域之外的问题。在他们将代码添加到主程序之前,他们通常还会经历一个称为代码审查的过程。在代码评审期间,一个团队成员通读他们的代码。队友经常会有有价值的反馈,即使是世界一流的著名程序员。这类似于写作,另一个强调可读性和优雅的领域。即使是最伟大的作家也有编辑,一个人与编辑一起工作的能力可以增强他的写作能力。我知道——我不仅为专业报纸和杂志写过文章,还在谷歌做过软件工程师。与写作中的编辑过程一样,代码审查是严格的软件开发过程中的关键步骤。
这是我写的另一篇文章,提供了更多关于在自学课程中学习数据科学的技巧。
进入数据科学:自学与训练营
哪种方法更好?
今天的世界允许我们超越学位和地理位置自由思考。互联网让世界各地的人们能够访问相同的数据,相互交流,相互学习。技术的爆炸使一切成为可能,使人们在 30 岁或 40 岁,甚至更晚的时候开始新的职业成为可能;使学生有可能在其他国家上学和学习课程。
虽然,有很多选择通常是一件好事,因为你可以根据自己的能力和情况选择最适合自己的。例如,如果你考虑从事数据科学,你有不止一个选择来实现这个目标。如果你还年轻,还在读高中,或者更年轻,那么获得计算机科学或任何相关领域的学士学位可能是你想要的起步。
但是,如果你年纪大了,已经尝到了工作生活的滋味,并考虑换一份职业,回到学校可能不是你的理想选择——甚至不是一个选择。因此,你通常有两种选择,要么带着一些钱(通常是很多钱)去训练营待几个月,要么系好安全带,打开笔记本电脑,在网上搜索信息。
这两个选项都是有效的,并且通常可以在不考虑您的物理位置的情况下完成。但是,一个比另一个需要更多的钱,这并不总是可行的。那么,你该走哪条路呢?有没有一种方法最终能保证一份工作?哪个更容易?本文将为您解答这些问题。
选项 1:参加训练营
让我们从选择参加训练营开始吧。这适用于您在 COVID 时代前后亲自或在线参加训练营。在过去的十年里,教授任何与技术相关的东西的训练营的数量呈指数级增长。这个数字的增加是对程序员、开发人员和数据科学家需求的增加。
参加训练营是一个非常诱人的选择,前提是你有足够的资金。现在,有数百家公司提供与数据科学相关的训练营,比如,熨斗,旅行车,总装, Thinkful 等等。这些公司的学费从 9500 美元到 17900 美元不等,承诺时间长达 15~20 周。
训练营职业选手
- 参加训练营将为您提供所需的数据科学实用知识。
- 你可以参加专注于一个特定主题或数据科学方面的训练营,如机器学习、人工智能或数据分析。
- 有些训练营的承诺只有 3 个月,这意味着在相对较短的时间内转行是一个很好的选择。
- 参加训练营将有助于你开始建立项目组合,积累实践经验。
- 如果你想有朋友与你分享学习之旅,这是一个很好的选择。
</7-tips-for-data-science-newbies-d95d979add54>
训练营囚犯
- 在我看来,训练营最大的缺点是它会变得多么昂贵。学费高达 18,000 美元,许多人负担不起参加训练营的费用,即使他们想要你。有时,一些公司提供奖学金和学费折扣,但这并不总是可行的。
- 几乎所有的训练营都在他们网站的第一页承诺在短时间内完成工作安排,这导致人们获得一些虚假的希望。因为即使你成功地完成了一次训练营,你也会发现找工作的困难。毕竟,这完全取决于就业市场的要求和你的投资组合。
- 由于大多数训练营专注于一个特定的主题或主题的一个特定方面,他们往往会忽略你在职业生涯中某个时候需要的计算基础。
选项 2:跟随自己的步伐(自学)
本文中我们考虑的另一个选项往往是最常见的选项,也是我个人在学习数据科学时采取的选项,也就是自学选项。自学是互联网的优势之一,也是世界的开放性。如果你今天想自学一些东西——不一定是科技话题——你可以在网上找到无穷无尽的资源。
这很神奇,因为你开始自学所需要的只是一些热情、开始,以及——这是棘手的部分——一个稳定的互联网连接,或者至少是一个体面的连接。在线学习数据科学有许多选择,从像 DataCamp 、 DataQuest 这样的伟大资源,以及像 Coursera 和 edX 这样的一些更普通的教育网站。
自学专家
- 通常,选择自学要比参加训练营便宜得多——如果不是免费的话,这使它成为世界各地许多人的有效选择。
- 当你自己做的时候,你可以完全控制自己的时间。例如,你想什么时候开始,什么时候结束,你想以多快/多慢的速度处理每个方面。
- 当你独立学习时,你可以在任何话题上想多深就多浅。
- 自学数据科学将教会你如何独立,知道如何在正确的地方寻找信息。
- 你将学会如何解决你面临的任何问题。因为你是自己做的,你会发展出一种高效处理和解决问题的技术。
</5-online-data-science-courses-you-can-start-now-748e4a2b5403>
自学的缺点
- 自学最难的是,你不会有一条结构化的道路可走。你需要制定自己的课程,或者在网上找一个,然后坚持下去。如果你参加免费的在线自学课程,情况可能就不一样了。
- 既然你是一个人去,那么有时很容易失去动力,感觉自己是一个人在经历旅程,这可能会让事情花的时间比应该花的时间长。然而,你可以通过加入一个在线社区并在旅途中结交朋友来克服这一点。
- 与训练营不同的是,你需要选择你所从事的项目,并努力让它们变得强大和有效,以便在适当的时候让求职过程变得更加容易。
最后的想法
无论你在生活中想做什么,有很多方法可以达到那个目的。做出选择并坚持到底——或者如果你想改变它——完全取决于你。如果你想转行进入数据科学领域,这同样适用。数据科学是一个充满无限机遇和机会的伟大领域。这是一个适合许多有不同激情的人的领域。
但是,进入这个领域并不总是简单的。进入数据科学有很多方法。例如,你可以去重点学习数据科学的学校,你可以参加许多在线或面对面的训练营,或者你可以浏览网页,自学。
</5-new-data-science-books-that-you-should-consider-reading-c90aec1d5b0d>
所有这些选项都是有效的,你的选择将取决于你作为一个人,你的物理位置,你的目标,以及你想如何实现它。这篇文章向你展示了两个最重要的选择:参加训练营或者按照自己的进度自学。我想告诉你的是,这些选择没有一个能百分百保证找到工作。但是,如果你努力工作,建立一个好的投资组合,你会得到你想要的工作,不管你走的是哪条路。
从熊猫数量中获取更多价值()
有效使用熊猫count()
方法的 5 个技巧
苏珊·霍尔特·辛普森在 Unsplash 上的照片
熊猫图书馆是最受欢迎的数据操作和分析工具之一。数据科学家通常花费大部分时间探索和预处理数据。谈到数据分析和理解数据集,Pandas count()
是了解非 NA 数量的最常用方法之一。
这个方法很快,很快,很容易理解,但是,大多数时候,我们最终使用了带有默认参数的count()
。在本文中,您将了解如何从中获得更多价值。这篇文章的结构如下:
- 对每一列和每一行的非 NA 细胞进行计数
- 在多指数数据框架上计数非钠细胞
- 仅用
numeric_only
计数数字 - 将
count()
应用于groupby()
结果 - 将计数组合回原始数据帧
源代码请查看笔记本。
访问 Github Repo 获取其他教程
1.对每一列和每一行的非 NA 细胞进行计数
Pandas count()
用于计算给定轴上非 NA 细胞的数量。值None
、NaN
、NaT
和可选的numpy.inf
被认为是NA
。
例如,默认情况下,该方法对每一列的非 NA 进行计数
df = pd.DataFrame({
"Person": ["John", "Tom", "Lewis", "John", "Myla"],
"Age": [24., np.nan, 21., 33, 26],
"Single": [False, True, True, None, np.datetime64('NaT')],
"Department": ["Product", "IT", "IT", "IT", "Product"]
})>>> **df.count()**Person 5
Age 4
Single 3
Department 5
dtype: int64
如果我们希望对每行的非 NA 进行计数,我们可以将axis
参数设置为1
或'columns'
:
>>> df.count(**axis = 1**)0 4
1 3
2 4
3 3
4 3
dtype: int64>>> df.count(**axis = 'columns'**)0 4
1 3
2 4
3 3
4 3
dtype: int64
2.在多指数数据框架上计数非钠细胞
一个多索引数据帧允许多个列作为一个行标识符,多个行作为一个标题标识符。例如,让我们用性别和幸存的列作为索引来加载泰坦尼克号数据集。
df = pd.read_csv(
'titanic_train.csv',
**index_col=['Sex', 'Survived']**
)
df.head()
作者图片
例如,我们可以设置参数level
来计算非 NA 以及特定的索引级别
df.count(**level='Sex'**)
熊猫count(level='Sex')
作者图片
df.count(**level='Survived'**)
熊猫count(level='Survived')
作者图片
如果您想了解更多关于 MultiIndex 的信息,请访问:
[## 在熊猫的多索引数据框架中访问数据
towardsdatascience.com](/accessing-data-in-a-multiindex-dataframe-in-pandas-569e8767201d)
3.仅在数字上执行count()
在熊猫count()
中有一个关于numeric_only
只配置数字计数的争论。值 float 、 int 和 boolean 被认为是数字。
参数默认为False
,我们可以将它设置为True
来只计算数值:
>>> df.count(**numeric_only=True**)PassengerId 891
Pclass 891
Age 714
SibSp 891
Parch 891
Fare 891
dtype: int64
4.将 count()应用于 groupby()结果
Pandas [groupby()](/all-pandas-groupby-you-should-know-for-grouping-data-and-performing-operations-2a8ec1327b5)
允许我们将数据分成不同的组来执行计算,以便更好地进行分析。
一个常见的用例是按某一列进行分组,然后获取另一列的计数。例如,让我们按“部门列进行分组,并获得“**单个”**值的计数。
df = pd.DataFrame({
"Person": ["John", "Tom", "Lewis", "John", "Myla"],
"Age": [24., np.nan, 21., 33, 26],
"Single": [False, True, True, None, np.datetime64('NaT')],
"Department": ["Product", "IT", "IT", "IT", "Product"]
})>>> **df.groupby('Department')['Single'].count()**Department
IT 2
Product 1
Name: Single, dtype: int64
或者,我们也可以使用聚合agg('count')
方法。
>>> df.groupby('Department')['Single']**.agg('count')**Department
IT 2
Product 1
Name: Single, dtype: int64
我们已经对groupby()
结果的特定列执行了count()
。事实证明,我们实际上不必指定像 Single 这样的列。如果没有列,它会将count()
应用于所有列,例如:
>>> df.**groupby('Department').count()**>>> df.**groupby('Department').agg('count')**
如果您想了解更多关于groupby()
的信息,请查看:
5.将计数组合回原始数据帧
在某些情况下,您可能希望将计数写回原始数据帧,例如,我们希望追加一列 department_total_single ,如下所示:
作者图片
这个任务中棘手的部分是,df.groupby()['Single'].cout()
返回只有 2 行的序列(如下所示),它不会匹配原始数据帧中的行数。
>>> df.**groupby('Department')['Single'].count()**Department
IT 2
Product 1
Name: Single, dtype: int64
一种解决方案是将上述结果转换成 DataFrame,并使用merge()
方法组合结果。
>>> temp_df = df.groupby('Department')['Single'].count().**rename('department_total_count').to_frame()** >>> temp_df.**reset_index()**
>>> df_new = pd.**merge(df, temp_df, on='Department', how='left')**
熊猫分组和合并(图片由作者提供)
这当然有助于我们的工作。但是这是一个多步骤的过程,需要额外的代码来获得我们需要的形式的数据。
我们可以使用transform()
函数有效地解决这个问题。一行代码就可以解决应用和合并问题。
>>> df.groupby('Department')['Single']**.transform('count')**0 1
1 2
2 2
3 2
4 1
Name: Single, dtype: int64
我们可以看到transform()
的结果保留了与原始数据集相同的行数。因此,我们可以简单地将结果赋给原始数据帧中的新列:
>>> **df['department_total_single']** = df.groupby('Department')['Single'].transform('count')
熊猫transform('count')
(作者图片)
如果您想了解有关 merge()和 transform()的更多信息,请查看:
结论
在本文中,我们探索了熊猫counts()
的不同用例。它非常方便,是探索性数据分析和数据预处理中最受欢迎的方法之一。
我希望这篇文章能帮助你节省学习熊猫的时间。我建议你查看一下关于counts()
API 的文档,并了解你可以做的其他事情。
感谢阅读。请查看笔记本获取源代码,如果您对机器学习的实用方面感兴趣,请继续关注。
你可能会对我的其他一些熊猫文章感兴趣:
- 9 个熊猫 value_counts()提高数据分析能力的窍门
- 所有熊猫 json_normalize()你应该知道的扁平化 JSON
- 使用熊猫方法链接提高代码可读性
- 如何对熊猫数据帧进行自定义排序
- 数据分析你应该知道的所有熊猫移位()
- 何时使用 Pandas transform()函数
- 你应该知道的熊猫串联()招数
- Pandas 中 apply()和 transform()的区别
- 所有熊猫合并()你应该知道
- 在 Pandas 数据帧中处理日期时间
- 熊猫阅读 _csv()你应该知道的招数
- 用 Pandas read_csv()解析日期列应该知道的 4 个技巧
更多教程可以在 Github 上找到
获得我的 Google Tensorflow 开发者证书
我得到一个的原因,以及帮助我的资源
最近拿到了 Tensorflow 开发者证书,被 Tensorflow 开发者网录取了!这是一个小小的挑战——在 5 个小时的考试中(我已经很久没有这样做了)解决 5 个跨回归、计算机视觉、NLP 和时间序列预测的问题,所有这些都是通过使用 TF 2.0 的深度神经网络完成的。
虽然拿到证书很好,但最有价值的是学习。在这篇文章中,我分享了我旅途中的一些心得和建议。
作者创作的图像
为什么我会考虑买一个?
多年来,我使用 Tensorflow (TF)或 Pytorch 在深度神经网络方面积累了许多不同的项目经验(包括工作和个人经验)。我还非常幸运地成为 ThoughtWorks Australia 活跃的 ML 社区的一员,在这个主题上一起讨论和学习,并得到了 mat kelcey 的指导——他是在 Google Brain 工作时 TF 的早期采用者之一,也是一个分享知识的了不起的人。
尽管如此,我仍然觉得我的知识相当零散。还有一点冒名顶替综合症。我不知道我是否只是触及了表面,可能遗漏了一些关于 TF 框架提供了什么(很有可能)或者它还能提供什么的重要知识。
去考 TF 证书是一个很好的方法来获得关于这个主题的全面的知识覆盖。
一个很好的起点是 TF 的候选人手册。读完技能清单部分后,我被说服了。显然有很多东西要学。它涵盖了从使用传统表格数据、计算机视觉、NLP、数据增强到预测模型的所有主题,所有这些都与深度学习和 TF 有关。和一些数据争论技巧。
最后,自从最近在 NAB 企业数据科学团队担任新角色以来,我获得了一些额外的动力。我们确实有一些令人兴奋的项目,也有许多具有强大研究或行业背景的人。虽然我的角色是技术和人员领导的结合,但我渴望不断更新自己的技术能力,为团队提供有用的技术输入,并帮助指导团队了解 AI/ML 技术雷达的最新动态。
我的学习之路
我不需要在这里重新发明轮子,只需要遵循社区和官方指南的建议。最重要的学习资源是:
- Andrei Neagoie 和 Daniel Bourke 在周日举办的 TF 课程。附带的资源非常好——强烈推荐练习 Github repo 中的所有章节。还有很多关于 TF 和深度学习的技巧。
- Coursera 上的官方推荐课程。虽然这是相当基础的——这是一个 4 周的课程,但是一旦你或多或少精通了 TF——它可以在一天内完成(我确实在一天内完成了)。很高兴有一个好的检查点(和另一个证书收集的乐趣:-)
- 有一个好的 TF 代码记忆肌肉对通过考试真的很有用(这是一个 5 小时的考试)——最好的方法是用你的玩具考试从头开始写东西。只是一遍又一遍的模型定义、model.compile()和 model . fit()😃。我做了一些有趣的工作,建立 MLs 来识别我家里的人(你可以在本地做,所以隐私风险很低)。
- 我意识到我通过练习自己的问题学到了最多的东西。当我没有遵循教科书时,我犯了很多错误——通过这些错误,我更加意识到构建 DNNs 时所有事情的细微差别。例如,对输入要素进行重缩放和不进行重缩放的区别有多大?
一些实用的考试技巧
最后,一些额外的提示:
- 第一个是从所有参加过考试的人那里寻找窍门!例如,这里的就是一个有用的例子。
- 准备好一些助手函数是很好的,这些函数可以帮助做一些事情,例如检查点最好的训练模型、提前停止、tensorboard 回调等等。
- 考试将在 PyCharm 中进行(我是一个 VS 代码人员,但是找到转换并不太难。同样好的老 JetBrains IDE)。确保你在考试前在这种环境下练习得足够好。
- 我发现在开发环境中拥有一个包含所有必需的包和依赖项的本地设置非常有用。不要只是在 Google Colab 中练习东西,重要的是要确保东西可以在你的机器上运行,获得相同的一致结果和性能(比如训练速度——以验证这一切都调整正确)。更具体地说,我使用了:
- Pyenv for Python runtime(将使用 3 . 8 . 0)/poems for dependency management(但考试还要求将特定版本的依赖项直接安装到他们的 PyCharm 插件中,因此请确保您也尝试了这一点)。
- 当您在本地开发时,确保您可以在本地环境中启动 jupyter lab(具有相同的依赖集)也很方便。如果你想快速地/交互地尝试一些事情,并受益于一个活动的有状态会话,这是一个不错的选择。
- 5 小时考试很棘手!确保你已经选择了简单的午餐或晚餐:-)
从这里去哪里?
显然 Mat 说的是 Jax!对我来说,经历这些提醒我把学习当成马拉松,而不是短跑。一个好的学习经历是一个很大的正面强化,可以帮助我走下去。
获取 NYT 文章数据并将其保存到 SQL 数据库中
从纽约时报 API 获取文章数据并保存到 SQLite 数据库
斯蒂芬·瓦伦丁在 Unsplash 上拍摄的照片
介绍
本周,我决定学习更多关于文字处理的知识,从基于报纸数据构建一些文字云开始。同时,我想提高我收集数据并将其保存到数据库中的知识。
我在这里的主要目标是获取并保存一些我可以使用的有趣数据。我认为 2020 年的报纸文章会很有趣,可以看到每个月的新闻主题。
最初,我从不同的报纸档案中寻找文章。有许多很棒的工具,但我能找到的提供 API 的工具并不多。我发现《纽约时报》确实有一个 API,提供与他们的文章相关的数据。
这是一篇记录我的学习历程的文章,从 API 获取数据并保存到 SQLite DB。
关于 API
这些 API 可在 https://developer.nytimes.com/apis获得
我发现 API 的文档(包括https://developer.nytimes.com/faq的常见问题解答)对入门非常有用。
《纽约时报》提供了许多不同的 API,包括 Books API,其中包含有关畅销书列表和书评的信息,Film API,用于电影评论,以及 Community API,其中包含有关用户生成的内容(如评论)的信息。
在本文中,我使用的是归档 API(https://developer . nytimes . com/docs/Archive-product/1/overview)。如果您将年份和月份传递给 API,它将返回该月的文章数据。文章数据告诉我们很多事情,包括 NYT 网站上的全文,发表时间,标题和导语。
获取访问权限
使用 API 的第一步是建立一个帐户并获得访问权限(https://developer.nytimes.com/get-started)
要求
我使用了请求、 sqlite3 和时间。
步伐
我在这里经历三个步骤。我:
- 连接到 API 以浏览可用的数据,并查看我想要保存的数据。
- 基于我要保存的数据建立一个数据库表。
- 获取一年中每个月的数据并保存到数据库中。
探索数据
在这里,我导入我将使用的内容。请求将调用 API, sqlite3 用于与数据库和时间交互,因此脚本可以在调用之间休眠。医生建议两次通话间隔 6 秒,以避免达到极限。
import requests
import sqlite3
import time
在这一行中,我发出一个初始请求来查看数据是什么样子的。您的纽约时报 API 帐户中生成的 API 密钥将放在[您的 API 密钥]占位符中。使用这个 API 进行身份验证非常简单
data_2020_01 = requests.get("[https://api.nytimes.com/svc/archive/v1/2020/1.json?api-key=](https://api.nytimes.com/svc/archive/v1/2020/1.json?api-key=rukHkq9CptpyckwG9qfMpHX7C06rn9zK)[YOUR API KEY]")
归档 API 将数据作为 JSON 响应返回。该信息在 API 网站上给出,但是也可以检查请求响应头,以查看返回的内容类型。是“应用/json”:
知道了这一点,我可以使用 Requests 自己的 JSON 解码器将响应转换成 python 字典:
data_2020_01_json = data_2020_01.json()
打印数据显示这是一本字典。文章本身包含在字典的列表中:
data_2020_01_articles = data_2020_01_json['response']['docs']
该列表的长度为 4480,这意味着它包含以下数量的文章:
为了探究一篇文章,我在列表中取一个数字,直到 4480,来查看它。例如,在位置 10 的文章:
data_2020_01_articles[10]
关于这篇文章有很多信息——比如它的 web_url、lead_paragraph、它在哪个部分(section_name)以及它发表的时间(pub_date)
我想先保存标题、引导段落和出版日期。我认为材料的类型也可能是有趣的,还有字数、主要标题、印刷页、新闻桌和版块名称。
数据库
数据库有许多选项。这里我使用 SQL lite。这样做的一个主要优点是我可以很容易地用 python 创建它并与之交互。我在https://docs.python.org/3/library/sqlite3.html使用文档工作
构建数据库
我想在我们的数据库中保存作为一行返回的每篇文章,并为上面提到的每个字段(即,主标题,打印页面,新闻桌面等)列。,)
我正在创建的特定列:
_id (这将是文章的唯一 id。API 为每篇文章返回一个), web_url , main_headline , pub_date , news_desk , section_name , type_of_material , word_count 。
创建数据库和表
使用 python 直接连接和创建数据库:
connection = sqlite3.connect('nytimes_articles.db')
创建一个游标对象,以便我可以开始执行查询:
cur = connection.cursor()
使用游标的 execute 方法创建表:
cur.execute('''CREATE TABLE articles(_id TEXT, lead_pargraph TEXT, web_url TEXT, main_headline TEXT, pub_date TEXT, news_desk TEXT, section_name TEXT, type_of_material TEXT, word_count INT)''')
保存数据
所以,我想得到一年中每个月的数据。早些时候,我获取了一个月的数据,以探索数据的结构,但现在我需要编写一个函数来获取每个月的数据,然后将每个月的数据保存到刚刚创建的数据库中。
在这里,我编写了一个函数来为我想要获取数据的每个月生成一个 URL。
def generate_urls():
month_range = range(1,13)
api_key = "[YOUR API KEY]"
urls = []
for month in month_range:
url = (f"[https://api.nytimes.com/svc/archive/v1/2020/{month}.json?api-key={api_key](https://api.nytimes.com/svc/archive/v1/2020/{month}.json?api-key={api_key)}")
urls.append(url)
return urls
我将遍历我要访问的 url 列表(由上述函数返回,访问每个 URL,并使用每个月返回的数据,遍历文章列表。然后,我将数据库中每一行的值添加为一个元组,然后将每个元组存储在一个列表中。每个月结束后,我都会把这些写在数据库里。
重要的是,数据以与数据库中的列相同的顺序保存在元组中,即:_id、lead_paragraph、web_url、main_headline、pub_date、news_desk、section_name、type_of_material、word_count
month_urls = generate_urls()for month in month_urls:
data = requests.get(month)
data_json = data.json()
data_articles = data_json['response']['docs']
values_for_db = []for article in data_articles:
row = (article['_id'], article['lead_paragraph'], article['web_url'], article['headline']['main'], article['pub_date'], article['news_desk'], article['section_name'], article['type_of_material'], article['word_count'])
values_for_db.append(row)
cur.executemany('INSERT INTO articles VALUES (?,?,?,?,?,?,?,?,?)', values_for_db)
time.sleep(6)
connection.commit()connection.close()
数据
我使用了 SQLite 的 DB 浏览器来查看文章数据。在这里,我可以很容易地看到保存了什么。55,493 篇文章的数据:
作者图片
我发现使用这个 API 非常简单,它有很多关于纽约时报上文章的有趣信息。虽然 API 没有提供整篇文章的文本,但是 lead_paragraph 字段应该是每篇文章中提到的内容的一个很好的指示器。今年,我计划在文字云可视化之前对文本进行命名实体识别。这也可能是用于情感分析的有趣数据。
介绍图片是斯蒂芬·瓦伦丁在 Unsplash 上的一张照片。其他所有图片均由作者拍摄。本文中使用的代码可以在这里找到:
https://github.com/LiamConnors/Medium-articles
作为一名有抱负的数据科学家受到关注
在竞争激烈的就业市场脱颖而出的秘诀
这篇文章交叉发布在我的网站 https://www.dscrashcourse.com/上,与我们为有抱负的数据科学家策划的其他指南放在一起。
对于任何喜欢与数字和分析打交道的人来说,数据科学家是一个受欢迎的职业选择。曾被《哈佛商业评论》称为“21 世纪最性感的工作”,这一行业的受欢迎程度导致其求职者和新兵训练营饱和。
在如此多的兴趣和竞争下,有抱负的数据科学家越来越难在就业市场上脱颖而出并受到关注。
那么,一个有抱负的数据科学家如何才能脱颖而出呢?
首先,理解数据科学角色的现实很重要,尤其是它对初级和入门级职位的要求。
数据科学职称已经成为所有从事数据工作的人的总称。这些角色中有很多本质上都是分析型的——提取数据、分析数据和分享结果。其他人将更加关注数据质量和可访问性——构建 ETL 管道、监控数据完整性和服务水平协议。很少有初级职位会处理模型构建和机器学习。
这种现实会成为从事数据科学职业的障碍吗?
如果没有,那就太好了。确保你了解你申请的是什么类型的职位,以及哪些技能与这个职位相关。让你的简历符合这些技能。例如,业务分析师可能有从数据中分析和产生洞察力的经验。尽管这不是一次“数据科学经历”,但它仍然与许多数据科学职位密切相关。
这里有一些其他的方法可以让你的个人资料脱颖而出。
有形的项目来展示你可以应用你的知识
我们很幸运能够使用各种工具来简化模型构建和数学计算。有了这个工具,我们可以在评估候选人的理论背景时更加宽松,尤其是那些更初级的候选人。
有抱负的候选人应该把重点放在应用他们的知识来构建在现实世界中有用的数据产品的能力上。
这里有一个好的副业项目的小清单:
我在这个项目中使用了正确的框架吗?它们与当今的行业相关吗?它们对这种特殊的应用有意义吗?
以一个 Python 项目为例:您有诸如 TensorFlow 和 Scikit-learn 之类的去因子库来满足您的大多数建模需求。这些图书馆有充分的理由变得受欢迎。如果你偏离了这些标准,你应该问问自己你的选择是否有意义。这很重要,这样 1)你就不会在不需要的时候重复发明轮子,2)你所展示的技能是相关的。
我是否展示了良好的软件工程实践?我的代码是可测试的、可维护的和可解释的吗?我的作品有多大的可复制性?
始终确保您在编写代码时考虑到了受众——其他人是否容易贡献或审阅您的代码?几周后理解你的代码容易吗?不管他们使用什么机器,安装说明都应该清晰明了。
我表现出很强的解决问题和沟通技巧了吗?我的工作有记录吗?我做这些决定的原因清楚吗?
解决问题和沟通是成为一名成功的数据科学家的两项关键技能。能够交流你的想法(尤其是为什么组件)是一个好科学家和像 AutoML 这样的工具之间的区别因素。
建立强大的在线形象
一旦你有一套要展示的作品,确保它很容易被拿到。强烈建议您通过 GitHub 这样的平台公开共享您的代码。这将使未来的雇主更容易找到并浏览你的工作。
让大家知道你的在线状态。维护一个技术博客,在那里你可以分享想法和知识,这会补充你的简历,让你的工作更容易被发现。考虑建立一个个人网站,进一步展示你的热情和技能。
积极参与社区活动。尽你所能为开源项目做贡献,无论是公开你经历过的问题还是对他们的代码库做一些小的改进。
加入一两个社区
有大量面向数据科学从业者的在线社区。这里有一个数据科学和机器学习松散社区的列表,你可以加入。
也要留意当地的社区,无论是在线的还是面对面的(meetup.com 是一个很好的起点!).这些社区通常会在你附近与当地的专业人士和雇主一起举办活动。这是建立关系网和找工作的绝佳机会。
继续学习并构建您的工具包
数据科学家身兼多职。要想在这个职位上取得成功,你需要掌握多种多样的技能。这个行业变化也非常快,需要大量的学习才能跟上这些变化。
永远不要停止学习,永远不要停止成长。
通过培养学习的倾向来掌握这些变化。承认自己的优势和劣势,制定可行的计划来不断提高自己。
感谢您的阅读!
如果你喜欢这篇文章,可以看看我关于数据科学、数学和编程的其他文章。请通过媒体关注我的最新消息。😃
作为一个业余爱好项目,我还在www.dscrashcourse.com建立了一套全面的免费数据科学课程和练习题。
如果你想支持我的写作,下次你报名参加 Coursera 课程时,可以考虑使用我的会员链接。完全公开—我从每一次注册中获得佣金,但不会对您产生额外费用。
再次感谢您的阅读!📕
AI 为什么这么哑?
为什么自动化知识获取提供了前进的道路。
集体推理主题图(图片由作者提供)
“为什么 AI 这么哑?”是 IEEE Spectrum 十月号封面故事的标题。在一系列文章中,对人工智能的全面分析表明,我们正处于人工智能应用和人工智能研究前进道路的重要转折点。本文的目的是探讨这个问题提出的结论,并提出一个前进的方向。我们正在走向一个新的人工智能冬天,还是有一条承诺持续增长和价值的前进道路?
我度过了第一个人工智能冬天。
作为第一次人工智能 IPO(INAI——intelli corp)的领导者和 1986 年 AAAI 的联合主席,我经历了人工智能浪潮取得巨大成功的喜悦。那些在漫长寒冷的冬天后遗失的故事,包含了前进道路的线索。几乎每一位领先公司的首席执行官都关注并在构建专家系统和其他人工智能应用程序上下了 R&D 赌注。一些非常成功的原型导致了广泛的新应用类别,例如需求预测/定价、配置管理、诊断方法和欺诈检测等等。承诺是巨大的,但成本高于收益。结果,成功的应用程序类别演变成了传统的软件应用程序。人工智能技术提供的生产力是有价值的,但广泛采用也有障碍。
可扩展性的最大障碍之一是知识获取是一个劳动密集型的过程。然而,困难并没有阻止大家。80 年代中期我在道格·勒纳特的办公室。他的既定任务是:建立一个庞大、全面的知识库。近 40 年后,该项目继续进行,并找到了效用。也就是说,手工制作知识库限制了可伸缩性。
在封面故事概述中,有两条引言阐明了当前的事态:
“无论是道格拉斯·莱纳特(Douglas Lenat)的 Cyc 等象征性人工智能项目,还是杰弗里·辛顿(Geoffrey Hinton)、扬·勒昆(Yann Lecun)和约舒阿·本吉奥(Yoshua Bengio)开创的深度学习进展,都还没有产生人类水平的智能。”
“就过去 20 年我们在这项工作上取得的进展而言:我认为我们今天的智力水平还远远没有接近一个 2 岁孩子的水平。但也许我们有相当于低等动物感知的算法。”
第一个评论指出了当前事态带来的限制:手工制作的人工智能系统无法扩展。第二种观点认为,基于从数据中学习数学模式的方法(尽管确实强大有力)不足以捕捉人类智能的本质。最后,朱迪亚·珀尔进一步阐述了这一观点:
“你比你的数据聪明。数据不懂因果;人类会……最可靠的知识是你自己构建的。”
珀尔的评论暗示了一条前进的道路,我们将在后面的段落中继续探讨。
虽然对人工智能局限性的认识越来越突出,但该领域的研究人员也认识到了这些局限性。几年前,我参加了麻省理工学院的一个会议,该会议标志着麻省理工学院智能探索的启动,这是一个促进人类和机器智能研究的广泛倡议。斯坦福和伯克利启动了类似的项目,以深化理解智能(人类和人工智能)本质的跨学科研究。此外,美国国家科学基金会(NSF)和美国国防部高级研究计划局(DARPA)的各种研究计划,都试图为整合人类认知和人工智能模型建立更好的基础。认识到限制和需要,人工智能的实际应用的前进道路是什么?
正如 MIT-IQ 所表明的那样,广义人工智能正在步入基础研究的漫长道路。前进的最佳途径是什么?我们能利用人工智能和集体智慧的发展吗?我相信答案是肯定的。尽管如此,它仍然需要通过找到人类协作学习和深度学习的共同点,深入地重新构建我们如何处理人工智能应用。一种新颖方法的精髓始于 90 年代末。
随着人工智能冬天的到来,我离开人工智能 5 年,并在 1992 年成为苹果公司的 CEO。Connect 成为电子商务平台,于 90 年代末上市。在我接近 Connect 的时候,一个朋友带着他最初称之为“思考游戏”的过程来找我。⁴:这是一个协作学习和融合的人工过程,最初是用索引卡实现的。这一过程和由此产生的模型是受研究科学发现过程的启发。⁵在 90 年代末,我们创建了一个基于网络的协作学习平台,我们将其注册为“适应性对话”宝洁公司和 NBC 是这项技术的早期采用者。我们能够证明,人们可以通过了解消费者喜欢某种产品或观众喜欢(或不喜欢)电视节目的原因来做出预测。
《适应性对话》的工作与《群体的智慧》和《引爆点》的出版同时进行。第一本书指出了什么成为了集体智慧的科学,第二本书涵盖了突现模式如何发展成为更重要的市场现象。集体智慧是关于我们如何一起变得更聪明。正如在《引爆点》中所讨论的,复杂适应系统模拟了导致巨大影响的早期趋势。
结合集体智能和复杂适应系统:人工智能的新框架
人工智能新框架的核心技术是从人类集合中获取知识,并使用我们称为集体推理的过程将这些知识存储在一个活的计算模型中。具体来说,集体推理过程构建了包含参与者集体智慧的概率图形网络。因此,人工智能是一种超级智能的会议主持人,它通过一个平衡发现与优化学习一致性的过程来指导团队,最终产生一种可能性和一种解释。 在嵌入了启发式模型(例如,决策规则或记分卡)的模板的驱动下,系统返回结果的概率估计以及对集体推理的完整解释。
通过与领先的消费品公司(P&G、乐高、NBC、Intuit)合作 12 年,我们了解到从自下而上的消费者对话中学习偏好(例如,你想体验什么?)是可靠的预测。核心自适应学习算法可以产生语句的相关排序。排名准确性通过了 CPG 和媒体领域全球领先的市场情报专业人士的审查。我们还了解到,它引起了高层管理人员的注意,导致技术推动了 Reichheld 的 NPS 书籍《一个问题》中五个案例研究中的两个。它创造了创新的变革案例,乐高就是一个最好的例子。时任乐高 Direct 首席执行官的他利用这项技术与乐高社区共同创新了《星球大战帝国歼星舰》,他从一个简单的问题开始:“当你把你的乐高倒在地板上时,你想体验什么?”
适应性学习奏效了。它将定性对话转化为定量预测结果,但我们只是触及了表面。我们不理解这次演出的根本原因。除了通过服务(例如,没有可靠的 NLP 技术),我们没有任何方法来处理结果,结果是一个报告。我们需要强大的 NLP 技术来释放整合人类和人工智能的新框架的力量。
整合人类和人工智能
集成人类和人工智能的框架在⁶的其他地方有更详细的描述,它由三个可互操作的组件组成:1 .使用隐马尔可夫建模技术基于对等体的学习对齐来学习系统的所有原因的相关性概率的组件,2。NLP 组件,创建推理空间的几何模型;以及 3 .集体推理过程的概率图形模型。⁷
上述框架的技术开发始于 2014 年。目标是确定是否可以获得数据贫乏的资产,如早期创业公司,并预测该创业公司获得后续投资的可能性。生存能力是成功投资回报的最重要的相关因素。预测筹资潜力的基于框架的模型来自天使资本协会赞助的研究。⁸这一预测的“数据”来自一个认知多样化的合作者群体。有些成员有投资经验,有些有行业经验,有些有创业经验,有些有终端用户经验。合作团队是根据每个初创企业所需的领域专业知识挑选出来的,人数从 12 到 30 人不等。四年来分析的数据集大约有 150 家公司。结果是非常积极的,得分超过 73%的 80%在风险投资市场上获得了市场关注。得分最高的公司目前的估值是其价值的 20 倍以上,并获得了两项 CES 大奖。通过这个过程产生的所有模型都被存储为贝叶斯信任网络。知识模型是集体推理过程的持久计算模型。一旦创建,模型就像迷你专家系统一样工作。例如,投资用例的模型是可组合的,有助于学习如何在早期投资中变得更好。⁹
从这些年的经验中,我们了解到我们有一个更通用的知识获取引擎,适用于与决策相关的市场情报或知识发现过程的各个领域。例如,在单盲集体推理过程中学习基于证据的比对,并接受同行评审,本质上是一个知识发现的过程,它与我们如何建立来自科学研究的模型高度一致。
出于这个原因,下一代人工智能技术的一条建议路径是使用协作推理来跨越学科,类似于麻省理工学院 IQ 的跨学科努力。集体推理适用于评估替代模型和技术。在商业层面,集体推理适用于评估技术在创新计划和投资中的影响潜力,这些计划和投资推动了企业转型计划。
集体推理技术的数学和科学基础与深度学习非常相似。深度学习之所以如此有效,是因为它植根于物理学中的合作现象。具体来说,深度学习的核心是一个来自磁行为物理的模型。例如,通过称为重正化群的数学公式,电子自旋标度与宏观磁性的微观排列。深度学习通过实施重正化组过程来衡量数据如何在从微观相互作用(例如,像素到像素)到宏观属性(“它是一只狗”)的模式中对齐。
我们开发的集体推理系统使用类似的数学公式,但将其应用于人类如何整合他们的知识来制定决策或预测。通过利用协作过程,我们学会了协调。具体来说,对齐学习算法智能地对寻求发现对齐区域的其他参与者提交的原因的候选列表进行采样。基于框架的知识获取模板指导系统。
可以将框架简单地看作是关注决策或预测的特定方面的一种方式。例如,早期投资的框架可能简单到“你认为市场机会如何?”以及“你觉得这个团队怎么样?”。集体推理系统将学习对市场机会和团队的集体推理观点。
集体推理算法平衡了发现(允许参与者开放思考,并在看到他人原因的基础上扩展自己的推理)和优化(学习对齐)。⁷类似地,一个团队会议的主持人会从发现走向融合(把所有的想法都提出来,然后进行优先排序)。学习算法具有学习何时将注意力从发现转移到优先化的方法。
自动化集体推理有着巨大的潜力。该系统学习支持任何规模的群体的决策或预测的理由的排序偏好。因此,从组织决策到预测市场智能模型,集体推理具有广泛的适用性。
第一波人工智能专注于模仿人类智能的手工制作系统。我们把人类的思维放在基座上,检查它,并使用逻辑和试探法建立知识和推理模型,试图反映和模拟人类的专业知识。人工智能的第二次浪潮将统计相关性放在了基座上,并在自动模式识别和分类方面取得了巨大成功。
人工智能的第三次浪潮将综合智能置于一个基座上。麻省理工学院对集体智慧的定义说得很清楚:“人和计算机如何连接起来,从而集体地比任何人、团体或计算机更聪明地行动。集体推理提供了一条有望实现这一目标的前进道路。集体推理采用数学上合理的方法来学习深度学习中缩放排列的含义,以可缩放地学习人类的排列,创建集体人类知识的计算模型。
关于决策或结果的共享推理的学习对齐创建了一个知识获取框架,该框架密切反映了科学发现的过程。此外,它基于物理学的一个基本原理,即合作现象,这为未来的研究和开发提供了坚实的基础。
如果你想成为探索集体推理的新倡议的一部分,请给我发电子邮件至 tom@crowdsmart.ai 。对于商业用途,该技术被授权为来自 CrowdSmart.ai 的基于云的服务。如果你的兴趣与研究相关,请在电子邮件中明确说明。
- 伊莱扎·斯特里克兰“人工智能动荡的过去和不确定的未来”IEEE Spectrum 年 10 月
- Yoshua Bengio,米兰-魁北克人工智能研究所创始人兼科学主任
- 朱迪亚珍珠采访为什么基础书籍 2018 年的书
- 布拉德·弗格森
- 托马斯·库恩《科学革命的结构》芝加哥大学出版社 1970 年
- 托马斯·克勒用集体推理改变协作决策
- 专利申请中
- 威尔特班克,罗伯特,和伯克,沃伦,回报天使投资者团体(2007 年 11 月 1 日)。可在 https://ssrn.com/abstract=1028592或 http://dx.doi.org/10.2139/ssrn.1028592或买到
- 托马斯·克勒运用集体推理进行投资
- 亨利·林、马克斯·泰格马克、大卫·罗尔尼克“为什么深度廉价学习效果如此之好?” arXiv:1608.08225
- 基于框架的表征在推理中的作用《CACM》第 28 卷第 9 期
针对数据管道的事件检测和警报
入门指南
如何设置端到端检测和警报,以识别和防止数据中的无声错误。
数据管道断了?仪表盘不靠谱?关键报告中有太多的空值?
要获得可靠准确的数据,测试和断路器只能帮你到此为止。在我们最新的系列中,我们重点介绍了数据团队如何为他们的生产数据管道建立 端到端事件管理工作流 ,包括事件检测、响应、根本原因分析&解决方案(RCA)和无可指责的事后分析。
在这篇客座博文中,蒙特卡洛的 斯科特·奥利里 带我们了解如何开始事件检测和警报,您防御 数据宕机的第一道防线 。
随着公司越来越依赖数据来推动决策,对数据准确性和可靠性的要求也越来越高。随着越来越多的数据进入您的数据生态系统,出错的可能性只会增加,每年会给组织造成超过1200 万美元的损失,更不用说宝贵的时间和利益相关方的信任了。
几十年来,软件工程和 DevOps 团队一直依靠一个 多步骤过程 来识别、分类、解决和防止软件和操作问题影响他们的应用程序。随着数据操作的成熟,是时候我们以同样的勤奋对待 数据停机 了,换句话说,就是数据丢失、不准确或其他错误的时间段,尤其是在构建更可靠、更有弹性的数据系统时。
**第一步?**事件检测和警报,这是您抵御数据管道中断和管理人员不可避免的清晨 pings 的第一道防线(“为什么数据是错的?”)和利益相关者(“这个仪表板怎么了?”)当管道破裂时。
有了正确的流程、技术和文化,您的数据团队就可以建立一个协作、高效的工作流,用于识别、补救和防止问题消耗太多宝贵的时间和精力,并侵蚀组织其他部门对数据的信任。
第一步。撰写您的数据事件操作手册
在您能够检测到事件之前,您需要建立流程并开发良好的(足够的)文档来传达职责、角色,以及在您确实收到可怕的松弛消息或寻呼责任通知时的清晰前进路径。引用本杰明·富兰克林的一句话,“未能计划就是计划失败”,当涉及到管理数据管道中的 未知的未知 时,这句话当然适用。
无论您为数据管道设置了多少测试,事故都是必然会发生的,当问题出现时,有一个适当的计划将有助于您。就像 站点可靠性工程师(SREs) 在应用程序中断时使用运行手册一样,现代数据工程师也应该为管道中断制定计划。
至少,我建议您使用以下操作手册地址:
- 您的组织认为什么是数据事件? 这可以让你的团队确定这是否是你应该担心的事情。也许数据事件可以通过重新启动 Airflow DAG 来解决,或者也许您需要提交一个票证,以便与数据团队的其他成员一起更深入地研究这个问题。无论哪种方式,确定什么是真正的事件,什么可以不优先考虑或忽略有助于减少噪音和保持您的团队专注。
- 发生数据事件时,谁会收到警报?这因组织而异,所以你需要找出最适合你的团队的方式。一些团队指派一个人负责所有数据事件,作为第一道防线,而其他团队则有一个数据工程团队负责数据的新鲜度和数量,还有一个分析团队负责验证数据。为特定类型的事件甚至某个事件的特定方面分配所有权,将在今后带来回报,提高您的团队合作和识别问题根源的能力。最佳实践是通过 PagerDuty、Slack、Opsgenie 和其他流行渠道将警报集成到数据工程工作流中,因为这可以确保所有数据利益相关方和最终用户在出现问题时收到警报。
- 您将如何向利益相关者和最终用户传达该事件? 一些组织对此采取了直接的方法,向团队特定的渠道发送事件通知(如影响重要营销仪表板的事件的 Slack 渠道)。其他组织在数据工程团队中保持第一道防线,并且只有当问题很明显是“真实的”并且确实影响到下游数据消费者时才提醒风险承担者。无论采用哪种方法,关键是您的第一道防线是技术性的,足以在您的数据环境背景下理解事件,并且足够了解业务背景和问题的影响。选中这两个框非常有帮助,因为它减少了来回沟通问题的技术范围和业务影响所需的时间。
第二步。检测数据事件
图片由蒙特卡洛提供。
当数据管道中断时,第一步是事件检测。
不言而喻,您应该在数据进入生产之前测试您的数据并捕捉已知的未知,换句话说,您可以在特定阈值范围内预测的问题。
然而,测试和其他断路器方法在检测生产中无法预测或解释的事件时会让数据团队失败— 未知的未知 。因此,测试数据并不能提供真正的端到端可观察性,而这对于数据驱动的业务来说是必要的。随着数据管道变得越来越复杂,对于试运行和生产,未知的未知数只会增加。
这就是为什么数据需要测试和 可观测性 来确保端到端的可靠性。现代数据团队必须将数据视为一个动态的、不断变化的实体,不仅要应用于严格的测试,还要应用于持续的数据可观察性。借助数据可观察性,可以通过自动 数据监控和警报 来检测问题,并基于 ML 生成的或自定义设置的阈值来触发问题。
数据可观察性的一个重要方面是异常检测,它允许组织确定数据健康的支柱(即,容量、新鲜度、模式和分布)何时不符合生产中的预期。与仅在数据平台的一两层中实施相比,端到端实施异常检测(例如跨您的仓库、湖泊、ETL 和 BI 工具)对企业来说是有价值的。这样做可以让您的团队全面了解组织的数据健康状况,因此如果出现问题,您的团队会第一个知道并解决。
第三步。为关键数据事件设置警报工作流
如果一条管道破裂,而周围没有人听到,那它真的破裂了吗?
2021 年,当数据驱动着您公司做出的几乎每一个关键决策,并影响到整个组织的团队时,答案是响亮的“是”。
玩笑归玩笑,当出现问题时,你的团队应该得到提醒,而不是花费几个小时甚至几天来手动调查问题。在您设置警报之前,您的团队应该建立考虑事件的基本规则,谁应该接收特定类型的警报,以及接收警报的最佳位置。这些指导方针和流程应该记录在您团队的操作手册中。
写完操作手册后,团队应该考虑实施支持机器学习的解决方案(如数据可观察性平台),以根据历史数据自动生成警报,只需最少的提升即可启动并运行。警报可以直接发送到 Slack、email、PagerDuty、Opsgenie、Mattermost、webhooks 或您的团队用于管理沟通的任何其他渠道。
图片由蒙特卡洛提供。
许多团队选择为重要的表(如财务报告、产品统计、营销支出和运营指标)设置页面责任或 Opsgenie 通知,并为不太重要的表设置 Slack 或电子邮件通知。这样的通知可以让你的团队减少嘈杂的警报。
图片由蒙特卡洛提供。
接下来,选择要发送到此通道的事件。默认情况下,您可以路由所有事件,也可以选择自定义选项,例如,只路由特定表或报告的自定义规则违规。
图片由蒙特卡洛提供。
如果您选择违规,团队可以将所有或部分违规发送至特定渠道:
图片由蒙特卡洛提供。
最后,您可以选择一个客户过滤器来缩小要通知的数据集或表的范围:
图片由蒙特卡洛提供。
虽然数据可观察性有助于基于数据中的历史模式开箱即用的自动端到端异常检测,但一些团队选择基于特定业务需求设置自定义警报。随着贵公司数据战略的成熟,我建议两者都加以利用。
建立数据信任文化
建立一流的事件管理实践不仅需要正确的工具,还需要整体的方法来减少噪音、区分关键资产的优先级、解决隐性错误,最重要的是,促进整个公司内更轻松的协作。
破裂的数据管道可能不会发出声音,但它们的影响可能强大到足以砍倒比喻意义上的树。
在我们的事件管理系列的第二部分,我们将分享我们在响应数据事件方面的最佳实践和经验教训。
有兴趣了解有关使用蒙特卡洛为您的数据团队建立可靠的事故管理流程的更多信息吗?伸出手去 斯科特 和 我们团队的其他人 !
开始学习数据科学意味着首先清理您的数据
入门
用于减少数据混乱的探索性数据分析(EDA)工作流
在阿姆主演的电影 8 Mile 中,歌曲 Lose Yourself 抓住了电影的整体构思。你知道我指的是哪一个。像这样开始的那个…
“他手心出汗,膝盖发软,手臂沉重。
他的毛衣上已经有呕吐物了,妈妈做的意大利面。
他很紧张,但表面上看起来很平静,准备好了”
是的,这就是我在新工作中第一次坐在我的新房间时的感觉。铭牌上贴着令人垂涎的头衔“数据科学家”看起来很自信,但是感觉…嗯…紧张。
有点戏剧性?也许吧。
但是这种感觉和我的经理给我第一个项目任务时的感觉一点也不一样。
“嘿布兰登。欢迎来到公司。您现在会开发我们的企业微细分模型吗?有你加入,每个人都很兴奋。再见了。”
我从紧张到害怕。我的手心不只是出汗,而是湿透了。为什么我会如此紧张?嗯,这里只是几个原因。
第一,我生活在学术界回归模型的世界里。我以前从未用聚类分析对数据建模,聚类分析对于细分是必要的。是的,我知道…完全没有…说真的,我是怎么得到这份工作的?
第二,也是这里最重要的一点,我得到了一个相当于 SELECT * FROM TABLE_A,TABLE_B,TABLE_C 内部连接 blah,blah,blah 的数据集,它包含 300 多万行和 200 多列。
当然,用 200 个变量建立一个有意义的聚类分析?对吗?我会在后面尖叫。
顺便提一句,如果你一直在关注我,你可能也知道我实际上试图一次分析 20 或 30 个东西,但很快发现这很痛苦,而且完全没有意义。
无论如何,如果不是因为下面的 EDA 技术,我可能还在研究那个问题。这个特定用例的主要目标是减少数据中可用的维度数量。
因此,我们希望评估每一列对于像这样的数据科学问题可能具有的潜在信息价值。因为模型是为了模拟数据中的变化而构建的,所以我们的大部分数据减少和清理都围绕着确定变量是否具有良好的变化。
在本文中,我将带您了解一个典型的 EDA 过程,该过程提供了一些常用工具,用于使用 Python 和 Pandas 执行数据简化。最终,这些工作使我们能够在数据科学生命周期的后期为更复杂的数据建模准备数据。我们开始吧!
在这里,我们使用一个常见的表格样式的数据集,包括行和列,来应用一系列重要的任务,帮助我们更深入地理解数据中不同列的潜在价值。
步骤 0:加载数据
这看起来很简单,但是在进行数据分析时需要考虑的一件事是将所需的数据加载到内存中的重要性。因为我们使用的计算机容量有限,所以确保我们的系统大小适合数据分析非常重要。
如果处理的数据对于您的系统内存来说太大了,那么使用向下采样来抽取数据的随机样本或者利用本文这里中详细介绍的其他技术是很重要的。
import pandas as pd
import numpy as nppath = '/path/to/data/'
df = pd.read_csv(path+'data.csv')
下面是我们正在处理的数据的样子:
作者图片
步骤 1:信号
一旦数据在内存中,我们需要元数据信号,使我们能够快速识别变量的信息值。初始清单应该包括检查每一列的数据类型。
我喜欢构建一个包含所有元数据信号的数据框架,让我能够快速识别有意义的变量。
在下面的代码中,我们首先创建一个数据帧,其中每一行都是原始数据帧中的一列。然后,我们的代码继续向这些变量添加不同的元数据信号,例如空值的数量、空值的百分比以及使用 describe()方法的描述性统计数据。以下是我们纳入元数据数据帧的完整信号列表:
-变量名
-空值的数量
-空值百分比
-数据类型
-数数
-卑鄙
-标准偏差
-最小值
- 25%、50%和 75%四分位数
-最大值
-出现频率最高的变量的值
-该变量最频繁值出现的时间百分比
meta_df = df.isna().sum().reset_index()
meta_df['percent'] = meta_df[0]/len(df)
meta_df = pd.concat([meta_df, pd.DataFrame(df.dtypes, columns=['dtypes']).reset_index(drop=True)], axis=1)d = df.describe().T.reset_index()meta_df = meta_df.merge(d, on=['index'], how='left')vcs = [pd.DataFrame(df[x].value_counts(normalize=True)).T for x in
list(df.columns)]vcs= [pd.DataFrame((x.idxmax(axis=1), x.max(axis=1))).T.reset_index() for x in vcs if len(list(x.columns)) > 0]meta_df = meta_df.merge(pd.concat(vcs), on=['index'], how='left') meta_df.columns = ['index', '0_x', 'percent', 'dtypes', 'count', 'mean', 'std', 'min', '25%', '50%', '75%', 'max', 'max_value','max_percent']
一旦我们的元数据 dataframe 构建完成,我们就可以构建一个函数,其中包含一系列规则,用于确定任何变量是否可能是坏的。
第一个规则确保至少有一些可变性,因此我们寻找标准偏差等于 0 的任何列。
第二个规则确保数据的某种分布,因此我们比较四分位数以确保它们不都等于相同的值。
根据这个建议这里,下一个规则标记具有超过 10%空值的变量。类似地,我们也标记那些出现频率超过 80%的单值变量。
最后,如果没有最大值,我们也标记变量,这意味着变量没有值。显然,这些规则可以根据不同的值或信号来定制。
def bad_flag(row):
if row['std'] == 0:
return True
elif (row['25%'] == row['50%']) and (row['50%'] == row['75%']):
return True
elif row['percent'] > .10:
return True
elif row['max_percent'] > .80:
return True
elif pd.isnull(row['max_percent']):
return True
else:
return False
meta_df['bad_var'] = meta_df.apply(lambda r: bad_flag(r), axis=1)
现在我们已经有了自己的标志,下一步是从主数据帧中删除那些变量。为此,我们列出了“bad_var”值设置为 NOT True(!idspnonenote)的列名。=).接下来,我们用一个新的 dataframe 替换我们的 dataframe,该 data frame 此时只包含感兴趣的列。
keep = (meta_df['index'].loc[meta_df['bad_var'] != True]).tolist()df = df[keep]
我们表现如何?我们从 150 个变量开始,现在减少到 113 个,我们已经能够从数据框架中删除 37 列。
第二步:可视化
上面的步骤很快也很容易完成,因为我们依靠数字表示来帮助评估每个变量的可变性程度。对于一些变量,我们可能仍然不确定它们的信息价值。
例如,有些变量在 70%的行中只有一个值。如果只有两个选项,这可能没问题,但是如果有两个以上的选项,则剩余值的可变性可能不足以对模型有用。在这些情况下,使用数据的可视化表示可以帮助我们进一步决定保留什么,去掉什么。
第一步是查看我们的元数据数据帧,检查任何异常或可疑的东西。例如,我们的一个变量有超过 75%的行被标记为“未知”
作者图片
让我们看看这个变量的条形图:
作者图片
根据条形图,变量“Variable_2”有两个值,“未知”和“是”在这种情况下,不清楚“未知”值和“是”值之间的差异意味着什么(一些“未知”可能是“是”),因此我们可以决定消除这个变量。
我们对数据的直观检查揭示的其他观察结果包括“年龄”被默认值“-1”填充,并且相当多的变量具有“未知”的值。虽然对特征工程的正确处理超出了本文的范围,但是这些额外的观察表明需要对特征进行额外的工程处理,以便为模型产生更多有用的数据。
当执行 EDA 以进行数据简化时,查看相关矩阵也可能是有用的,因为一些变量可能高度相关,以至于表明它们本质上是相同的变量,因此可以从分析中移除一个或多个变量。换句话说,变量没有给模型增加任何独特的东西。
快速目视检查将生成热图。要做到这一点,你需要做的就是遵循代码这里。这是我们使用相同代码的热图:
作者图片
例如,在 Variable _ 30-Variable _ 50 范围内似乎有一大块变量具有非常高的相关性,保留这些变量可能没有用。
在下面的代码块中,我们更深入地研究了相关性矩阵,只提取了那些相关性高于. 90 的变量。
high_corrs = corr[corr.iloc[:,:] > .90]
meta_corr = high_corrs.isna().sum().reset_index()
potential_drops = meta_corr.loc[(meta_corr[0] < meta_corr[0].mode()[0])]
从这里开始,由数据科学家来评估这些变量中哪些应该删除,哪些应该保留。
第三步:降维
如果在执行上述步骤后,我们仍然发现自己有太多的变量,EDA 的最后一点是使用探索性因子分析或主成分分析,这对于减少变量的数量同时仍然保持其潜在的信息价值是有用的。这些分析类似于我们在步骤 2 中生成的关联热图,但更进一步,寻找相关变量组,而不是简单的双变量关联。
因子分析帮助我们识别变量是否有足够的方差,我们可以做两件事情中的一件;将它们组合成它们平均值的一个指数(探索性因子分析)或者只关注一个因子中最重要的变量而忽略其余的(主成分分析)。你可以利用因子分析的结果做更多的事情,但这是我在野外处理数据时最常做的两件事。
虽然这些技术通常被认为是“无监督的”,因为我们允许算法识别数据的自然分组,但现实是数据科学家必须在执行分析之前应用一些有意义的框架来分组数据。
我说的有意义的框架是什么意思?
例如,假设一组变量代表健康的不同方面,而其他变量是来自客户满意度调查的项目。寻找跨越这两个独立数据领域的因素并没有多大意义。因此,我经常发现执行聚类分析的多次迭代来识别可能确实有自然分组的数据的自然分组更有用。
在下面的代码中,我们通过对我们一直在使用的演示数据集执行示例因子分析来完成我们的数据缩减。代码是从这个伟大的因子分析教程这里派生出来的,并应用于我们的数据。以下是对相关步骤的简要概述:
首先,我们列出想要包含的特定列。
其次,我们执行充分性测试,以确保因子分析对于给定的数据是可行的。请注意,我们正在寻找小于 0.05 的 p 值,这表明相关矩阵不是单位矩阵。
第三,我们进行因子分析。
第四,我们可视化特征值,并在图中寻找“肘”,以帮助我们决定我们的模型应该包括多少因素。
接下来,我们重新进行因子分析,并根据我们的“肘”图分析设置因子的数量。
最后,我们提取因子负载并查看它们,以确定我们可能希望如何组合我们的变量。
#subset our dataframe to focus only on domain relevant variables
df_fac = df.iloc[:,98:]import pandas as pd
from factor_analyzer import FactorAnalyzer
import matplotlib.pyplot as pltfrom factor_analyzer.factor_analyzer import calculate_bartlett_sphericity#df_fac from optum_data_segmentation.py
df_fac = df_fac.dropna()chi_square_value,p_value=calculate_bartlett_sphericity(df_fac)
chi_square_value, p_value# Create factor analysis object and perform factor analysis
fa = FactorAnalyzer()
fa.fit(df_fac)
# Check Eigenvalues
ev, v = fa.get_eigenvalues()
ev# Create scree plot using matplotlib
plt.scatter(range(1,df_fac.shape[1]+1),ev)
plt.plot(range(1,df_fac.shape[1]+1),ev)
plt.title('Scree Plot')
plt.xlabel('Factors')
plt.ylabel('Eigenvalue')
plt.grid()
plt.show()# Create factor analysis object and perform factor analysis
fa = FactorAnalyzer()
fa.set_params(n_factors=2, rotation="varimax")
fa.fit(df_fac)loads = pd.DataFrame(fa.loadings_)
loads_df = pd.concat([loads, pd.DataFrame(list(df_fac.columns))], axis=1)
loads_df.columns = ['Factor_1','Factor_2','Variable']
以下是“负载 _df”数据帧的样子:
作者图片
在因子负荷的输出中,我们看到大多数变量对因子 1 的负荷比因子 2 重。也就是说,我们看到“变量 _141”和“变量 _143”在因子 2 上的负载更重。
从这一点来看,降维的下一步是通过平均每个因子上加载的变量来为每个因子创建指数。
例如,如果我们想使用“变量 _141”和“变量 _143”为因子 2 创建一个索引,我们首先需要注意“变量 _143”有一个负负载。因此,在对“Variable_141”进行平均之前,我们需要对该变量进行反向编码。
反向编码的一个快速技巧是在平均之前将变量乘以-1。但是,请注意,只有当我们还打算在建模之前对数据进行规范化时,我们才会这样做(对于大多数数据科学模型,这是一个强烈推荐的过程)。
下面是创建因子 2 指数的一些示例代码:
df['Variable_143_R'] = -1*df['Variable_143']df['Factor2'] = df[['Variable_141','Variable_143_R']].mean()
我们的清洁行动现在需要 2 分钟
既然我们已经花时间减少了数据集中的维度数量,我们就准备将数据传递给更复杂的特征工程,并最终进行下游建模。
总共减少了 50%以上的可用数据,现在我的手心出汗少多了。所以我留给你们这个:
“他最好去捕捉这一刻,并希望它不会错过”
前进!
比如参与学习数据科学、职业发展或糟糕的商业决策?加入我。
Bootcamp 数据科学入门
将职业生涯转向数据科学指南
我写这篇博客的目的是与任何正在考虑职业转型、感到不知从何开始、或在致力于他/她的数据科学职业转型时需要一点鼓励的读者分享我最近开始的数据科学之旅的故事。
我的背景
我是 2016 年金融专业毕业,辅修数学的 SF 地区高级销售运营及策略分析师。我在一家小型精品投资银行起步,很快意识到这不是我理想的文化;这是一个竞争激烈的世界,这不符合我的个性。幸运的是(以及后来的数百份申请),我进入了科技领域,在一家小型初创公司做业务运营和战略分析师。尽管我热爱我所做的工作、有趣的环境以及个人和职业发展机会,但在 2020 年 9 月,我开始探索其他领域,寻求新的挑战,以揭开我人生的下一个篇章。当然,更高的工资是另一个激励因素(没有废话)。
探索阶段
基于我的兴趣和愿望,我的潜在选择是软件工程或数据科学。在这之前的一年,我与一位令人印象深刻的同事进行了一次步行会议,他领导了一些有影响力的项目,对公司和行业有着深入的了解。他是数据科学的主管。我了解到他是从一个与金融相关的领域来到这个职位的。他给我的建议是从 SQL 开始,然后如果我对数据科学领域感兴趣,就继续学习 python。按照他的建议,我完成了 SQL,但是没有继续 python,因为公司正在进行收购,这是一个相当紧张的时期。因此,我自然倾向于进一步探索数据科学。
行动和学习
- **安排与数据科学家的会面:**那时,我不知道从哪里开始,也不知道数据科学在日常和/或专业化方面需要什么。幸运的是,我利用工作之外和当前公司内部的关系,为数据科学家安排了这些会议,以回答我的迫切问题。最重要的是,他们中的一些人告诉我,甚至在我现在的公司也有一些同事是从训练营开始的,这个消息让我大吃一惊。
- **做研究:**我对参加训练营和继续自学方向进行了高层次的成本效益分析。也许因为我是一个怀疑论者,我的大部分在线研究显示,人们对训练营持批评态度,这与我的面对面反馈相反。无论如何,我决定更加重视与我交谈的数据科学家,并继续进行训练营对比。在网上做了一些调查并打电话给他们的招生办公室收集信息后,我选择考虑的前两个是镀锌和熨斗。
作者图片
- **果断点:**在评估了最适合我的环境后,我选择了“激励”。即使在那时,我意识到我几乎没有赶上最后一个优质预备班的截止日期,让你为 2 月份的数据科学沉浸式项目开始日期做好准备。如果你有足够的信息来帮助你做决定,我的建议是你赶快行动。
不要和学习
我做了所有这些不该做的事。事后意识到收益递减,我建议避开以下情况。
- 不要在分散注意力的活动上浪费时间:限制你的研究时间。分配的时间结束后,请集中精力学习构建您的数据科学知识的材料。花很多时间在 LinkedIn 上跟踪数据科学家,试图找到一种职业模式,不会让你接近你的职业。
- **不要因为恐惧而放弃追求数据科学:**我会认为自己是一名好学生(聪明、学习快、勤奋),但我记得编程的想法让我感到恐惧和不知所措。我当然不想暗示编码/数据科学很容易,当然不是。但我可以向你证明,只要你投入时间、精力和努力,你就能掌握各种看似令人生畏的概念。
持续的训练营体验
作者图片
回顾第一个 python 基础视频几乎让我流泪的时候,我觉得编码是我不明白的事情,这很有趣。但这就是训练营的用武之地…我从 Galvanize 的 premium prep 中获得的一个价值是信息合成。正如其他人提到的,所有入门的必要材料都可以在网上找到,而且很大一部分是免费的。有了像“激励”这样的项目,你可以获得清晰有序的学习材料和视频供你使用。当然还有专家资源供您使用!这帮助我轻松地浏览主题,更快地消化信息。讲师们和蔼可亲,富有思想,简直棒极了,其中一些人我会感激很久。我最喜欢的部分是老师故意给学生留下面包屑,以便更顺利地介绍下一章。
课程是截止日期驱动的;这对培养责任感意义重大。很快,我发现了大多数概念的浩瀚。你可以花无数个小时深入钻研,成为一名主题专家。对于像我这样的初学者来说,我发现花更多的时间去理解基本概念,以及学习正确的时机去学习另一个同样重要的科目来接受全面的教育是非常重要的。考虑到数据科学的广度和深度,如果没有激励,我自己是无法高效完成这项工作的。尊重那些有抱负的数据科学家选择自学的路线来完成自己的事业!
查看到目前为止涵盖的主题
- 简介/中级 Python
- 统计学导论
- Unix 介绍,Git/Github
- 熊猫,熊猫,噢
- 积分学、微分学、线性代数
- 结构化查询语言
离别的思绪
如果你能从我的故事中得到什么(在我下一次更新之前),这些是我希望你留下的:
- 努力做到最好!不后悔。
- 一步一步来!重要的是不要感到不知所措和沮丧。
- 每个人的人生道路都不一样;接受并拥抱你是独一无二的。
感谢您的阅读!
材料信息学入门
如何开始研究材料信息学(数据科学+材料科学)
用数据科学理解材料中的结构-性能-性能-加工关系。来自维基共享。
在这篇文章中,我分享了参与材料信息学研究的资源和建议。随着发现和设计新材料以应对一些最紧迫的全球性挑战(人类健康、食品和水安全、气候等)变得越来越昂贵和耗时。),我们需要拥有科学领域专业知识和数据科学培训的材料科学家。无论你是想在自己的研究中使用数据科学,还是只是想更好地了解该领域的发展状况,这篇文章都会帮助你。
我在 GitHub 上分享了一个资源列表,用于材料信息学入门。该列表包括论文和交互式教程、有用的 Python 库、博客、时事通讯、播客、数据库和学术材料信息学研究小组。
什么是材料信息学?
信息学是转换信息(数据)的科学。从某种意义上说,所有的材料科学都涉及信息学,因为所有的材料科学都是建立在数据和解释数据的理论之上的。“材料信息学”,我们特指被现代数据科学所超越的材料科学。这让我们能够加速材料属性预测,在可能的材料空间中进行系统搜索以发现具有优化属性的化合物,甚至根据我们想要的属性设计新材料。
实验科学家可以使用材料信息学来减少他们在实验室中进行反复试验的时间和精力;而计算科学家和理论家可以提供更好的指导,告诉他们制造什么材料、如何制造,以及如何理解它们的属性。你对数据科学和机器学习了解得越多,就越清楚这些是高效科学的工具,而不是科学家和科学思维的替代品。
先决条件
数据科学先决条件:眼镜、大量显示器、夜间模式文本编辑器。来自 Unsplash。
我假设感兴趣的读者已经在材料科学的某些领域工作:纳米材料、聚合物、冶金、生物材料或量子材料。要进行材料信息学的研究(或培养对材料信息学的欣赏),你需要从数据科学的基础开始:统计学,一种科学计算语言,如 Python 或 Julia,具有相关的数值计算能力和数据结构,机器学习,以及用数据讲故事(可视化)。
好消息是,如果你是一名科学家,你可能有很多必要的背景。更好的消息是,现在是学习数据科学的最佳时机——有大量免费课程、教程和博客可供学习。从某些方面来说,最具挑战性的事情可能是筛选所有这些资源并找到最好的。有大量的数据科学入门指南。
根据你的学习风格,你可能想从自下而上的方法开始,从头开始阅读教科书和实施方法,或者从自上而下的方法开始,在你自己的研究中选择一个有趣的问题或者从 Kaggle 中选择一个简单的问题,然后开始破解,边做边学。
进入兔子洞
如果你想对材料信息学有一个简单的技术介绍,你可以从这里列出的资源开始。从材料信息学的详细定义,到正式的最佳实践、交互式教程和为期三天的研讨会,这些资源将帮助您尽快入门。
如果你对这个领域感兴趣,无论是作为一名从业者还是一名不经意的观察者,这里有一些博客、播客和时事通讯可以帮助你。
图为:用材料信息学加强研究后的你。来自 Unsplash。
行业工具
一旦你准备好开始自己的材料信息学研究,利用许多已经可用的令人惊叹的开源项目会有所帮助。Python 是该领域的编程语言选择,Jupyter 笔记本环境是进行材料信息学的虚拟实验室。以这些工具为基础,有完整的软件生态系统来生成和分析计算的材料数据,建立机器学习管道来预测性能和设计新材料,可视化材料数据,并以机器可读的方式分享您的研究。
努力实现的一个关键原则是确保您的数据是可查找、可访问、可互操作和可重用的(公平)。换句话说,让其他科学家更容易将你的数据用于材料信息学!幸运的是,有一些很棒的框架可以让你的数据清晰可见,并以一种可以通过网络界面和 Python API 探索的方式分享。
一切都是为了数据……
数据科学的第一条戒律是“垃圾进,垃圾出”这一切都归结于获得带有某种信号的巨大数据源,处理它,并应用可用工具的瑞士军刀来提取一些见解。如果缺少第一步:高质量的数据源,任何机器学习方法都无法提供有意义的输出。世界各地的英雄们不辞辛苦地计算和测量了成千上万种材料的特性,并使这些数据在数据库中变得容易获取。
即使是现在,大多数耗费大量人力和资源生成的材料数据都被锁在 pdf 的图形、表格和文本中。有正在努力解析 pdf 并挖掘数据,但是你可以通过将你的数据贡献给数据库并使其公平,在你自己的研究小组和你的领域内产生直接影响。
…还有问题
数据科学的第零条戒律是“问正确的问题”数据科学不能告诉你你的研究方向应该是什么。科学家的主要工作仍然是弄清楚什么是最有趣的问题去询问和研究。希望通过使用这些资源,你能更好地理解材料信息学能做什么和不能做什么。
材料信息员
为了帮助学生、博士后和教师找到所有在这个领域工作的优秀团队,我列出了一个简短的材料信息学团队(排名不分先后)。这些小组专注于完全不同的材料科学领域,共同的主题是他们在某种程度上使用理论、计算和数据科学。如果您在材料信息学小组工作,并且希望被添加到列表中,请告诉我!
欢迎投稿!
我喜欢你的反馈!该资源列表并不全面,相反,它是我在自己的工作中发现的有用的东西的精选集合。我忽略了许多前沿方法(例如,量子机器学习、等变神经网络),因为它们还没有达到日常使用所需的成熟水平,也不太适合“入门”水平。如果有材料信息学资源的某些功能没有包含在列表中,请随意阅读投稿指南并与我分享。我还要感谢 Pat Walters 出色的化学信息学资源列表,它启发了这个列表。
保持联系
如果你喜欢这篇文章或者有任何问题,请随时通过电子邮件联系我,或者通过 LinkedIn 和 Twitter 与我联系。
完整的资源列表可以在 GitHub 的这里找到。
你可以在我的网站上找到更多关于我的项目和出版物的信息,或者只是阅读更多关于我的。
医疗人工智能入门
临床医生在线学习资源指南
随着人工智能(AI)改变医疗实践,所有临床医生都将成为机器学习技术的用户,并将需要学习人工智能和机器学习的基础知识。当你计划升级你的机器学习知识时,你可能会对许多可用的教育选项感到困惑。
我最近完成了为期四个月的休假,在此期间,我调查了越来越多旨在建立人工智能知识和技能的教育课程、视频和书籍。以下是我基于那次经历的想法。
我已经按照职业轨迹组织了我的建议,从放射科医生和其他经验很少的医疗专业人员的基本资源开始,到任何具有强大技术背景和更雄心勃勃的目标的人的高级课程结束。你需要根据你的背景、经验和职业目标来定制你的道路。
放射学家和放射实习生
如果你对人工智能和机器学习完全陌生,那么通过 Coursera 在吴恩达的 deeplearning.ai 项目中提供的 AI for Everyone 课程,强调了为什么人工智能是如此多行业的焦点,而不仅仅是医疗保健。对于医疗保健特定的材料,您可以尝试由北美放射学会 (RSNA,小额费用)、医学成像信息学学会(SIIM) 和美国放射学院(ACR) 提供的网络研讨会,以及由健康人工智能研究中心提供的研究研讨会、期刊俱乐部、小组讨论,包括https://www.youtube.com/c/stanfordaimi医学和成像人工智能中心(AIMI 中心)的 YouTube 频道。
无论你是正在接受培训的放射科医师,还是经过委员会认证的放射科医师,由 RSNA 和 SIIM 赞助的国家影像信息学课程(NIIC) 都清晰地介绍了更广阔的信息学世界——结合录音和现场讲座,以及“翻转课堂”,使信息学名人和同学能够进行小组讨论。任何住院医师项目的受训者都可以参加这一课程,只需象征性的费用,但是住院医师需要说服他们的项目主管提供一个临床时间表的休息时间。训练有素的放射科医生也可以付费参加该课程。
如果你参加 RSNA 年会,我强烈推荐参观 RSNA 的深度学习实验室。在 90 分钟的初级班中,你将使用自己的笔记本电脑来构建和测试一个对医学图像进行分类的深度学习算法。这一简短的经历是对上述教学材料的完美补充,对于理解人工智能算法是如何构建的,包括陷阱是至关重要的。
研究合作者和实践领导者
你们中的一些人有雄心不仅仅成为一个有见识的人工智能用户。例如,你可能渴望成为你临床实践的人工智能领导者——协助决定采用机器学习算法,制定人工智能技术的实施和监控计划,并决定临床实践数据的管理政策。其他人可能会寻求成为领域专家和研究实验室的合作者,或者与行业合作伙伴一起开发机器学习技术。这些目标需要对神经网络和深度学习有更丰富的理解。
机器学习的基本技巧之一是将复杂的计算任务重新转换为一组矩阵运算。作为机器学习命脉的图形处理单元(GPU)通过快速的矩阵数学获得了它们的能力。如果你从来没有学过线性代数,或者像我一样,已经忘记了你所学的大部分内容,我建议你复习一下向量、矩阵、张量以及相关的数学运算。来自 3Blue1Brown 的视觉导向的 YouTube 视频对深度学习和神经网络所必需的矩阵运算给出了清晰的视觉解释。前 10 个视频以正常速度需要 90 分钟左右。
医疗保健专业的人工智能可以作为任何人的健康人工智能教育的基础。这门课程是在我休假快结束时发布的,但已经吸引了成千上万的学习者。专业化从健康经济学家劳伦斯·贝克(Laurence Baker)的医疗保健介绍开始,他介绍了医疗保健系统的基本要素,重点是美国。即使你已经在美国医疗系统工作,本课程也将提供有用的健康政策复习。课程的一些元素与人工智能直接相关,例如对可能来自患者、提供商和中介的不同数据源的讨论。您可以决定本课程中的哪些主题最符合您的需求。
Nigam Shah 教授的第二个专业课程是关于健康数据的。我们如何找到正确的医疗保健数据来回答一个特定的问题?由于数据的收集方式,哪些偏见可能会影响数据?研究人员应该如何处理时态数据、缺失值和文本数据的问题?这些问题是用具体的例子来回答的,这些例子说明了像特征矩阵和知识图这样的概念。第 7 周的道德模块尤其及时。
第三个课程,医疗保健机器学习基础,重点是机器学习方法。讲师 Matt Lungren 和 Serena Yeung 从基本术语和行话的定义开始。然后我们学习损失函数、梯度下降和其他关键概念,接着是过拟合和欠拟合以及其他对算法评估很重要的概念。关于机器学习陷阱的讲座,包括对因果关系、环境、信任和可解释性的讨论,是非常宝贵的。任何计划开始一个大型项目的人都应该密切关注第 6 周关于组建跨学科团队的材料。
第四门课程,由 Tina Hernandez-Boussard 主讲的医疗保健中人工智能应用的评估,讨论了我们如何决定人工智能算法何时工作良好,包括效用和可行性的概念,以及对行动所需的前置时间的实际考虑。强调了实施过程中迭代和部署后监控的重要性。第 4 周提供了可能影响人工智能评估的偏见的广泛目录,并讨论了公平性、校准和透明度。监管的考虑和美国食品和药物管理局包括在内,这是一个全球监管图片的简短讨论。
由所有教师领导的顶级课程将所有材料联系在一起。
机器学习研究人员
任何想成为真正的数据科学家的人都应该学习基本的软件开发技能。python 是一种用于机器学习任务的流行语言,可以在网上的 W3Schools 、 Codecademy 和许多其他地方找到优秀的互动课程。
为了学习医学成像的各种深度学习方法,RSNA 深度学习实验室的全系列实践课程涵盖了图像分割、数据准备和生成对抗网络。当你开始构建实用的深度学习模型时,你可以参考 Brad Erickson 的魔术师之角,这是Radiology:Artificial Intelligence杂志上的一系列文章,与 RSNA 深度学习实验室的课程平行,并提供系统设置的逐步指导。
杰瑞米·霍华德的 fast.ai 课程是我个人最喜欢的课程,对于任何有很强技术背景但懂一点编程的人来说,它都是理想的资源。该课程采用自上而下的方法,从几行计算机代码开始,而不是建立详细的数学符号。第一课将指导你构建和测试你自己的深度学习模型。(我的能以 95%的准确率区分 37 种猫狗。)每一课都使用动手的方法来揭开深度学习的神秘面纱,Jupyter 笔记本中预先编写的代码可供您探索、修改和重用。没有抽象的定理或证明需要努力学习,但在课程结束时,你将知道如何阅读和理解任何深度学习论文的方法部分。
我没有花太多时间做练习,因为我是一个编程老手,现在主要管理项目而不是写代码。但这并没有影响我的学习。对于那些喜欢印刷版的人来说,杰里米刚刚与人合著了一本书,以同样的顺序提供了同样的材料。
吴恩达在 Coursera 上从 deeplearning.ai 推出的开创性和广受欢迎的深度学习专业是对 fast.ai 课程的一个很好的补充。Andrew 采用传统的自下而上的方法,从深度学习的基本概念的理论基础开始。他讲述了许多开创性的人工智能概念的历史和演变,介绍了标准符号,并强调了关键的参考资料。大量的练习提供了你所学的实际经验。我跳过了第三个课程,构造机器学习项目,因为我在这方面有经验,但其他人可能会发现它很有用。该系列的最后一门课程涵盖了序列模型,对于放射科医生和其他处理文本数据的临床医生来说将会特别有意义。它回顾了自然语言处理方法的当前进展,包括来自转换器的双向编码器表示(BERT)和其他转换器方法。像 fast.ai 一样,我发现整个课程很容易跟上,无需完成练习。此课程序列最近已更新。
参考资料
对于真正的核心,一些学术文本为机器学习概念提供了大量的数学基础。古德费勒、本吉奥和库维尔的深度学习在亚马逊有售,在线免费。神经网络和深度学习作者迈克尔·尼尔森,也可以在网上免费获得。这些资源不是为胆小的人准备的,但对于那些想在特定领域更深入研究的人来说,它们是有用的参考文本。
我祝你在机器学习的事业上一切顺利!
Pytest 单元测试入门
入门
没有数据科学家认为他们需要的工具,除非他们知道。
本周,我在一个数据摄取管道上工作,该管道必须处理许多不同的数据场景。我们就说是政府数据,其他的你可以想象。我遇到了一个你可能很熟悉的问题。我开始更新我的函数来处理不同的数据清理场景,这破坏了以前的工作代码。在我的例子中,这些问题大多是在使用正则表达式解析文本时出现的。
此时,我意识到是时候进行单元测试了。为什么?因为单元测试正是为这个问题而设计的。您编写小的独立测试来确保您的代码按预期执行。每当您对代码进行更改时,您都可以轻松地运行这些测试,以确保您没有破坏任何东西,并且您可以继续添加测试,以确保对代码的新更改不会破坏您早已忘记的场景。
我不认为每个数据科学项目都需要单元测试。许多项目都很小,目标明确,因此测试是不必要的。但是一旦你开始编写一个需要维护的包,这是任何生产中使用的包,测试就变成了一个巨大的时间节省器。在这一点上值得注意的是,几乎所有最常见的数据科学包(包括Pandas
、NumPy
、scikit-learn
和matplotlib
都使用pytest
作为他们的测试框架。
pytest
Python 自带unittest
,大多数情况下运行良好;然而,今天大多数开发者都在使用pytest
。值得看一下这两个工具的文档,但是因为这是一个速成课程,我们将只看一下pytest
和它的三个最常用的工具:
- 基本断言测试
- 参数化
- 固定装置
这里使用的所有代码都可以在这个 GitHub 库中找到。
让我们开始吃吧。
安装 pytest
要继续学习,您需要安装 pytest。在大多数系统上,您可以通过在命令行运行以下代码来实现这一点:
pip install pytest
基本断言测试
我们将从头开始。我们的第一个测试将测试一个简单的加法函数。我们将把这段代码放在一个名为project.py
的文件中。
def add(a, b):
return a + b
测试代码放在以test_
为前缀的文件中。当我们运行测试时,pytest
将执行一个发现过程。发现过程将递归扫描当前文件夹及其所有子文件夹,寻找以test_
开头或以_test
结尾的文件。Pytest 将运行位于这些文件中的测试。
现在我们知道我们需要一个前缀为test_
的新文件。我们将在前缀后面添加我们正在编写测试的文件的名称。这给了我们一个文件名test_project.py
。将以下内容添加到您的新测试文件中。
def test_add():
import project # test basic functionality
assert project.add(1,1) == 2 # try a border case
assert project.add(-1,-1) == -2
注意测试函数也带有前缀 **test_**
**。**当 pytest 扫描我们的文件时,它将运行任何带有test_
前缀的函数。
查看测试函数,我们可以看到实际的测试使用了assert
关键字。如果assert
后的表达式为真,功能将继续。如果assert
后面的表达式为假,则assert
将引发AssertionError
。这将导致测试失败。
为了运行测试,我们进入命令行并键入pytest
。
作者图片
如果我们的测试失败了会发生什么?让我们将第一个断言改为:
def test_add():
import project # 1+1 != 3\. This will rais an AssertionError
assert project.add(1,1) == **3**
作者图片
pytest
不仅清楚地表明我们的测试失败了,而且通过向我们展示函数和测试失败的原因,它还告诉我们确切的位置!从底部开始检查这个结果,我们看到:
- 失败的 test _ project . py::test _ add—assertion error:assert 2 = = 3它告诉我们文件名、测试函数以及导致失败的原因。在这种情况下,我们的表达式(计算结果为 2 == 3)为假。
- 就在那上面,有一个“test_add”部分,以“test _ project . py:10:assertion error”结束。这告诉我们错误的文件和行号。
- 上面的一切给了我们错误的上下文,所以我们可以理解并快速修复我们遇到的任何问题。
注意,虽然有两个 assert 语句,但是 pytest 认为这只是一个测试,因为它们在同一个函数调用中运行。
让我们看看另一个涉及熊猫DataFrame
的例子,它可能更像我们在数据科学工作流中看到的东西。
这是我们想要测试的函数。它向一个DataFrame
添加一列。
def add_col(df, colname, coldata):
# add a column to a DataFrame
df[colname] = coldata
return df
为了测试这一点,我们将:
- 在我们的
test_project.py
文件中创建另一个以test_
开头的函数。 - 定义一个起点
DataFrame
。 - 定义我们的预期结果
DataFrame
。 - 通过调用 DataFrame 的
equals
方法,将使用add_col
函数向起始DataFrame
添加一列的结果与预期结果DataFrame
进行比较。
def test_add_col():
import project # start
df = pd.DataFrame(
[[0, 1], [2, 3]],
index=['cat', 'dog'],
columns=['weight', 'height']) # expected
df_expected = pd.DataFrame(
[[0, 1, 2], [2, 3, 2]],
index=['cat', 'dog'],
columns=['weight', 'height', 'n_ears']) # test the result
assert project.add_col(df, 'n_ears', 2).equals(df_expected)
重新运行 pytest,我们可以看到我们的新测试通过了,但是之前的测试仍然失败。我们可以看到有多少测试失败了,有多少通过了。当其中一个测试失败时,测试不会停止;它运行我们所有的独立测试,并向我们报告每个测试的结果。
让我们通过在我们的test_add
函数中修改这条线来恢复这条漂亮的绿线。
assert project.add(1,1) == 2
作者图片
是啊!
参数化测试
另一个在某些情况下有用的工具是用不同的参数调用测试函数的能力。我们将创建一个新的测试函数,一个减法函数。
def subtract(a, b):
return a - b
在 pytest 中,参数化是通过一个装饰器来完成的,该装饰器定义了我们想要传递给测试函数的参数。让我们为使用不同参数的 subtract 函数定义一个测试。
# test parameterization
[@pytest](http://twitter.com/pytest).mark.parametrize("a,b,expected", [[2,1,1], [-1,1,-2]])
def test_subtract(a, b, expected):
assert project.subtract(a,b) == expected
让我们仔细分析一下。装饰器告诉 pytest 将列表元素作为a
、b
和expected
传递给下面的函数。它将为每个列表重复函数调用。
如果我们重新运行测试,我们会看到现在有 4 个测试,而不是 3 个。因为参数化多次调用测试函数,所以每个函数调用都算作一个单独的测试。
作者图片
固定装置
您可以想象,如果您要在同一个数据帧上测试许多执行不同任务的函数,那么在测试之间回收该起始数据帧会很方便。这就是固定装置的用途。
fixture 是一个带有特殊装饰器的函数,它创建一个资源并返回它。然后我们可以调用我们的测试函数,就像我们传入了那个资源一样。这有点违反直觉,但我认为一旦你看到它的作用,它就会有意义。
这是固定装置。
[@pytest](http://twitter.com/pytest).fixture()
def df():
df = pd.DataFrame([[0, 1], [2, 3]],
index=['wallaby', 'kangaroo'],
columns=['weight', 'height'])return df
当我们调用我们的测试时,我们将在中传递 fixture 函数的名称。Pytest 将调用该函数,并将其返回值传递给我们的测试函数。
def test_add_col2(df): # expected
df_expected = pd.DataFrame(
[[0, 1, 3], [2, 3, 5]],
index=['wallaby', 'kangaroo'],
columns=['weight', 'height', 'hop_height']) assert project.add_col(df,
'hop_height',
[3,5]).equals(df_expected)
注意,我们定义了test_add_col2
来将df
作为参数。因为我们已经定义了一个名为df
的 fixture 函数,pytest 将调用df
fixture 函数并将结果传递给test_add_col2
。
运行我们的测试,我们得到:
作者图片
包起来
显然,使用 pytest 单元测试可以做更多的事情,但是在您了解所有这些东西之前,现在就开始做是值得的。当您看到拥有一套测试的力量时,无论您何时更改您的包,您都可以快速、轻松地运行这些测试,您还将体验到大量的时间节省。即使你还没有看到它的价值,如果你想为任何开源项目做贡献,你可能需要为你的贡献编写测试。
也就是说,不要觉得你需要立即为你所有的代码创建完整的测试套件;在大多数情况下,这是不切实际的。相反,当您开始对代码进行更改时,或者当项目的范围变得足够大而不总是清楚某个函数需要处理的所有情况时,可以考虑编写测试。
向前迈进,测试你的代码,把你的额外时间花在你的家人身上。
资源
- Pytest 文档
- 测试组织从贡献给熊猫
- Aditya Sharma 的 Python 单元测试
- 与 Python 的持续集成:简介
- 维基百科上的单元测试
Pytest 单元测试入门—第 2 部分
制作一个单元测试的模拟器- y。
上周我写了关于开始单元测试的文章。我们讨论了基本的断言测试、参数化、固定装置,最重要的是,测试如何节省您的时间,以便您可以完成更多的工作或花更多的时间与家人在一起——这是您的选择。本文从上一篇文章停止的地方开始,所以如果您需要复习,这里有那篇文章:
单元测试的一个重要原则是它们应该是独立的。在测试环境中,这意味着我们的测试应该只依赖于我们正在测试的功能,而不是任何其他服务或功能。Immagine 你的函数对 goggles.com 进行 API 调用,并使用一些复杂的人工智能返回与你的搜索最相关的泳镜。如果我们不模拟 API 调用,我们的测试将依赖于它。
在我们的测试中,依赖那个 API 调用有几个问题。最常被提起的是时间。一个 API 调用可能需要一两秒钟,我们希望我们的测试很快。我们也想经常测试,如果我们对这些 API 调用收费,测试会变得很昂贵。但是这两个都不是我们不想依赖那个 API 的主要原因。
记住,单元测试的主要目的是节省我们维护项目的时间。如果那个 API 关闭,我们的系统可能会崩溃,但是当我运行我的测试时,我们不希望测试告诉我们问题出在调用 API 的函数上,因为它不是。我们希望我们的测试告诉我们,如果 API 关闭,我们的系统将如何响应,我们也可以通过模拟来模拟。好的测试会告诉我们,我们的代码是否独立于我们所连接的任何其他代码或服务而工作。
测试的主要思想是告诉我们 我们的代码 是否在做我们期望的事情。如果 goggles 的代码坏了,应该不会影响我们的测试。这应该反映在他们的测试中。
好了,解决了这个问题,我们该怎么办呢?
设置
要进行后续操作,您需要安装pytest
和pytest-mock
。
pip install pytest pytest-mock
您也可以在本文的 GitHub 资源库中跟随。
设置场景
首先,我们将假设进行一个 API 调用。
from time import sleepdef fetch_goggles():
# make an api call to goggles.com
# ...
sleep(4) response = {"foo": True}
return response
我们将为它编写一个测试,就像我们在本系列第 1 部分中所做的一样。
def test_fetch_goggles():
import project result = project.fetch_goggles() # test that the value in result['foo'] is True
assert result['foo']
运行测试。
作者图片
太棒了。我们的测试通过了。但是如果 API 调用失败了呢?我们可以通过改变函数的返回值来模拟。如果您遵循 GitHub 存储库中的代码,您可以取消注释新的响应行。
def fetch_goggles():
# make an api call to goggles.com
# ...
sleep(4) # return a 408 (timeout) status code
response = {"status": 408}
return response
作者图片
哦不!我们可以看到我们的测试失败了,因为结果对象没有将foo
作为键。
如果这个 API 调用实际上失败了,它不应该破坏我们的代码。那么,我们如何确保它不会发生呢?
模仿者
这个问题可以通过使用mocker
fixture 和“修补”API 调用来解决。在其最基本的形式中,有两个元素我们必须添加到我们的测试函数中,以便用 mocker 修补。
- 将
mocker
作为夹具添加到我们的测试函数定义中(夹具在第 1 部分的中讨论过,以防你错过)。mocker
夹具由pytest
提供。 - “修补”我们想要规避的功能
新代码如下所示:
def test_fetch_goggles(**mocker**):
import project **mocker.patch('project.fetch_goggles',
return_value={'status':200,"foo": True})**
result = project.fetch_goggles('Hi') assert result['foo']
让我们仔细看看那条mocker.patch
线。第一个元素是一个字符串,它匹配我们希望替换的对象的模块路径。请注意,它与下一行的project.fetch_goggles
相同,但没有()
。我还向我们的project.fetch_goggles
函数传递了一个变量,以说明无论向函数传递什么,返回值都是相同的。一个被模仿的函数会接受你给它的任何东西而不抛出错误。这是很重要的一点,也是你对嘲讽越来越熟悉时需要小心的地方。
运行测试:
砰。测试在 0.02 秒内完成。你可能从图片上感觉不到,但是等待测试完成 4 秒钟感觉是很长的时间。这样好多了。
模仿者提供的另一个我们绝对不想错过的机会是测试 API 调用的失败的能力。毕竟,我们确实想优雅地处理生活和代码中的失败。
def test_fetch_goggles_failure(mocker):
import project mocker.patch('project.fetch_goggles',
return_value={'status':408})
result = project.fetch_goggles() if result['status'] != 200:
# recover gracefully
graceful_recovery = True
# assert that this was not a success
assert graceful_recovery
我们已经将mocker.patch
中的返回值改为{'status':408}
。这模拟了 API 调用超时。现在我们可以测试如何从 API 调用失败中恢复。这使得我们的代码更有弹性,并且仍然不依赖于实际调用 API。
作者图片
现在我们知道我们是优雅的。
嘲笑物品的用途,而不是它的来源
如果你还没听过这个,你会的。你会听到很多次,才会有意义。这不完全是你的错。让我们看看我们是否能分解它。
首先,《去哪儿嘲讽》比较混乱。大家说这话的意思是“如何引用你要嘲讽的对象。”您实际上在测试函数中编写了模拟程序。问题是,您要模仿的对象的路径需要遵循特定的路线。
你可能经历过这些。您导入pandas
并编写一些代码。您决定将一些代码分解到一个单独的helpers.py
文件中。您从helpers.py
将函数导入到您的应用程序中,但是当您第一次运行代码时,您得到一个错误:NameError: name ‘pd’ is not defined
。显然,你忘了在你的新helpers.py
文件中导入熊猫。这是理解如何创建想要模仿的对象的路径的关键。
我们将使用 API 调用函数创建一个helpers.py
文件:
# helpers.pydef fetch_goggles():
# make an api call to goggles.com
# ... response = {'status':200,
"count": 5} return response
我们还将在project.py
中创建一个新函数,在这里我们将使用这个函数。
import helpers
def count_goggles():
result = helpers.fetch_goggles()
return result['count']
最后,我们创建测试函数。
import project
ojectdef test_count_goggles(mocker): mocker.patch('project.helpers.fetch_goggles',
return_value={'status':200, "count": 4}) result = project.count_goggles()
assert result == 4
为了修补我们的函数,我们沿着从我们所在的地方到函数的路径。从测试文件中,我们导入了project
。从project
我们导入了helpers
。fetch_goggles
驻留在helpers
中。因此我们得到project
。helpers
。fetch_goggles
作为我们希望修补的对象的路径。
结论
嘲讽是测试人员工具箱中的一个便捷工具,既然你现在是一名测试人员,你将嘲讽。模仿的价值在于它允许我们保持测试的真正独立性,并给我们一种方法来测试不同类型的返回值,而不需要这些值的所有上下文。当你在学习构建更好的单元测试时,永远记住要考虑单元测试的独立性。
似乎总是有很多关于“嘲笑哪里”的讨论,可能是这个问题的框架造成了混乱。您在您的测试函数中编写 mock,并沿着模块路径找到您正在模仿的对象。我建议不要去想“你在嘲笑哪里”,因为那只会让人困惑。
现在去做你的单元测试。
神经网络入门
使用 Pytorch 的简单 CNN 示例
图片来自 https://pixabay.com/images/id-1201014/的 https://pixabay.com/users/remazteredstudio-1714780/
问题是
在这篇文章中,我们要解决的玩具问题是识别图像中一条线的起点和终点的坐标。图像将是全黑的,即除了代表线的像素之外,所有像素都是 0。
这既不是分类问题(目标是识别线的存在或不存在),也不是对象检测问题(处理识别不是一个而是许多对象,对对象进行分类并通过边界框识别它们的位置)。这在某种程度上介于两者之间,这种选择的基本原理只是为了处理一些与网上数百个现有分类示例略有不同的东西。
基础知识
我们需要做一些事情来设置神经网络的必要组件。
图 1:训练步骤的简单列表(图片由作者提供)
- 数据准备
- 模型定义
- 训练和测试功能:训练功能是图 1 中调用的步骤将驻留的地方
- 损失函数和优化器
1.数据
在我们的练习中,我们将准备自己的自定义数据集。我用 skimage 生成了线坐标。给定起点和终点坐标,这将生成两个数组,表示属于该行的像素的索引。一个代表 x 的列表,另一个代表 y 的列表,把它们放在一起给出了直线经过的坐标。
https://scikit-image.org/docs/dev/api/skimage.draw.html#skimage.draw.line
图 2:生成一行(作者图片)
图 2 显示了一个简单的例子,说明我们将如何实现这一点。首先,我们将创建一个表示全 0 的单通道 10 X 10 图像的张量。然后,我们将随机选择一个起点和终点,以获取表示该行的像素的索引,并在创建的图像张量中将相应的值设为 1。
图 3 是利用该逻辑来创建图像和结果张量的函数。图像数量(dataCount)和图像大小(imgPixelSize)被定义为输入参数。注意:在这个例子中,我使用 128 作为 imgPixelSize。
当我们随机选择一个起点和终点时,我们还会执行一些基本的检查。
首先,我们确保起点总是在终点的左边。这仅仅是基于一种直觉,对于给定的任何一条线,我个人很可能总是将最左边的点指定为“起点”,而将另一个点指定为“终点”。
这使我能够消除“顺序无关紧要”的问题。给定一条从(0,0)到(9,9)的线,虽然从技术上来说将任一点称为起点或终点都是正确的,但训练模型以适应这两种可能性可能需要我编写一个自定义损失函数,而不是简单地与一个单一的基本事实进行比较。我还直觉地感觉到,像这样的约束可能有助于模型训练得更快。
第二个检查相当简单,我们确保随机选择的起点和终点不相同(如果是,那就不是一条线,而只是一个点)。
最后,我们返回图像和相应的结果张量。结果张量只不过是开始和结束坐标的表示,即具有 4 个值的张量。
图 3:创建线条
虽然这创建了我们需要的张量,但是使用它需要我们创建一个自定义数据集和一个相应的数据加载器。自定义数据集应该是实现 len()函数(返回数据集的长度)和 getitem(index)函数(返回给定索引处的样本)的类。我们还将使用 Pytorch 的数据加载器来创建一个可迭代的加载器,它将允许我们批处理和混洗数据。
图 4:定制数据集和数据加载器
2.培训和测试功能
训练函数非常简单,实现了图 1 中的内容。它将数据加载器、模型、损失函数和优化器作为输入,将模型置于训练模式,并为每一批迭代数据加载器。
对于每一批,我们首先将数据移动到可用的设备(gpu vs cpu),然后使用当前模型预测该批的结果,根据预测和基本事实计算损失,将上一轮的梯度归零,使用反向传播计算这一轮的梯度,并让优化器采取一个步骤来更新模型参数。
正如您可能注意到的,这是一个非常通用的函数,不管我们的模型结构如何,也不管我们选择的损失函数或优化器如何,它都能工作。
我们也有通用的测试函数,旨在评估不同于训练数据集的单独测试数据集的损失。测试函数的目的是查看模型对以前没有见过的数据(即没有训练过的数据)的表现。因此,我们将模型置于评估模式,只进行预测并计算损失。
图 5:训练和测试功能
3.模型
通过设计,卷积运算考虑了两个相邻像素之间的空间关系。一段时间以来,卷积神经网络一直是处理图像的事实架构。尽管还很初级,我们的玩具数据集也能处理基本的线条图像。所以让我们从建筑开始。
我从一个接一个的卷积层的随机排列开始。一个简单的谷歌搜索“卷积神经网络”显示,典型的标准似乎减少了高度和宽度,同时增加了这些层上的通道。最后,我们往往会有一个线性层堆栈,将最后一个卷积层展平为输出矢量。
在我们的例子中,输出向量将代表我们想要预测的内容。它将是一个 4 个值的张量,代表线的起点和终点的(x,y)坐标。
图 6:模型 1
上面的图 6 代表了模型本身。在这个例子中,我使用 128 作为 imgPixelSize。因此你所看到的数字都是由此而来的。第一个卷积层表示输入将有 1 层,这是我们在图 3 的 createDate 函数中生成的。它还指示输出将具有 4 层,卷积核的大小将为 3,步长为 2。我们有三个以上的 conv 层堆叠在这上面。然后,我们将输出变平,并在顶部堆叠几个线性层,最后一层产生 4 个值的输出张量。
你可能会注意到,重要的是我们不仅要知道第一层的输入形状,还要知道每一层的输入形状。在 Conv2D 中,我们需要知道输入中的通道数,而在线性中,我们需要知道输入张量的大小。虽然手动推导对于了解这些操作是如何工作的很重要,但是您可以将样本输入传递到一个临时的顺序网络,该网络由模型中使用的一个或多个相同的层组成,并打印结果的大小。请参见下面的图 7,了解如何快速了解添加到模型中的图层末尾的大小。
图 7:快速确定每层末尾尺寸的方法(图片由作者提供)
4.损失函数和优化器
交叉熵损失和 MSE 损失可能是许多例子中两个比较流行的损失函数。交叉熵通常用于分类问题,从公式的核心你可能已经注意到了。它是预测值的对数的函数,在分类问题中,我们感兴趣的是将真实类别的预测值推至 1,当预测值向 1 移动时,对数和损失将向 0 移动(反之亦然)。
图 8:交叉熵损失(图片由作者提供)
然而,我们不是在处理分类问题。我们处理的是预测一个“连续”值——介于 0 和(imgPixelSize-1)之间的任何值。以指示起点和终点的坐标。MSE 或均方误差适用于这类问题。正如下面的核心公式所示,这里我们处理的是实际值和预测值之间的差异,而不是预测值的对数。
图 9: MSE 损失(图片由作者提供)
输出向量预计包含 4 个数字,代表线的两个点——起点和终点。由于不熟悉哪种优化器工作得最好,我选择了 SGD——在 Pytorch 文档的快速入门示例中,它与 MSE 损失一起使用。
结果、观察和改进
请参见下面的图 10,了解我们上面讨论的所有内容是如何组合在一起的。
图 10:将所有这些整合在一起
只是为了测试所有部分是否都按预期工作,我重新创建了一个只有 100 张图像的训练数据集,并用该模型运行了 1 个时期。虽然端到端的过程看似可行,但结果却非常糟糕。对于更大的数据集,我甚至无法完成训练。
图 11:不良结果— 100 个图像训练数据集(作者提供的图像)
图 12:不良结果— 1000 个图像训练数据集(作者提供的图像)
但这是我们想要的初稿。第一稿不是迷失在一个“部分”的完美中,而是意味着首先将整个设置到位。我们可以稍后微调这些部分。
爆炸梯度
在最后一次跑步中,我注意到了一些事情。一是所有结果都是 NaN。当打印来自训练函数的预测时,很明显,在几轮训练后,预测开始呈指数增长,直到它变成 NaN。在打印模型参数(即权重)时,它们也变成了 NaN。
图 13:参数和预测都是 NaN(图片作者提供)
这表明了爆炸梯度问题。这是当导数很大时的情况,因为当我们反向传播时梯度也很大,并且模型权重变化如此剧烈,以至于它们变得太大而无法存储并变成 NaN。在图 14 中,您可以看到权重是如何以指数方式在各个时期更新变大的。
图 14:爆炸渐变(作者图片)
标准化数据
图像处理中的一个基本建议是归一化输入数据和输出,以避免爆炸梯度问题。在我们的数据中,我们没有这样做。
我们有两组数据。一个是图像本身,另一个是结果集。碰巧的是,我们生成图像的方式已经将背景像素标记为 0,将代表线条的像素标记为 1。因此不需要对图像数据进行进一步的归一化。
或者,如果我们处理的是一幅真实世界的图像,其中像素值可能在 0 到 255 之间变化,我们可能必须将它们除以 255 才能得到介于 0 和 1 之间的值。
另一方面,结果集需要一些规范化。目前,我们有绝对坐标,即一对 0 到 127 之间的数字,来代表起点和终点。让我们将它们除以 128,这是我们使用的图像的大小。
图 15:规范化结果集(作者图片)
激活功能
还要注意,我们的任何一层都没有激活功能。一般来说,跨层具有非线性激活函数是很常见的。这在一般意义上有所帮助,因为网络将学习非线性关系,没有这种关系,我们只是将一个线性函数应用于另一个,并创建一个大的线性函数。
尽管有卷积层,但在它们之间缺乏非线性激活函数将导致这样一个线性网络。如果我们把不同的层看作是代表一系列抽象概念的观察者的输入图像,以寻找起点和终点为最终目标,我不得不想象这些层之间的关系的性质将不会简单地是线性的。即使是这样,也可以用非线性激活函数在模型中表示这种关系,而用线性函数表示非线性关系则是不可能的。
所以在图层后添加了 ReLU。如今,在各种中枢神经系统中,标准做法是在卷积函数之后添加 ReLU。
图 16:修改后的模型(作者图片)
减少的层
考虑到我们的问题相对简单,我们还减少了卷积层的总层数。注意:我们现在没有添加任何脱落层(图像处理模型中的另一个常用功能),因为我们处理的是非常初级的图像,而不是具有复杂图案的真实图像。因此,在我们的案例中,辍学实际上可能会伤害学习,而不是帮助学习。
精度度量
为了获得更好的精确度,还添加了一个新的函数,允许在预测开始和结束坐标时有一定的回旋余地。即,如果(20,20)是起点的坐标,则预测(22,22)不一定是错误。因此,为了更好地了解模型是如何运行的,编写了一个新的函数,该函数将基础事实、预测和偏差作为输入参数,任何落在偏差定义的边界内的预测都不被视为错误。
图 17:考虑偏差的准确度指标(作者图片)
学习率
最后,我们必须了解要使用的正确学习率。从 0.1 的学习率开始,我注意到输出要么是 1,要么是 0。在打印线性层末端的中间权重和输出时,我注意到最后一个线性层的输出达到非常高的正值或负值。虽然参数本身没有发生如此剧烈的变化,但无论做了什么改变,都足以导致这种情况。
所以我将速率降低到 0.01,较慢的学习速率意味着参数值的变化较小,然后再次尝试。虽然更新确实更小,并且需要几个额外的时期,但最终结果仍然相同,输出收敛为 0 或 1。但是 0.001 的情况要好得多,我注意到即使经过 5 个时期,这些值并没有真正变成 1 或 0。它们在第一批结束时增加,在下一批减少,表明某种对最优解的搜索正在发生。
因此,在这种学习速度下,我运行了 500 个时期的训练,如图 X 中的度量标准所定义的,准确率飙升至 94%以上,这使得这成为解决我们着手解决的玩具问题的一次相当令人满意的尝试。合并了上述修改后的笔记本最终版本的要点可以在这里找到。
图 18:修改后的结果更好(作者图片)
开始使用蛋白沉积:在 PyTorch 示例中赢得深度学习图像增强技术
Kaggle CV 比赛获奖秘诀?关于如何使用 Albumentation 库进行图像增强的教程
克里斯汀娜面粉在 Unsplash 上拍摄的照片
无论你是安静地参加 Kaggle 比赛,试图学习一种新的酷 Python 技术,还是数据科学/深度学习的新手,或者只是在这里抓取一段你想复制粘贴并立即尝试的代码集,我保证这篇文章将非常有帮助。
在这篇文章中,我将全面介绍最广泛使用的(2021 年和正在进行的)图像增强库之一,albumination,并给出示例 Python 代码和输出。通过这篇文章,你应该能够对 蛋白 有一个基本的了解,并最终在你自己的工作空间中进行尝试。任何没有(或很少)Pytorch 或 Python 经验或接触图像增强技术本身的人也是受欢迎的。
我个人发现这个库在我的日常使用中对任何计算机视觉相关的任务都非常有用,所以我想,‘为什么我不就此发表一篇文章呢?’?
免责声明:这篇文章不是由albumination赞助的,也不隶属于它。
那么,究竟什么是蛋白沉积?使用起来有什么特点和优势?现实世界的应用有哪些?
什么是蛋白沉积?
在你了解白质化有什么帮助之前,理解图像增强在计算机视觉中的意义是至关重要的。
Ryan Allred 的帖子有一个很好的解释。
深度神经网络,尤其是卷积神经网络(CNN),尤其擅长图像分类任务。最先进的 CNN 甚至被证明在图像识别方面超过了人类的表现(……)图像增强是获取已经存在于训练数据集中的图像并对其进行处理以创建同一图像的许多修改版本的过程。这不仅提供了更多的图像进行训练,而且还可以帮助我们的分类器暴露在更广泛的光照和颜色情况下,从而使我们的分类器更加鲁棒
图像增强样本。图片由 https://github.com/aleju/imgaug 的提供
基本上,它向给定的图像/图片中定制添加各种不同的品种,以增加训练数据集的规模,最终帮助提高深度学习模型的准确性。
Albumentation 是一个工具,可以在将图像/图片放入模型之前,对其进行[ 弹性、网格、运动模糊、移位、缩放、旋转、转置、对比度、亮度等] 定制。
官方蛋白网站称自己为
Albumentations 是一个 Python 库,用于快速灵活的图像增强。Albumentations 有效地实现了针对性能而优化的丰富多样的图像变换操作,并且同时为不同的计算机视觉任务(包括对象分类、分割和检测)提供了简洁而强大的图像增强接口。
albuminations 已于 2020 年正式发表在信息杂志上,标题为albuminations:快速灵活的图像增强 ,目前由来自俄罗斯的 5 名核心团队成员维护,功能更新一致。
为什么要用白蛋白?
与其他图像增强相关包不同的是,
是 快
这个包已经被几个基于 OpenCV 的库(包括 NumPy,OpenCV,imgaug)优化了。
现在你有机会面对最终的老板,而不用痛打所有的中层老板
我的深度学习首选 python 框架是 Pytorch,所以我最初接触了 torchvision 原生提供的torch vision . transforms的用法。torch vision . transforms已经给出了相当扎实的定制增强方法和文档,所以我一直坚持它的产品。
在寻找更好的增强开源库时,我发现了这个 Albumentation 包。我发现它非常快,高度可定制,最重要的是,它只需要 https://github.com/albumentations-team/albumentations
上图是英特尔至强白金 8168 CPU 的测试结果,由 ImageNet 中的 2000 个验证集映像提供。每个单元格中的值表示单个内核中处理的图像数量。你可以看到,在许多转换中,Albumentation 比所有其他库至少快 2 倍。
您可以在albumination 官方 GitHub 中找到有关最新 0.5.0 版本的基准测试的更多信息。
怎么用白蛋白?
教程
对于这个项目的范围,我将介绍白蛋白的主要成分和用途。该代码集主要基于 Albumentations 团队的教程笔记本。我参考了下面的笔记本:
migrating _ from _ torch vision _ to _ albuminations . ipynb
- 在 Google Colab 中安装 Google Drive
我坚持使用 Google Colab 来制作简单/可共享的笔记本原型。他们的 Jupyter 是免费的,你可以使用免费的 GPU!
你可以上传你的照片到你的 Google Drive,然后用下面的代码把 Google Drive 挂载到 Colab。
该单元格将返回以下内容在浏览器中转到该 URL。点击 URL 后,您可以检索授权码。复制粘贴这段代码,然后按回车键和就可以了!**
**from google.colab import drive
drive.mount("/content/gdrive")**
作者照片。认证后的结果
此外,我将导入本教程所需的所有其他 Python 库
为了演示的目的,我用了一张意大利威尼斯的街景照片,这是我前阵子去欧洲旅行时拍的。
**from PIL import Image
import time
import torch
import torchvision
from torch.utils.data import Dataset
from torchvision import transforms
import albumentations
import albumentations.pytorch
from matplotlib import pyplot as plt
import cv2
import numpy as np**
作者照片。意大利威尼斯的一条街道
原始火炬视觉数据管道
我通常使用 PyTorch 和 Torchvision 创建一个数据加载器来处理图像数据管道。在下面的代码中,它
创建一个简单的 Pytorch 数据集类
- 调用图像并进行转换
- 用 100 个循环测量整个处理时间
- 首先,从 torch.utils.data 中获取 Dataset 抽象类,并创建一个 TorchVision Dataset 类。然后我插入图像,并使用 getitem 方法进行转换。此外,我使用
total_time = (time.time() - start_t
来测量需要多长时间
然后,我们将图像的大小调整为 256x256(高重),并随机裁剪为 224x224。然后以 50%的概率应用水平翻转,转换为张量。输入文件路径应该是你的图片所在的 Google Drive 的路径。*
**class TorchvisionDataset(Dataset):
def __init__(self, file_paths, labels, transform=None):
self.file_paths = file_paths
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.file_paths)
def __getitem__(self, idx):
label = self.labels[idx]
file_path = self.file_paths[idx]
# Read an image with PIL
image = Image.open(file_path)
start_t = time.time()
if self.transform:
image = self.transform(image)
total_time = (time.time() - start_t)
return image, label, total_time**
然后,我们计算从 torchvision_dataset 中提取样本图像并转换它所需的时间,然后运行 100 次循环来检查它所需的平均毫秒数。
**torchvision_transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.RandomCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
])
torchvision_dataset = TorchvisionDataset(
file_paths=["/content/drive/MyDrive/img5.jpg"],
labels=[1],
transform=torchvision_transform,
)**
在我的 Colab 环境中,Resize+RandomCrop+RandomHorizontalFlip 的一百次循环大约花费了 40 ms,最后一张图像花费了 224x224,如您所见。你也可以看到翻转发生在第 100 张图片上!
**total_time = 0
for i in range(100):
sample, _, transform_time = torchvision_dataset[0]
total_time += transform_time
print("torchvision time/sample: {} ms".format(total_time*10))
plt.figure(figsize=(10, 10))
plt.imshow(transforms.ToPILImage()(sample))
plt.show()**
沉淀数据管道
现在,我将重构从火炬视觉到蛋白质合成的数据管道
类似于 TorchVision,我们创建了一个 Albumentations 数据集类。
现在在蛋白沉积中创造一个转变。在这个例子中,你可以发现一个小小的语法差异,那就是 Torchvision 的 RandomHorizontalFlip() 通过 HorizontalFlip() 在 Albumentation 中产生相同的结果
**class AlbumentationsDataset(Dataset):
"""__init__ and __len__ functions are the same as in TorchvisionDataset"""
def __init__(self, file_paths, labels, transform=None):
self.file_paths = file_paths
self.labels = labels
self.transform = transform
def __len__(self):
return len(self.file_paths)
def __getitem__(self, idx):
label = self.labels[idx]
file_path = self.file_paths[idx]
# Read an image with OpenCV
image = cv2.imread(file_path)
# By default OpenCV uses BGR color space for color images,
# so we need to convert the image to RGB color space.
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
start_t = time.time()
if self.transform:
augmented = self.transform(image=image)
image = augmented['image']
total_time = (time.time() - start_t)
return image, label, total_time**
执行相同的图像转换,获得平均时间,并可视化结果。
**"""
torchvision_transform = transforms.Compose([
transforms.Resize((256, 256)),
transforms.RandomCrop(224),
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
])
"""
# Same transform with torchvision_transform
albumentations_transform = albumentations.Compose([
albumentations.Resize(256, 256),
albumentations.RandomCrop(224, 224),
albumentations.HorizontalFlip(), # Same with transforms.RandomHorizontalFlip()
albumentations.pytorch.transforms.ToTensor()
])**
令人惊讶的是,只用了 1.77ms,比 Torchvision 快了约 23 倍!它甚至比我们从官方基准文档中看到的计算差距更大,而且裁剪区域似乎也略有不同。
**# Same dataset with torchvision_dataset
albumentations_dataset = AlbumentationsDataset(
file_paths=["/content/drive/MyDrive/img5.jpg"],
labels=[1],
transform=albumentations_transform,
)
total_time = 0
for i in range(100):
sample, _, transform_time = albumentations_dataset[0]
total_time += transform_time
print("albumentations time/sample: {} ms".format(total_time*10))
plt.figure(figsize=(10, 10))
plt.imshow(transforms.ToPILImage()(sample))
plt.show()**
白蛋白的应用
如你所见,它非常快,速度很重要。
在代码竞赛中,如果可以减少图像处理中的计算瓶颈,就可以将更多的资源用于其他部分(模型拟合、超参数调优等)。
- 在现实世界的行业中,生产数据库中新图像的流入量可能很大(即每秒 1000 幅图像)。想象开发一个实时深度学习模型。在该模型中,处理图像的快速方法至关重要,这可能会影响用户体验并最终影响收入/利润。
- 对于你的学习目的来说,接触最新的和表现最好的技术技能是有帮助的,这在你建立自己的项目时可能是有用的,也许在找工作(例如简历)时也是有用的
- 更复杂的例子
最后,我将展示如何使用函数中的函数进行增强,我个人认为这是最复杂的,但在蛋白沉积中非常有用
它在调整大小和随机裁剪方面与之前的代码集有相同的代码。 OneOf 在括号内随机选取一个列出的变换。我们甚至可以把发生的概率放在函数本身中。例如,如果其中一个([…],p=0.5),它以 50%的几率跳过整个变换,并以 1/6 的几率随机选取三个变换中的一个。
**albumentations_transform_oneof = albumentations.Compose([
albumentations.Resize(256, 256),
albumentations.RandomCrop(224, 224),
albumentations.OneOf([
albumentations.HorizontalFlip(p=1),
albumentations.RandomRotate90(p=1),
albumentations.VerticalFlip(p=1)
], p=1),
albumentations.OneOf([
albumentations.MotionBlur(p=1),
albumentations.OpticalDistortion(p=1),
albumentations.GaussNoise(p=1)
], p=1),
albumentations.pytorch.ToTensor()
])**
我让它从水平翻转、旋转、垂直翻转中随机选择,又让它从模糊、失真、噪声中随机选择。所以在这种情况下,我们允许 3x3 = 9 种组合。
来自定义的图像变换的五个样本如下:
**albumentations_dataset = AlbumentationsDataset(
file_paths=["/content/gdrive/My Drive/img5.png"],
labels=[1],
transform=albumentations_transform_oneof,
)
num_samples = 5
fig, ax = plt.subplots(1, num_samples, figsize=(25, 5))
for i in range(num_samples):
ax[i].imshow(transforms.ToPILImage()(albumentations_dataset[0][0]))
ax[i].axis('off')**
我们看到旋转 360,水平翻转,垂直翻转被应用,不同的失真被应用到所有遮光罩下的图像。
除了我所解释的,还有许多例子。请参考官方营养强化网站或营养强化 Github 来应用最适合自己需求的强化!
额外资源
注 您还可以找到 Jupyter 笔记本,其中包含了 albumination:ka ggle 竞赛的真实用法
孟加拉语。AI 手写字素分类是一个代码竞赛,给定一个手写孟加拉字素的图像,对图像中的三个组成元素进行分类。这是一个图像分类问题,Albumentation 用于转换最初存在于拼花文件中的数万张图像,大小为 GB。
GitHub: 孟加拉语。AI 手写字素分类大赛
结论
总之,我介绍了图像增强技术,Python 中的 Albumentation 库,教程中有示例代码。为了这个项目,这个实验只使用了一张图像,但是可以发现速度有了很大的提高。白蛋白提供了各种各样的转换,所以我强烈推荐我的读者从今天开始使用它。
有关学习其他数据科学主题的更多详细信息,下面的 Github 存储库也会有所帮助
生产中的 AWS sage maker
展示如何使用 Amazon SageMaker 及其 ML/DL 算法解决业务问题的端到端示例。
- PySpark
函数和实用程序,带有真实世界的数据示例。可以用来构建一个完整的数据建模的 ETL 过程 - 推荐系统
py torch 中推荐系统的生产级实现。克隆 repo 并通过运行“main.py”开始训练 - 自然语言处理(NLP)
Python 中几种自然语言处理方法的完整实现示例。按照学习的复杂程度排序 - 关于作者
贤俊是一名拥有统计学学位的数据极客。他喜欢分享数据科学/分析知识。在 LinkedIn 上给他发消息。
参考: (1)瑞安·奥尔雷德,https://towardsdatascience . com/AWS-glue-and-you-e2e 4322 f 0805
(2)霍亚 012,https://hoya012.github.io/blog/albumentation_tutorial/
(3)蛋白发酵官方文档,https://albumentations.ai/docs/
Reference: (1) Ryan Allred, https://towardsdatascience.com/aws-glue-and-you-e2e4322f0805
(2) Hoya012, https://hoya012.github.io/blog/albumentation_tutorial/
(3) Albumentation Official Docs, https://albumentations.ai/docs/