用你自己的机器学习算法找到文本相似之处
只需几行代码和一点点线性代数,我们就可以创建一个强大的 ML 算法,轻松地将相似的文本片段聚集在一起。
首先,有大量的材料专注于处理文本数据,并使用各种分类算法来提供相似性和/或聚类。我们将使用一种方法来精确计算与我们任意选择的文档相似的文档。相似性评价基于“”最重要的词语的文档及其相关语料库。
为什么?您曾经使用简单的分类或回归实现来对数据进行分类吗——非常肯定您使用过。今天,我们来看看记录非常完整的方法,它们具有很高的准确性和稳定的性能。不过,我发现对我个人的学习曲线至关重要的是,实现类似的算法和概念来理解基本思想。记住这些知识,你将很难理解更深层次的概念。一步接一步。
我们将在这里做什么:
- 从 HTML 和 CSV 文件导入数据——我们使用的是 Beautifulsoup
- 清洗数据
- 使用正则表达式、NLTK 和 concentration 创建单词包
- 对字典中的数据进行排序和分类
- 创建单词到矢量的实例
- 将数据合并成一个(稀疏)矩阵
- 识别相关文本元素
- 喝一杯有机茶,为自己感到骄傲
如果这是您在“使用文本世界”中的第一次冒险,我认为这里的这些文字将是一个很好的开始,让您了解仅用几行代码就能做些什么。关于文本相似性,我个人推荐我最喜欢的出版物“文本相似性:估计两个文本之间的相似程度”,这可以在medium.com找到。如果你想深入研究文本处理程序。
现在让我们关注一个非常简单的实现,仅用几个词来描述一个文档的特征,并检查这是否是在彼此之间比较文档/文本的合适的度量。
《不是一袋文字》来源
对于我们的实验,我们将处理与计算机和数据科学有关的各种领域,换句话说,期待巨大的乐趣!在概述的步骤过程中,我们将使用几个库作为快捷方式,例如,我们将使用预定义的英语停用词来“过滤”我们不能用于进一步分析的词,我们将使用库来处理 HTML,我们将使用标准数学库。
为了确定文本元素之间的相似性,我们将经历以下步骤:
***0.** Define the procedure of evaluating word importance
**1.** Import the data we would like to analyze
**2.** Clean data in order to being able to process paragraphs, phrases and words without running into issues
**3.** Use the cleaned data to create bag of words
**4.** Implement the tf_idf algorithm (adapted)
**5.** Calculate frequencies per bag vectors
**6.** Store data in a matrix
**7.** Calculate similarities
**8.** Analysis*
我们将通过分析两个不同的数据集来测试我们的方法:(1) IMDB 的评论集以及(2) Reuters -21578 数据集[1],这两个数据集都可以很容易地在网上找到并下载到您的机器上。为了正确起见,我根本不隶属于 IMDB 或路透社。
凭直觉,我们可以假设重要的单词对文档来说是某种“特殊的”,所以如果我们计算文档中的所有单词,而忽略对文档值没有贡献的单词,如(is、has、will 等。我们可能会在文档中找到重要的单词。
我最初尝试的是统计单词,并认为最常用的单词是最重要的(这种方法最多是的)。为什么这在某种程度上起作用是很简单的,我们清理了文本并删除了(非常频繁出现的)停用词,所以自然地我们会以频繁出现的词结束,这些词可能是重要的。这个想法有一个很好的理由是有缺陷的:那些绝对不重要,但是没有通过前面的过程(停用词清理)过滤的词可能会保留在文本中,然后被认为对我们的分析很重要。
我们将继续用代码片段覆盖必要的步骤,完整的代码可以在 Github 上找到。
***0。*基本思路,“逆文本频率”
例如,在我们谈论电影评论的情况下,电影可能经常出现(有趣的事实:我们即将分析电影评论)——然而,“电影”的出现不太可能为我们提供任何可靠的信息,即两个文本片段是否可能相似。换句话说,如果我们依赖“电影”,我们最终会有太多的相似之处。
词频-逆文档频率,简称 tf-idf,是评估单个单词对语料库的重要性的常用方法。一般来说,这可以概括为三个计算[2,3]。请注意,tf-idf 空间中有相当多的变化(特别是在计数规范化方面)——我尝试了一些变化,并选择了提供良好总体结果的方法。
我们多久能在文档 D 中找到术语 t ?由于长文档可能导致这个问题的扭曲(因为术语可能出现得更频繁),我们考虑文档中一个术语 t '的最大频率,以便归一化 D 中的#t。
D 中的项 t 的数量除以 D [2]中的项 t '的最大频率
2.在整个语料库的多少个文档中,我们找到了术语 t ?(在所有被考虑的文档中出现的术语如果在那些被考虑的文档中多次出现,则不太重要)
N =文件总数 D;{d 的 D 元素,其中 t 项是 D 的元素}
3.在最后一步中,给定文档 D 中的词 t 的权重被计算为上述两个计算的乘积:
为什么我们需要对数函数呢?这是一种自然的方式,允许我们限制大量事件的重要性。出现的次数越多,如果按对数计算,重要性的变化就越不明显。
我们将使用前面描述的 ft-id 案例。对于这种方法,我们将考虑所有可用的文档,而不是只计算单个文档中的单词(这是我们首先想到的,如何解决这个问题)——这当然需要更多的 CPU 内存来进行计算,但代价是希望更加准确。
我们已经通过了数学运算,大部分都通过了——太好了!我认为这是一个很好的时间休息一下,回顾一下我们到目前为止所看到的。至少这是我在这里做的。现在让我们来谈谈更多的代码🐍。
1。导入数据
我们的开始很简单,我们将导入我们的 IMDB 和 Reuters 数据:
IMDB
*data = pd.read_csv('.../PATH/imdb.csv')*# limit the number of records, avoid loading times while tweaking*
NO_OF_ENTRIES = len(data)//8
**imdb = data.review.iloc[:NO_OF_ENTRIES]***
路透社
在这种情况下,我们不能依赖可靠的 pandas 功能,但是 bs4 允许我们毫不费力地提取数据,只需 n🍦。有一件事可能会立即映入你的眼帘,那就是" soup-functions" 确实经常看起来像典型的 regex 函数。如果需要,这个提示可以帮助您浏览文档。
对于我们之前的定义来说,重要的是我们能够正确地清理数据。这将进一步允许我们将句子、段落和最终文档压缩成一组独特的单词。(我们没有特别介绍词干,但是这可以在某种程度上改进我们的方法——如果感兴趣的话,请看这里的和【4】)。
2。& 3。清理数据,把单词装进他们的包里
从 tf、idf 公式推导出,我们需要收集所有(干净的)单词,确定这些单词在文档中出现的频率以及这些单词在所有文档中出现的最大频率。为了删除停用词,我推荐 nltk 的停用词,它在许多语言中都有。
*#Note the global dicts:
**maximum_per_document** -> which is the denominator for the first equation
**number_docs_containing_term** -> which is the denominator for the second equation*
只是一个非常基本的数据过滤方法(使用正则表达式)
我没有使用过,因为我们的基本实现的结果很好,但是只需要几行代码,就可以了。如果我们选择所有我们找到(并过滤)的单词,记下它们,并根据单词出现的次数来调整后者的大小,我们可以生成一个单词云,如下所示:
《星球大战评论》一词云
4。TF-IDF 算法
由于我们使用了上述函数来清理和过滤数据以及设置计数,因此我们将继续实施我们实验的核心功能,即 tf-idf 算法:
TF IDF 主要使用字典
利用我们的 tf-idf 算法,我们现在可以决定只考虑有限数量的单词,只考虑每个文档中计算出的得分最高的 n 个单词[3]。这个 n 是任意的,n 越大,我们的相似矩阵就越稀疏——记住这一点。
为了计算相似性,我们需要一个参考向量。在遍历所有文档、清理它们并计算字数时,我们将
- 计算 tf_idf 分数,以及
- 创建一个参考向量—这是一个由所有相关单词(每个文档 n 个单词)组成的向量。自然,相似的文档越多,我们的向量就越小。预计它会很大。
5。计算相似度
我们接下来要做的是计算袋子相似度,其中袋子由它的 n 个顶部单词表示。所有顶部的单词都聚集在一个单词向量中。我们将为每个包创建向量(迭代过程),在下一步中,我们将把所有向量叠加到一个矩阵中。
6。适当存储数据
我们已经做了相当多的工作,以便处理和组织数据,使我们能够非常接近我们分析的最后步骤。在堆叠我们的向量之后,我们找到一个稀疏矩阵,它只在对角线周围是密集的(这很有意义,但是在 7 下更多。计算相似度)。让我们先做一些理智检查。
***# for our matrix m
np.where(m.toarray()[0] > 0)
# n top values:
(array([ 52, 803, 1151, 1778, 1993], dtype=int64),)***
让我们检查路透社和 IMDB 的矩阵(图限于 25000 条评论):
Matrix m 在路透社数据下看起来——由于大量的热门词汇
矩阵 m 在 IMDB 数据[:25,000]下的样子—密集
7。计算相似度
计算相似性是一项有趣的任务,线性代数提供了一种非常直接的方法来计算相似性:我们感兴趣的是两个向量 A 和 B 之间的余弦角,这两个向量指向同一方向越近,它们的值就越接近 1:
余弦相似度——谷歌上出现的第一张图片;) [5]
在我们的最后一步中,我们将把我们的矩阵值与矩阵中的所有其他值相乘(如果我们把一个向量与它本身相乘,则相似性是 1),我们把这个相似性矩阵称为 m_d_m 。正如我们可以看到的,有一个清晰的模式,我们可以从中找到明显的相似之处——如果我们需要将它们放在一起,这将是一个完美的聚类任务。
在下图中,我们将检查路透社的数据,原因很简单:路透社的数据是每日新闻。这意味着我们当然期望某些相似的模式,然而新闻覆盖了许多不同的领域,自然会有更广泛的词汇。如果我们对电影评论使用相同的情节,我们基本上会得到一个巨大的蓝色正方形(由于密度)。
我们的路透社矩阵 m_d_m 包含非零值**
8。分析
在我们的任务中,我们的目标是找到与我们选择的文档相似的文档。我们使用一个简单的迭代来查找所有至少 x% 相似的相关文档,其中 x 再次被任意定义。我得出的结论是,0.5 左右的相似性非常好。
IMDB —与路透社数据集相比,如果我们只选择文本中的 n 个重要单词,我们可能会得到相当密集的结果。这可以解释为这样一个事实,评论,好的或坏的,很可能包含许多相似的词——这导致了巨大的密集矩阵!这将我们带到一个非常敏感的点:我们可以选择更多的单词(一个更大的 n),但是计算将变得相当消耗内存。让我们在给定不同参数的情况下进行几次比较:
***n=10
[**7054**] vs [**11311**] vs [**7637**] ~ similarity 0.6***
似乎有些用户发明了自己写评论的捷径😏。也许这只是我,但我真的觉得这很有趣:
对抗
对抗
我之前提到过“词干”是查找相似单词的一个有趣选项,在我们的例子中,我们可以清楚地看到为什么:
我仍然喜欢它|我仍然喜欢它
这两个不同于我们的代码,享受和被享受是两个不同的术语,因此它们的重要性可能完全不同。正如我们在这三个片段的比较中所看到的,很可能“享受[ed]”不在我们的 n 大热门词汇中。
如果考虑到我们的下一个测试场景是相当令人印象深刻的,并表明我们的算法必须至少在某些点上工作。由于我们的 IMDB 数据集没有而不是提供电影本身的任何参考(除非明确提到),我希望找到属于彼此的评论(连续实验的潜在参考——聚类)。还要注意的是,即使这部电影被提及,也只是被提及了几次,因此它可能不会被视为一个重要的词,也不会被列入我们的 n 大词汇中。****
在下面的例子中,我们的算法将两个评论匹配在一起,而两个都提到了电影的原始日文标题,一个提到了英文电影标题。
***[8745] vs. [18038]***
对抗
好吧,让我们在包含路透社新闻数据的稀疏矩阵中检查我们的发现。
路透社——浏览结果,我们可以在 m_d_m 中看到,数据聚集在各种条目周围。当更详细地研究这一点时,我们发现这是由于数据包含许多简短的股票价格更新(看起来非常相似)。对于这些更新,我们将在矩阵中找到许多类似的条目。这里有一个例子,我假设 Shr、cts、Net、Revs 可能被视为对我们的算法“重要”:
***# example of a "very similar" document
'Shr 24 cts vs 15 cts
Net 1,520,797 vs 929,017
Revs 5,268,486 vs 2,617,995
Reuter'***
如果我们采用更严格的方法,比如 99%的相似度,我们几乎不会期望任何结果(因为文档与其自身匹配,总是 1,被排除),但是我们确实找到了一个。事实证明,这是我们数据中的重复和非常相似的文本片段。很公平。
*****# data point 3 and 15 are perfect duplicates**
BankAmerica Corp is not under
pressure to act quickly on its proposed equity offering and
would do well to delay [...]***
总体而言,路透社的数据似乎更具挑战性。这一方面是由于各种金融术语和缩写(这将占用我们“重要”词汇的一部分)另一方面,看起来相似的文本不一定谈论相似的事情。为了只获取可能在内容方面有关联的文本,我将忽略相似性值大于. 55 的数据(因为这将是看起来非常相似的财务数据)。
***[915] vs [660] ~ similarity .39***
对抗
尽管这些收件人邮件分享了它们的大部分单词,但它们的相似性得分远低于我的预期——特别是关于我们在 IMDB 数据集中可以达到的得分。
先不说:奇异值分解
由于我们已经计算了一个奇异矩阵,识别出与其他文档有最多共同点的顶级文档可能会很方便*(因此,如果我们也检查了这个,这些文档应该在同一个集群中)。***
***from scipy.sparse.linalg import svds
U, Sigma, V_T = svds(m_d_m, k=1, which='LM', return_singular_vectors=True)sorted_U = np.argsort(abs(U.reshape(m_d_m.shape[0])))[::-1][:10] #**top 10 only*****
tldr
这个简单的算法允许我们找到相似的文本(例如,我们可以看到,可以很容易地找到重复的文本),但是文档变得越复杂,文档之间的差异越多,计算的代价就越大。由于我们需要遍历整个数据集,对重要单词的说明和计数过程,算法的资源需求会随着每一个额外的记录而大量增加。
如果你觉得这篇文章有帮助,我会很感激“关注”🫀,直到那时:
下次见。
(注意安全!)
[0]链接完整代码:https://github.com/guenter-r/medium/blob/master/tf_idf.py
[2]维基百科(TF-IDF):https://en.wikipedia.org/wiki/Tf%E2%80%93idf
MSalnikov 对一个三个句子的实验做了一个非常好和清晰的解释👍:https://medium . com/@ MSalnikov/text-clustering-with-k-means-and-TF-IDF-f 099 BCF 95183
https://en.wikipedia.org/wiki/Stemming
[文字云图片]一个“星球大战评论文字云”,创建于wordclouds.com
# NLP # corpus # numpy # bs4 # beautiful soup # examples # github # TF-IDF # data science # tokenize # sk learn # python # R # rlang #词干#wordcloud
用 Python 找到当天最高的移动(隐藏)股票
图片来自 unsplash 。
有更多的股票不只是 SP500!在本文中,我们将探索揭示快速移动的小型创业板股票的 Python 代码…
股票市场是一个瞬息万变的地方,尤其是在这些动荡时期。虽然我们经常听说最受欢迎的股票(所谓的 SP500),但还有许多其他股票。有些小,有些快速上涨,有些是新的 IPO,有些是快速崩溃…在这篇文章中,我将分享一些我编写的有用的 Python 代码,以深入研究最不为人知的股票,并找到那些快速移动/快速上涨的股票…
我们将利用一个名为 yfinance 的图书馆,它将为我们提供历史库存数据并进口熊猫。
# imports
!pip install yfinance
import yfinance as yf
from pandas_datareader import data as pdr
import pandas as pd
由于我们不只是想探索最知名的股票,我们将加载所有纳斯达克股票的完整列表:
# list all stocks
url = “ftp://ftp.nasdaqtrader.com/SymbolDirectory/nasdaqlisted.txt"
df=pd.read_csv(url, sep=”|”)
print(df.head())
print(df['Symbol'].head())
print(len(df['Symbol']))
这为我们提供了一个包含 3549 个股票代码的变量(df )!
那么,我们如何获得今天的高推动者?让我们从检索列表中每只股票的最近历史开始,并将其存储在movementlist
中
我首先定义了一个助手函数,它允许我们通过错误检查从数据帧中快速查找值。
def lookup_fn(df, key_row, key_col):
try:
return df.iloc[key_row][key_col]
except IndexError:
return 0
我回顾 5 天前。您可以在命令hist = thestock.history(period=”5d”)
中更改时间段
我们填充运动列表(股票代码,在一段时间内的低,在一段时间内的高)。
movementlist = []for stock in df['Symbol']:
# get history
thestock = yf.Ticker(stock)
hist = thestock.history(period="5d") # print(stock) low = float(10000)
high = float(0) # print(thestock.info) for day in hist.itertuples(index=True, name='Pandas'): if day.Low < low:
low = day.Low
if high < day.High:
high = day.High
deltapercent = 100 * (high - low)/low
Open = lookup_fn(hist, 0, "Open") # some error handling:
if len(hist >=5):
Close = lookup_fn(hist, 4, "Close")
else :
Close = Open if(Open == 0):
deltaprice = 0 else:
deltaprice = 100 * (Close - Open) / Open print(stock+" "+str(deltapercent)+ " "+ str(deltaprice))
pair = [stock, deltapercent, deltaprice]
movementlist.append(pair)
现在我们已经填充了我们的股票移动列表,我们可以继续过滤出最高的移动。如果您只想快速获得那些移动超过 100%的人的列表:
for entry in movementlist:
if entry[1]>float(100):
print(entry)
如果我们有兴趣更详细地了解这些股票,我们需要更多的信息,比如它们所属的行业。下面是我们如何正确清理列表:
# High risers:
def lookup_stockinfo(thestock):
try
return thestock.info
except IndexError:
return 0cutoff=float(80)for entry in movementlist:
if entry[2]>cutoff:
print("\n"+ str(entry))
thestock = yf.Ticker(str(entry[0])) if entry[0]=='HJLIW':
print("no info")
else:
a = lookup_stockinfo(thestock)if a == 0:
print("no info")
else:
if a is None:
print("no info")
else:
if a == "":
print("no")
else:
print(a)
print('Up '+ str(entry[2]) + "%")
print(str(a['sector']))
print(str(a['longBusinessSummary']))
print("year high "+ str(a['fiftyTwoWeekHigh']))
结果是一个详细的概述,其中包含过去 5 天中涨幅最大的股票的一些信息。非常有趣的检测一些快速移动的股票,为投机者或只是为任何人想找到一个隐藏的宝石股票!
使用 Python OOP 找到两组坐标的交集并按颜色排序
解决两个编程问题,一个用排序算法,另一个用 Python 中的 OOP。
资料来源:马丁·w·柯斯特的《Unsplash》
这篇文章是关于一些编程练习的。如果你是一个初学者,正在学习 Python 中的数据结构和面向对象编程,这可能对你有帮助。我将解决两个问题,并尽可能多的解释。我假设您了解 Python 编程基础和 OOP 基础。我是从 Coursera 的课程《算法》第一部分得到这两个问题的想法的。
问题 1
开发一种算法,它采用两个坐标列表并返回它们的交集。我们需要找到两个列表中的共同坐标。
解决方案
解决这个问题有 4 个步骤
- 连接两个列表,并从两个列表中生成一个列表。
- 首先按 x 坐标,然后按 y 坐标对这个合并列表进行排序。因此,如果有任何共同的项目,他们将并排。
- 然后返回重复的坐标。
下面是完整的代码。函数“concArray”将连接列表。函数“sortList”将对坐标进行排序。如果两个连续坐标相同,函数“clash”将返回。
class Intersection():
def __init__ (self, sets):
self.sets = setsdef concArrays(self):
self.sets = self.sets[0] + self.sets[1]
return self.setsdef sortList(self):
self.sets = sorted(self.sets, key=lambda x: x[0])
return sorted(self.sets, key=lambda x: x[1])
def clash(self):
return [self.sets[i] for i in range(0, len(self.sets)-1) if self.sets[i] == self.sets[i+1]]
让我们检查算法是否正常工作:
sets = [[(2,4),(5,3),(2,6),(6,2),(4,9)],[(4,9),(10,8),(9,3),(5,3),(1,7)]]
inter = Intersection(sets)
inter.concArrays()
inter.sortList()
print(inter.clash())
它返回[(4,9),(5,3)]。如果你注意到我们的集合变量,这是两个公共坐标。由于我们的列表不太大,我们可以通过查看来检查。
问题 2
给定 n 个桶的列表,每个桶包含蓝色、白色或红色卵石。按照红、白、蓝的顺序按颜色排序。
解决方案
可能有不同的解决方法。我展示了两个解决方案。第一个是使用排序算法。这里我使用了插入排序。任何其他排序算法都将以同样的方式工作。
以下是步骤:
- 制作一个字典,其中颜色是关键字,值是整数。
- 在排序算法中,比较两种颜色时使用字典中的值。
以下是完整的代码:
def sortColor(a):
color = {'red': 1, 'white': 2, 'blue': 3}
for i in range(1, len(a)):
value = a[i]
hole = i
while (hole > 0) and (color[a[hole -1]]>color[value]):
a[hole] = a[hole -1]
hole = hole -1
a[hole] = value
return a
使用以下颜色列表检查该算法:
print(sortColor(['red', 'white', 'red', 'blue', 'white', 'blue']))
输出是完美的。请尝试一下。
我还想展示一个两行代码的解决方案。如果你知道如何使用 lambda,这是给你的。
def sortColor1(a):
color = {'red': 1, 'white': 2, 'blue': 3}
return sorted(a, key=lambda x: a[color[x]], reverse=True)
我希望它有帮助。
附加阅读:
为你所有的兼职项目找时间
怎么会?尽可能少做你觉得舒服的事情,以取得最小的进步
达里娅·图马诺娃在 Unsplash 上的照片
如果你像我一样,你有一长串想做的事情,但是你从来没有找到时间开始做。这些可以是任何事情,从编码项目到家庭想法,演奏乐器,写作,阅读,锻炼。
任何你希望自己经常养成的习惯,但你没有开始,因为它们会占用你每周很多时间,而你没有那样的时间。
如果你已经很有效率了,而且一周没有剩余时间,你就不需要这篇文章了。很明显,你可以随心所欲地支配自己的时间,没有时间去做兼职,这完全没问题。
但是如果你有项目想法,倾向于拖延,有时觉得你不知道时间去了哪里,或者总的来说觉得你可以更好地利用你的时间,请继续阅读:)
我有什么资格谈论时间管理?我不是生产力专家(因为没有这样的东西),但是我多年来一直在管理我的时间和生产力,我发现了一个对我和我推荐的一些人非常有效的系统。如果有兴趣的话,我会再发一个帖子。
但是我遇到的一个难题是找时间做兼职项目,理想情况下我每周会花很多时间去做,当然我没有时间。因此,他们不断积累,直到几个月前,我决定尝试一些东西。
这个想法
就我而言,这些是我潜在的副业:
- 做算法练习(破解代码面试书,hackerrank),明确定义的练习
- 做 freecodecamp 课程,定义明确的部分和练习
- 阅读 NLP 文件
- 制作一个电报机器人
- 练习一下长笛
- 漫长的等
正如你所看到的,这是我已经很忙的大学、工作和生活日程之外的一大部分。以前,我会解决其中一个问题,但它们很长(尤其是前两个),阅读论文是一项永无止境的任务,事情会妨碍我,我会停下来。所以我是这么想的。
我可以每周花 1 小时学习算法,每周花 1 小时学习 freecodecamp,我可以每周读一篇论文。
我想:我能花在这些任务上的最少时间是多少,这样我才能取得一些小的进步,并且仍然感到满意?在我的情况下,通常情况下,一个小时足以完成一项运动,或者大部分时间。一周一篇论文是可行的。每天吹笛子 15 分钟就够了。
花这么少的时间在算法书上意味着我不会在几个月内完成它,我不会在几个月内完成 freecodecamp 课程,我的论文清单也是如此,但这些都不紧急。这样,每周,我都在许多不同的事情上取得小小的进步。
分配最少的必要时间,让你的项目取得微小但有意义的进展。
现在,我们该怎么做呢?
物流
我建议你写一份你想开始的兼职项目的清单。浏览一遍,分配一周中你觉得最少的时间。
每周 30 分钟的写作,每周 1 次锻炼,每天 5 分钟的阅读,每天 5 分钟的锻炼,让这些时间变得微不足道。你越挣扎,你投入的时间就越少。无论如何,你肯定能坚持 5 分钟!在那之后,你可以停下来,感觉很有成就感。谁知道呢,也许开始后你会想做更多。
我在我的电脑上有一个文件,因为我在一周内改变了很多东西,但你也可以在笔记本上做。
在你的文件/表格中有一个“待办事项”清单,明确规定任务,无论是时间还是内容。每天晚上睡觉前回顾它并思考:这些事情中的哪些我明天可以完成?我会度过忙碌的一天还是更轻松的一天?哪里有时间?以某种方式标记这些任务,并且现实一点。
第二天,把完成这些任务的 5 到 30 分钟作为你的任务。早餐前,休息时,当你觉得自己在拖延的时候。去做吧,不会花很长时间的。
晚上,不管你有没有做到,再次坐下来重新评估。把你做过的任务移到另一个清单上,比如“完成”,然后把你认为明天可以做的任务再做一次标记。
在这一周里,你会将更多的任务移到“完成”列表中。周日晚上,也许你会有一个空的“待办事项”清单,也许没有。回顾你的一周,你满意吗?你经常拖延吗?你能以某种方式完成剩下的任务吗?更新下周的‘待办事项’清单,不要放太多事情。
结论
重要的:这个系统没有失败,你和你自己一起踏上这个旅程。如果你觉得你不能做得更多,那么你就不能做得更多。没人看,这只是给你的。如果你没有完成你的清单,删除一些项目。从小处着手,尝试。
周日看到一个(几乎)空的“待办事项”清单和一个满满的“已完成事项”清单令人无比满足。但更重要的是,能在所有这些项目上取得一些进展,无论多小,感觉都棒极了。因为有总比没有好。
我鼓励你尝试这个方法的想法,按照你的意愿改变它,让它为你工作,不要过度劳累自己。我几个月前开始,有些周比其他周忙,但我正在稳步前进,我非常高兴。
如果你想告诉我你过得怎么样,或者和我聊些什么,你可以在推特上找到我。感谢阅读!
找到你作为数据科学家的第一份工作
成为数据科学家并拥有美好职业生涯的 6 个步骤。
数据科学确实是一个美妙的职业特别是如果你喜欢摆弄数据,思考正在发生的事情并解决问题。在本文中,我将介绍如果你刚刚开始,如何找到你的第一份数据科学工作。
成为一名数据科学家。通过数据科学工作面试。
构建 Github 组合
首先是获得一些实用技能。
- 你需要学习统计学和线性代数来理解基本的数据科学概念,如随机变量、分布、概率和矩阵运算。所以你的第一步应该是学习这些方面的材料,做一些练习,直到你对数学部分感到舒服为止。没有太多,但你真的需要它。
- 然后你需要拿起 Python。安装 Anaconda,打开 Jupyter 笔记本,开始玩一些你在互联网上找到的。试着打开。csv 文件,加载到熊猫数据框,尝试可视化你在做什么。
- 最终得到一个数据集,你可以利用它来解决一个实际问题。找一些你会感兴趣的东西。如果你喜欢音乐,试着去找音乐资料。谷歌“音乐数据集”,然后开始搜索。尤其是 Kaggle 是一个很好的数据集资源,网上有大量由研究人员和数据科学家准备的数据集。
- 让一个数据集开始修补它,尝试回答一些简单的问题,比如这个数据如何表现,什么是异常等等——这些问题将取决于你正在处理的数据。这里最重要的是要有 2-3 个你能清楚回答的具体问题。
- 解决一个问题后,回答你的问题,你就可以把所有东西上传到 Github 了。创建您自己的存储库并共享它。这是向世界展示你技能的最好方式。
- 现在重复问题解决-Github 三次,你就准备好下一步了。
这些步骤可能需要你几周到几个月的时间,所以不要担心时间,要有耐心。数据科学是一场马拉松。您应该学习的概念包括:
分类 :我们有 2 个或者更多的类别(标签),我们想根据这些标签对物体进行分类。我们在这里讨论监督学习和标准技术,包括:KNN,朴素贝叶斯,决策树,XGBoost,神经网络。点击阅读更多关于分类的信息。
:我们没有任何标签,但我们仍然想对我们的数据进行分类。我们通过不同的相似性度量对数据进行聚类,从而创建标签。我们在这里讨论的无监督学习和标准技术包括:k-means 和 DBSCAN。点击这里阅读更多关于集群的信息。
神经网络 本身就是一个独立的话题。它们背后的基本思想是将一个问题简化成可以被“神经元”单独处理的更小的部分。我将介绍像 Keras 和 Tensorflow 这样的基本框架,然后还将讨论 MNIST 和其他一些很好的问题。在这里阅读关于神经网络的内容。
降维 如果你想可视化数据或者更好的理解数据,是必须的。有时,您只想在 2D 绘制 4D 数据,然后必须对其进行转换,以捕捉信息的本质。标准技术包括主成分分析和 SVM。看这里。
可视化数据 对于数据科学的商业应用来说很重要。最后,你想把你的发现传达给其他人,最好的方式是用一个漂亮的图表展示给他们,每件事都很清楚。我们将讨论 plotly 和 Dash。看这里。
如果你正在寻找一些开源项目的想法,请阅读这篇文章。
LinkedIn 个人资料和数据科学简历
当你完成了上一步的所有事情,也就是说你有 2-3 个 Github 开源项目,你就准备好润色你的 LinkedIn 个人资料了。如果你有的话,请附上你做过的任何证书。如果你现在还没有,最好在 Coursera 上完成 1-2 门课程,以便在你的简历中显示出来。你可以在这里找到值得一试的课程清单。
在你的 LinkedIn 上写一篇好的介绍。让你的雇主知道你为什么要找一份数据科学的工作,为什么要转行,这很重要(如果是这样的话)。诚实但要谈论你的优势。
给出你的 Github 项目的链接,并在你的简历中简单描述一下。表明你愿意学习很重要,因为数据科学就是测试和尝试,这是一个终身学习的过程,所以你不应该害怕。
开始投简历,准备面试
最后,如果你有一份准备充分的简历,LinkedIn 个人资料是最新的,并且你有活跃的 Github,那么是时候开始向不同的数据科学公司发送简历了。
不要一开始就担心结果。最重要的是去参加工作面试,亲自看看面试是什么样的。把前三次面试当作一次练习。你会解决一些问题,你会与人交谈,你会学到一些新东西。保持开放,自己看看别人对你的期望是什么。询问关于工作和要求的问题。询问工作条件,可能的职业等。
如果你想为数据科学工作面试做好准备,只需多读一些关于该公司的信息,仔细阅读工作描述中任何可能表明你将解决什么问题的内容,并多读一些关于这些问题的内容。还要记住这不是考试。评判你的不仅是你的技术技能,还有你的表达能力、沟通技巧、开放性、好奇心以及其他许多方面。所以不会被录用的时候也不要太难受。你可能不太适合这个特定的组织,但这并不能说明你的技能。
数据科学是一场马拉松
数据科学是一项伟大的事业。如果你在最初的几个月没有得到结果,也不要担心。耐心点,简单的多编码。一切都是为了训练。技能是会随着时间来的。
如果您正在寻找教育材料,请查看:
祝你好运!
让我们保持联系,了解更多关于数据科学的知识。](https://creative-producer-9423.ck.page/c3b56f080d)** 
数据科学工作:如何成为一名数据科学家
最后,如果你想了解成为一名数据科学家意味着什么,那么看看我的书数据科学工作:如何成为一名数据科学家,它将指导你完成这个过程。
免责声明:以上链接是我的书的附属链接,感谢您的支持!
如果你喜欢这段文字的视频版本,我已经在 YouTube 上录制了它:
找一份数据科学的工作
在众多旅游景点中寻找出路——城市行程规划者
来源:谷歌搜索
数据科学的最终目标是优化人们的生活,尤其是日常生活。从我的生活中找到真正的问题和不便,并利用技术工具来解决它,这正是我如何在这个寒假发现数据科学的魅力。
整个故事始于我的旧金山之旅,这是一个世界闻名但对我来说却有些陌生的城市。我知道我要去参观金门大桥、朗伯德街、斯坦福大学和其他著名的景点。然而,伴随我兴奋而来的是任何旅行中最烦人和最耗时的部分——为一天的往返行程制定一个有效的旅行计划。事实上,对于那些到一个不熟悉的城市旅行的人来说,规划行程是一个很常见的障碍,因为通常情况下,我们不知道每个景点的位置以及它们各自相对于彼此的方向,这使得设计一条精心规划的路线变得极其困难。我能做的最好的事情就是在谷歌地图上标出每一个感兴趣的地方,并根据我内置的雷达直觉设计一条旅行路线。大体上知道去哪个地区是容易的,但困扰我的是确定在一个区域内去的地方的具体顺序。例如,我知道我将在 SF 的东北部(在地图中圈出)度过我的第一天,但我很难立即找到最省时高效的路线来覆盖地图中所有标记的地方。此外,游客开始一天生活的最典型地点——住宿的酒店,将在很大程度上影响他们随后选择的路线。
图 1:旧金山旅行的准备工作
被每天规划旅行路线的不便所困扰,我转向算法来实现路线设计的自动化。这个项目的目标是解决一个痛点:我如何优化一天往返的路线?
数据收集
我需要的数据无非就是地理信息。因此,唯一的数据来源是谷歌地图。使用了他们的几个应用程序接口(API)。具体来说,我需要旅游景点的名称,各自的经度和纬度,所在的城市,路线的长度,以及估计的乘车旅行时间。
假设
我为这个项目做了几个假设。
1.源和目的地应该相同。在现实世界中,典型的一日城市游是往返旅行。我假设你旅行的起点是你住宿的地方,比如一个 Airbnb 公寓(我这里不是打广告)或者一个酒店房间。固定起点的目的是提供个性化的旅行路线,因为开始旅行的地点将在很大程度上影响当天剩余时间的旅行路线设计。此外,没有人喜欢在忙碌了一天游览城市后的游牧生活。
2.全程你都要开车。为了方便编程,运输工具固定为汽车。游客在旅游期间可能会改变停留的地点,以及他们选择交通工具的个人偏好。然而,在这个项目的最初版本中,这些可能性都被排除了。
背景
我在访问 SF 时遇到的问题的本质是一个经典的动态规划问题——旅行推销员问题(TSP)。在 TSP 中,要问的问题是:“给定一个城市列表和每对城市之间的距离,访问每个城市并最终绕回到原始城市的最短可能路线是什么?”因此,处理这个问题的主要算法类似于 TSP 的解决方案。
让我们开始吧!
该项目的蓝图如下:
Python 用于实现算法和数据信息检索。web 开发框架 Flask 用于嵌入 Python 脚本和制作交互式 web 用户界面(UI)。
步骤 1:定义一个 Python 函数,从 Google Map APIs 中检索两个地方之间的地理数据,以便 TSP 算法能够运行。
**import** tsp
**import** numpy **as** np
**import** requests
def get_api(source, dest):
gmaps_key = 'YOUR GOOGLE MAP API'
url ='[https://maps.googleapis.com/maps/api/distancematrix/json?'](https://maps.googleapis.com/maps/api/distancematrix/json?')
r = requests.get(url + 'origins=' + source +
'&destinations=' + dest +
'&key=' + gmaps_key)
x = r.json()
x = dict(x)
distance = str(x['rows'][0]['elements'][0]['distance']['text']).replace(" km", "").replace(",", "")
return float(distance)
第二步:获取用户输入。用户可以输入他们旅程的起点/终点,以及他们想去的中间地点。
#determine the ending of a loop.
flag = 1
#geolist
list = []
# get the starting point
dimensions = input("please enter 1 to start your journey ...\nand enter 0 to end...")
if dimensions == "1":
dimensions = input("\nplease input the source & dest to start your journey...")
list.append(dimensions)
while flag == 1:
#prompt the in-between places
dimensions = input("\nplease input any place within your journey...")
if dimensions == "0":
flag = 0
else:
list.append(dimensions)
else:
print("\nyour journey ends...\n")print("the places you want to go are ",list," , and you want to go back to ",list[0]," after this busy day..")
步骤 3:用中间位置构建每个起点/终点,并将它们集成到配对元组中,并将它们推送到一个列表中。
#construct a source-destination pair
source_dest_pair = []
for i in range(0,len(list)):
#source;
source = list[i]
for j in range(i+1,len(list)):
#destination
temp = []
temp.append(source)
dest = list[j]
temp.append(dest)
source_dest_pair.append(temp)
步骤 4:应用步骤 1 中定义的函数计算每对的距离。
#construct a list to get distance for each pair
distance_list=[]#calculate distance for each pair using get_api function
for i in range(0,len(source_dest_pair)):
distance_list.append(get_api(source_dest_pair[i][0],source_dest_pair[i][1]))
步骤 5:构建一个距离矩阵,其中存储了每对地点的对应距离。
distance_matrix=[]
for i in range(0,len(list)):
temp_matrix = [0] * len(list)
distance_matrix.append(temp_matrix)temp_list_row = distance_list.copy()for i in range(0,distance_matrix.__len__()):
# for each source
for j in range(i+1,distance_matrix.__len__()):
distance_matrix[i][j] = temp_list_row.pop(0)temp_list_col = distance_list.copy()for i in range(0,distance_matrix.__len__()):
# for each source
for j in range(i+1,distance_matrix.__len__()):
distance_matrix[j][i] = temp_list_col.pop(0)
步骤 6:将距离矩阵中的值转换为字典格式,这是 Python 中常用的键值对数据结构,也是 TSP 算法工作的兼容格式。然后,应用算法,得到最有效的出行路线。
r = range(len(distance_matrix))#construct a path matrix and put it into a dictionary
shortestpath = {(i,j): distance_matrix[i][j] for i in r for j in r}print("----------------------------------------------")
print("\nyour travel routine is ")for i in range(len(tsp.tsp(r,shortestpath)[1])):
print(list[tsp.tsp(r,shortestpath)[1][i]],end=" -> ")
print(list[0],end="")
print(", and the total distance of travel is: ",tsp.tsp(r,shortestpath)[0], " km.")
这是该项目的视频演示。
项目演示
【http://uihojk.pythonanywhere.com/】点击以下链接,您可以尝试设计自己的旅行路线:
**注意:**出于认证目的,用户必须通过谷歌地图申请自己的 API,然后才能成功使用该产品。关于如何从 Google Maps 获取 API 的详细说明可以通过以下链接找到:
[## 获取 API 密钥|地图嵌入 API | Google 开发者
新用户:在开始使用谷歌地图平台 API 和 SDK 之前,你必须注册并创建一个账单…
developers.google.com](https://developers.google.com/maps/documentation/embed/get-api-key)
限制
有几个限制。当我在考虑用户界面时,我发现谷歌地图上显示的计算出的有效路线是一种理想的可视化方式,让用户对他们将拥有的计划有一种直观的感觉。不幸的是,Google API 不允许任何包含方向层的 HTML 格式输出(如果我想显示路线,我需要添加一个方向层)。因此,包含方向和顺序引导的直接地图在本项目中不适用。
图 2:最终输出的理想可视化效果
与此同时,用户界面仍然是一项正在进行的工作,在功能和美学方面都有改进的空间。在当前版本中,最多总共有 10 个位置。但是,如果用户不想访问那么多位置,他们就被迫使用 0 来填充 web 表单中的空白。下一个版本将会有一个动态的网络表单,用户只需点击“再添加一个停靠点”按钮,就可以提示服务器提供额外的空间来添加位置。
此外,为了准确定位感兴趣的地方,我必须避免任何歧义(例如,具有相同的名称,但在不同的城市),因此用户必须在每个地方后添加这些地方所在的城市名称。
过去,我一直认为很难产生一个好的商业想法。然而,请记住,数据科学源于日常生活,因此,请反思您的活动,并尝试解决您经常面临的问题。你可能会对身边等待你抓住的机会数量感到震惊——很多机会和有趣的东西其实就在我们身边。
参考
https://en.wikipedia.org/wiki/Travelling_salesman_problem
https://jupyter-gmaps . readthedocs . io/en/latest/tutorial . html
https://console.developers.google.com/apis
在疫情找一份数据科学工作
和脸书、亚马逊、康卡斯特的面试经历
在 面试查询 ,我们爱聊我们的成功故事。本周,我采访了最近以数据科学家的身份加入 Attain 的 Jennetta。我询问了她的面试经历,在当前的疫情时期找工作有多难,以及对其他数据科学求职者的建议。
你好!你的背景是什么,你是如何进入数据科学的?
嗨,我叫珍妮塔。我的背景是理论数学,我在 2018 年获得了斯德哥尔摩大学的硕士学位。从那以后,我做过三份不同的工作,一份是在一家水务公司担任人工智能研究员,然后在一家政府承包商担任软件工程师,最后在 Penn Interactive 担任首席数据科学家。目前,我即将开始担任一个政府承包商的 AI/ ML 的专家领导。我们也在招=)。
找新工作时,你的整体面试体验如何?
疫情的面试经历太奇怪了。在此之前的六个月,我就在就业市场上了,关键的不同是,上次我马上就找到了工作。这很直接,因为我辞去了上一份工作,接受了提供给我的新职位,感觉更像你们所说的买方市场。我猜在这种情况下,在员工市场中,获得数据科学工作并不困难。
然而,这一次,就在疫情开始前,我被解雇了。起初,我马上就能得到面试机会,并为此兴奋不已。一个工作机会是在康卡斯特,我是主要角色的最终候选人之一。导演非常爱我,他用他的私人手机给我打电话,让我知道他们正在敲定事情。但是,一旦疫情受到冲击,就出现了大规模的招聘冻结,机会也失去了。
我的另一个工作机会是在迈阿密。我对搬到那里很感兴趣,所以我开始与皇家加勒比面试,甚至自己飞到现场。面试的经历很棒,我觉得我通过了面试,但显然那次也没有成功。慢慢地,采访开始到处被取消。
后来你做了什么去疫情找工作?
我开始关注像亚马逊和脸书这样的大公司。对我来说,这绝对是一种不同的情况,因为我从未在西海岸生活过,以前一直在初创公司工作。
我最终进入了亚马逊的最后阶段和脸书的技术筛选,他们都给出了相同的反馈,即我是一个强有力的候选人,但鉴于这是一个雇主市场,他们都有一个更大的合格候选人池可供选择。
在面试过程中,有一件事让我印象深刻,那就是我感觉很多人都在为他们的面试做功课和大量的研究。我不能说我是那种人。一般来说如果他们喜欢我,他们就喜欢我。这就是为什么我会对一些面试如此具体地针对一种角色感到惊讶。
有时候,我觉得由于我没有技术背景,当谈到超参数、进行密集的编码练习或讨论开发运营时,我总是受到抨击。但是在脸书数据科学的面试中,他们最终拒绝了我,因为*他们认为我太专业了?!*脸书让我感到惊讶,因为他们想让我更多地关注业务方面,而我认为我是一个很强的沟通者。
你收到的最难的面试问题是什么?
我在亚马逊遇到了一个供应链问题,这个问题与供应和履行有关。他们给了我一个问题,他们给我可以访问的不同种类的数据集命名,比如产品、邮政编码和履行中心的列表,并要求我模拟这个问题以实现利润最大化。
我发现这个问题很难,最后,招聘经理和另一位参加面试的数据科学家告诉我这个问题他们已经研究了 3 年,仍然没有解决。我觉得如果他们事先告诉我,我就不会直接进入解决方案,而是进行讨论。但是我想这次经历正好说明,考虑到你在面试中面临的信息不匹配的程度,提前提问和澄清假设是多么重要。
你是如何在 Attain 找到现在的工作的?
随着我在attach的面试过程,我与技术招聘人员进行了一次非常积极的电话筛选,然后与该项目的一位领导进行了另一次同样良好的交谈。大约一周后,我从招聘人员那里听说一份工作正在准备中,我很快就接受了。具有讽刺意味的是,对于其他公司的这么多面试,我不得不跳过几十道关卡,执行具有挑战性的带回家项目或在线评估,经历 8 个小时的现场面试,所有这些都以没有工作机会而告终,而最终给我提供工作机会的公司只需要与我进行两次 30 分钟的谈话,就知道我是他们想要的人。
对于现在正在寻找数据科学工作的人,你最后的建议是什么?
我对面试的建议是,尤其是现在,你必须非常警惕,随时准备接到电话,让公司对你感兴趣。我在面试查询 Slack channel 上读到很多东西,比如我发出了 10-15 份简历,为什么我没有收到任何回复?不,不是很多。在我找工作的一天里,我会在 LinkedIn 上联系 200 多名招聘人员,并额外申请 20-40 份工作。这样做了一个星期后,我会收到大约五个回复。这是一份全职工作,既要提交简历,也要写求职信。
后续行动也同样重要。有几次我可能找不到工作,最后我发了一封真诚的电子邮件给某人留下了比面试实际情况更好的印象。结果我在面试中一轮又一轮地前进。不过,这样做确实需要毅力和勇气。
感谢阅读
- 更多面试问题可以在面试查询 上找到
- 查看我的 Youtube 频道 获取更多数据科学内容、面试指南和解决问题的技巧&。
- 在面试查询博客上找到更多数据科学面试指南,如 谷歌数据科学家面试 和DoorDash 数据科学家面试 。
原载于 2020 年 4 月 26 日 https://www.interviewquery.com。
聪明的方法是找到一个杂货递送点
使用 Python、Heroku 和 Twilio 从一个杂货网站的 API 中抓取数据,并在有空位时获得文本通知
如果你还没听说,我们生活在前所未有的时代…
随着时间的推移,“史无前例”一词的使用。来源:谷歌趋势
前所未有的时代带来了新的挑战。其中一个问题是我们如何维持食品供应链,由于新冠肺炎病毒的传播,数百万人现在处于封锁状态。对于那些脆弱的、孤立的或者不能亲自去超市的人来说,唯一的选择通常是在网上预订超市送货位置。然而,随着对这些服务的巨大需求,找到一个可用的位置变得众所周知的困难——使得许多人不停地登录以检查位置。
这让我思考——随着我在生活中面临的问题越来越多——我如何使用 Python 来自动完成这个过程?
检查我们的杂货网站
我们实现某种形式的“自动递送槽检查器”的目标的第一步是弄清楚我们如何以编程方式从杂货店网站提取我们想要的数据。
在选择 Asda 作为我们的杂货网站之后,创建一个帐户,并输入送货邮政编码,我们就进入了 送货位置页面 ,如下所示。
Asda 交付槽页面,显示我们想要抓取的数据。
在这里,我们可以看到一个整洁的日期,时间和每个位置的可用性表。不出所料,所有插槽目前都显示为“售完”。但是我们现在可以看到我们希望通过工具获取的目标数据。
下一步可能是最重要的一步。如果你以前做过网络抓取,或者从事过网络开发,你会很熟悉大多数主流浏览器内置的 DevTools 功能。对于那些不是这样的人,这些是一套工具,允许用户检查网页的幕后,检查 HTML,CSS,Javascript,以及-对我们的项目至关重要的-与服务器和我们的网页发出的网络请求相关的元数据。我们可以通过在我们的网页上右键单击并选择“检查元素”或键入 Ctrl+Shift+I 来访问 DevTools 选项卡(我使用的是 Firefox,但类似的过程也适用于 Chrome、Internet Explorer 等。).
访问 Firefox 开发工具
随着我们的 DevTools 窗口现在可见,我们可以开始在我们的网页中看到幕后发生的事情,使我们能够看到最新的插槽可用性表。导航到 DevTools 窗口的“ Network ”选项卡,我们现在可以访问我们的网站发出的所有网络请求,以获得我们可以看到的最新数据。刷新我们的网页将产生一个请求列表,其中一个请求必须包含找出我们的空位可用性数据来自哪里的关键。
追踪杂货网站发出的网络请求
这个列表最初可能看起来有点混乱,因为我们将有大量不同的请求,收集了从描述网页格式的 CSS 到确定网站功能的 Javascript 的所有内容。然而,我们感兴趣的是被收集起来并呈现在网页上的数据。因此,只过滤那些类型为’ XHR ’ (XMLHttpRequest)的请求,允许我们只关注那些从服务器请求数据的请求,忽略那些关注网页样式的请求。这仍然留下相当多的请求需要检查;幸运的是,赌上我们需要的请求将包含单词“slot ”,将我们的搜索缩小到只剩下四个请求。
过滤请求
点击一个请求并选择’ Response ‘选项卡,显示请求产生的 JSON 响应,从而显示发送到网页的数据。由此,我们可以很快看出,包含我们正在寻找的数据的请求是对 URL 的一个 POST 请求,https://groceries.asda.com/api/v3/slot/view。看一下’ Params ‘选项卡,我们可以看到我们的浏览器在 POST 请求中发送的 JSON 数据,右键单击并选择’ Copy All '将这些 JSON 数据复制到我们的剪贴板,这意味着我们拥有了向 Python 解释如何收集数据所需的一切。
使用 Python 发出 web 请求
Python 中的请求库使得以编程方式发出 HTTP 请求变得非常容易。从我们对网站的上述检查中,我们现在知道:我们需要向其发送请求的 URL ,我们需要使用的请求类型(POST)以及我们需要发送的 JSON 数据(当前存储在我们的剪贴板中)。
实际上,这留给我们下面的代码:
我们在这里所做的就是从剪贴板中粘贴出我们的 JSON 数据,并添加一个简单的请求,使用requests.post()
方法的json
参数将这些数据发送到我们的 URL。我们的请求响应对象现在存储在变量r
中,以备后用。
我们还用变量替换了数据中的一些参数。start_date
和end_date
变量向 API 传递一个动态日期范围,因为我们总是对从当前日期算起的两周内的情况感兴趣。datetime 对象的strftime
方法允许我们指定我们希望 datetime 对象采用的确切的字符串格式,这可以与我们在复制的初始 JSON 数据中检查的格式相匹配。
存储为os.environ
变量的参数是我们不想在 GitHub 上公开显示的敏感信息。稍后,我们将看到如何安全地存储这些内容,以便部署到我们的脚本中。
我们现在有了一个全功能的 Python 脚本,我们可以用它来向 Asda 的 API 发送一个请求,并且存储我们作为结果接收到的响应对象。现在让我们看看这个响应对象,并探索如何解析它以提取我们正在寻找的数据。
解析 JSON 响应
我们的响应对象r
包含从我们对 Asda 的 API 的 POST 请求中接收到的所有数据/元数据。我们应该检查的第一件事是我们对服务器的请求是否成功,或者在这个过程中是否出现了错误。为此,我们可以检查响应对象的status_code
属性。
r.status_code # Inspect status code of response
如果这个没有返回200
,那么这个请求就有问题了。在这种情况下,我们需要仔细检查 URL 和数据的格式是否正确。可能的 HTTP 状态代码的完整列表可以在这里找到;但是,一般来说,我们会收到一个表示’ OK 的200
代码和一个分别表示’ Bad Request ‘和’ Not Found’ 的400
或404
代码。
假设我们已经收到了一个200
状态代码,我们现在准备检查我们在响应中收到的数据。因为以 JSON 的形式接收数据是很常见的,所以 requests 带有一个内置的 JSON 解码器。
r.json() # Decoding JSON response content
将r.json
的值打印到终端将会很快显示出我们已经从服务器收到了大量与插槽可用性、价格、容量等相关的数据。因为我们主要对项目中的插槽可用性感兴趣,所以我们可以遍历这个 JSON 响应并用插槽和可用性填充一个字典。
我们首先循环查看我们所要求的两周内的每个时间段,然后在每一天内检查每个单独的时间段,填充我们的字典:
现在我们已经有了所有需要的数据,并且有了一种在我们需要的时候以编程方式提取数据的方法,让我们看看如何设置一种方法,以便在发现一个交付位置可用时通知我们的最终用户。
Twilio —使用 Python 发送文本
Twilio 是一个云通信平台,提供 API,使开发人员能够在他们的应用程序和项目中发送和接收短信和电话。这为自动短信通知、双因素认证、构建聊天机器人等打开了一个潜力无限的世界。在我们的例子中,我们将创建一个简单的文本通知系统,这样每当我们的脚本运行时,我们都会收到一个文本,详细说明任何可用的交付时间段。
虽然 Twilio 是一项付费服务,但他们提供了大约 13 英镑的免费试用余额。这足够让我们开始这个项目了——因为发送一条短信大约需要 0.08 英镑。为了开始使用 Twilio ,我们需要做的就是 在他们的网站上注册 (不需要支付细节)并选择一个电话号码。一旦完成,Twilio 将为我们的项目提供一个帐户 SID 和认证令牌。
一旦我们都设置好了 Twilio 帐户,我们就可以开始使用 Twilio 提供的 Python API 了。Python 的 Twilio 模块可以简单地通过 pip 安装。
pip install twilio
Python 的 Twilio API 非常容易上手,在 https://www.twilio.com/docs 有大量的文档。要用我们新获得的电话号码发送短信,我们只需要以下信息:
from twilio.rest import Client
client = Client(account_sid, auth_token)
message = client.messages.create(
body='message text',
from_='+15017122661',
to='+15558675310')
将此合并到我们的脚本中以获得可用的交付时段,我们现在可以检查任何可用时段的数据,如果存在,就向我们选择的电话号码发送一条文本,通知我们选择的电话号码。这在我们脚本的最后一部分进行了概述:
我们现在有了一个完整的脚本,使我们能够在 Asda 检查可用的交付槽,如果有可用的话,通过文本接收通知让我们知道。我们项目中剩下的唯一一步是找到一种方法让我们的脚本按照计划自动运行。
部署到云— Heroku
eberhard grossgasteiger 在 Unsplash 上拍摄的照片
Heroku 是一个云计算平台,支持开发者轻松将应用和项目部署到云。它在以最少的设置启动和运行 web 应用程序时特别有用:使其成为个人项目的理想选择。在这里,我们将使用 Heroku 作为一种简单的方式,让我们的脚本在云中以预定的时间间隔运行。
你可以报名在这里与 Heroku 一起开始。
我们需要采取的第一步是创建一个新的应用程序来存放我们的项目:
为了让我们的脚本在云上运行,我们需要创建一个新的包含我们脚本的 GitHub 库。你可以在这里 找到我的 供参考。我们还需要创建一个名为requirements.txt
的文件。这将包含我们需要告诉 Heroku 在成功运行我们的脚本之前安装的所有包依赖项。
然后,我们可以将应用程序连接到刚刚为项目创建的 GitHub 存储库。启用’automatic deployments’意味着当我们推进到我们的主分支时,我们的项目将自动部署最新的更新:如果我们希望在产品化的同时继续开发我们的项目,这是很有用的。
从 GitHub 部署 Heroku 应用程序(为演示加速)
正如我们前面提到的,在我们的脚本中有几个变量我们希望保持隐藏。我们可以使用 Heroku 应用程序的’ Config vars '设置来实现这一点,这是一种在我们的项目中存储敏感信息的便捷方式,这些信息可以作为环境变量轻松访问:
剩下的唯一一步是让我们的脚本按照计划自动运行。为此,我们需要安装一个附加到我们的应用程序。 Heroku scheduler ,可以在这里安装,让我们每 10 分钟、小时、天运行一次任务。
一旦我们安装了 Heroku scheduler,我们就可以创建一个新的作业,这将允许我们选择我们的计划频率和我们想要运行的命令。由于插槽往往运行得很快,所以 10 分钟的频率可能是我们计划作业的最佳频率。我们想要的运行命令只是运行我们的 python 脚本:
**python get-grocery-delivery-slots.py**
我们现在可以高枕无忧,等待我们的短信通知来了!
结束语
权力越大,责任越大。来源: knowyourmeme
在这个项目中,我们已经看到 Python 在为我们自动化任务方面是多么强大。但是我们知道,伴随着巨大的力量而来的是巨大的责任。
考虑到我们为这个项目反向工程的 API 可能不是为公共使用而设计的,我们应该尊重地使用它,并记住这一点。从理论上讲,我们现在有能力向服务器发送比人类使用 web 界面所能做到的更多的请求。虽然人们会期望一家大公司有适当的保护措施来阻止行为不端的 IP 地址,但我们不应该得寸进尺。坚持原则上可以手动执行的操作可以确保我们尊重这种公平使用。
此外,仅仅因为我们现在有效地拥有了一个位置可用性的预警系统,并不意味着我们应该在不需要的时候预订位置。这个项目的动机源于对投递位置稀缺和许多人在寻找投递位置时所面临的困难的认识。因此,我们应该非常清楚这对社会中最弱势群体造成的障碍:对他们来说,这不是一种便利,而是一种必要。
也就是说,我们在这个项目中开发的技能为进一步的项目打开了一个可能性的世界:
- 我们现在可以使用 DevTools 检查网站,对 API 进行逆向工程,并使用 Python 的请求库提取数据:这给了我们从几乎任何公开网站提取数据所需的基本技能。
- 我们使用了 Twilio,这是一个允许我们发短信和打电话的通信 API。这不仅为我们提供了一种通过文本接收或发送通知的便捷方法,还为我们打开了 Twilio 的更多可能性:聊天机器人、警报系统、机器人呼叫者等。
- 我们将我们的项目部署到 Heroku,允许我们的脚本在云上按计划自动运行。这是一项很棒的技能,它消除了必须在笔记本电脑或 PC 上运行脚本的本地依赖性,并给了我们一个在网络上展示我们项目的绝佳机会。
感谢阅读!
这个项目的所有源代码都可以在这里找到:
**** [## Emile gill 743/杂货交付项目
项目从一个杂货网站的 API 抓取数据,并在有空位时获得文本通知。…
github.com](https://github.com/emilegill743/grocery-delivery-project)****
寻找数据科学领域的导师
如何爬上巨人的肩膀
我非常相信导师制度。找到一个导师可能是你为什么能在 5 年内而不是 45 年内成功实现数据科学目标的决定性因素,因为你有勇气坚持那么久。
毫无疑问,你是一个聪明的人,积极主动,愿意阅读所有关于数据科学的书籍,但没有什么比得上被一个已经在那里做过数据科学的人指导。事实上,我不确定两辈子是否有足够的时间去了解数据科学这个名称所涵盖的一切,因此这就更有理由去寻找一位导师。
“这并不是说短期内不可能取得实质性进展.”
老实说,我觉得我不应该让你相信找到一个数据科学导师的重要性…这通常是我们都知道有益的事情。尽管如此,我仍然发现许多人以错误的方式去寻找这个领域的导师。
对自己有价值
我曾经读过一个故事,我觉得这个故事与这个话题非常相关(我希望我能记得这个故事叫什么)。故事的主角是一只鸟,这只鸟已经孵出来了,但是它的妈妈却不见了。结果,这只鸟开始寻找它的妈妈,它会去找任何它看到的人——狗、猫、人、狐狸,你明白我的意思了吧——并问“你是我的妈妈吗?”。
在专业环境中,这相当于问一个你刚刚在 LinkedIn(或其他任何地方)上联系过,但还没有建立关系的数据科学家,“你愿意做我的导师吗?”。很有可能你得不到回复,但是让我们想象你得到了回复,这可能是一种响亮的“不”(因为数据科学社区是多么礼貌)。
“如果你不得不请人指导你,答案很可能是否定的”
我个人认为伟大的导师会找到你。我并不是说他们会光彩照人地来到你面前,宣布“从今以后,我将成为你的导师”,因为那将和“你会指导我吗”的情景一样荒谬。
相反,一个伟大的数据科学导师应该是这样的人,你已经展示了你的潜力,或者更好地说,你已经展示了你的价值,他们已经被吸引了——这是克服你对开源工作的任何恐惧的另一个原因。
他们接触你可能不是为了让你成为他们的学员,但持续的互动会向你展示你们的信念有多一致,反过来,会成为他们建立信任的一部分,以确定他们是否认为你值得他们投入时间。
没有议程
这听起来可能会适得其反,但我真的觉得不接受这个建议可能是你做过的最糟糕的事情。
当有人带着议程、额外的善意和额外的奉承来到我们面前时,我们都能感觉到。这个人想要的东西会打乱你目前的安排吗?大概 99.99999%的时候。
数据科学领域值得接受指导的人将会受到很多人的高度需求。每个人都想从他们那里得到一些东西,如果他们成为你的导师对他们没有明显的好处,他们到底为什么要这样做呢?
让我把这个说清楚…
“伟大的导师不需要你”
他们努力工作,做出了在当时会造成伤害的牺牲,可能还有更多我们无法想象的事情,只是为了达到他们今天达到的位置——一点点奉承不足以补偿他们积累的所有伤痕,因此这可能不会让你得到你想要的结果。
或者,真诚地想要真正了解这个人以及他们的想法。
全力以赴
好了,你已经确定了你想指导的人。接下来要做的就是全力以赴!
我一直不理解多导师的想法。请不要误解我的意思,我不是说在你生活的不同领域有多个导师,我指的是在一个领域有多个导师,即在数据科学领域有多人指导你。
如果有人在数据科学相关的工作中指导你,那么全力以赴去倾听这个人的意见。人们有不同的哲学,对一个人有用的东西对另一个人可能是完全矛盾的。如果有人给了你他们的时间,全力以赴,充分利用你拥有的机会。
关注他们的工作,支持他们,了解他们需要什么帮助,这样你就可以提供帮助,给予,给予,给予,给予更多。例如,用支持性的评论来评论他们所有的帖子,如果有一个可选的事件,那么确保它对你来说不是可选的。
包裹
如果你希望你的数据科学事业以更快的速度发展,导师将是带你实现这一目标的工具。然而,找导师不是看谁赚的钱最多,也不是看谁在 LinkedIn 上的粉丝最多。相反,寻找一位数据科学导师是为了找到一个人,他的信仰体系与你的信仰体系一致,可以让你与他人建立联系。
你认为我寻找导师的方法怎么样?请留下您的回复或在 LinkedIn 上与我联系,让对话继续下去…
[## Kurtis Pykes -数据科学家-自由职业者,自由职业者| LinkedIn
在世界上最大的职业社区 LinkedIn 上查看 Kurtis Pykes 的个人资料。Kurtis 有 3 个工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/kurtispykes/)
用强化学习找到一条通往雾湖上冰屋的路
在“frozenlake-nonslippery”环境下使用交叉熵方法开始强化学习。
环境中的智能体随着时间的推移对最优决策的学习通常是如何定义强化学习的。
在高层次上,有几种强化学习的方法,以一种过于简化的方式分类和解释如下:
1。 无模型还是有模型: a. **无模型:**代理先行动后思考的蛮力法。
b. **基于模型:**代理根据历史数据做出预测,根据预测采取行动。
2。 基于价值还是基于政策: a. **基于价值:**从一个环境的给定状态中,代理人可以获得的总报酬折现。
b. **基于策略:**当一个 agent 有很多动作空间,有了策略,解释器(we)就会控制 agent 的状态和动作。
3。符合政策还是不符合政策: a. 符合政策:学习是所采取的行动及其对国家的影响的结果。
b. 非政策:学习是几个行动的结果,然后累积奖励。
交叉熵方法是一种无模型、基于策略、基于策略的方法。
在结冰的湖面上:
环境是一个冰冻的湖,一个代理试图到达一个目的地。
挑战
湖面上覆盖着冰和浓雾。对我们来说,冰原上有已知的开口,但特工并不知道。
代理人穿着钉鞋,以防止他转弯时在冰上滑倒。
演员的能见度也很差,导航也是一个挑战。对这个演员来说,每一步都是信念的飞跃。
这是一个生存游戏,目标是回家。因此,只有当我们到家时,才会收到奖励“1”。在余下的旅程中,我们的假设是,我们活着是为了迈出新的一步。
我们没有从生存的环境中得到任何回报。
将案例转换为确定的非连续场景:
Lake 是一个 4x4 的网格,代理可以上下左右移动。因此,观察空间从 0 到 15 是离散的,动作空间从 0 到 3 也是如此。
让我们继续创建一个类,通过使用 onehot 编码将观察空间和动作空间转换为二进制。
在代码中,我们的环境看起来像这样:
交叉熵方法:
由于这是一种基于策略的方法,神经网络(非线性函数)确定代理人应该采取的行动,以使回报最大化。
该方法的步骤:
- 使用当前模式和环境播放“n”集。
- 计算每集的总奖励,并确定一个奖励范围。通常,我们使用所有奖励的某个百分点,比如第 50 到第 70。
- 扔掉所有低于界限的有奖励的剧集。
- 将观察结果作为输入,将发布的行动作为期望输出,对剩余的“精华”片段进行培训。
- 从第一步开始重复,直到我们对结果满意或达到目标。
在我们冰冻的湖泊环境背景下,让我们看看“第二集”:
观察 1: o1 =像素 1,1, a1 = 0, r1 = 0
观察 2: o2 =像素 1,2, a1 =右, r1 = 0
观察 3: o2 =像素 2,2, a1 =下, r1 = 0(结束
解决奖励问题:
我们将通过引入折扣系数为 0.9 到 0.95 的总奖励来解决奖励检测进度的问题。
这都是在 filter_batch 函数中引入的:
我们会将成功的剧集或播放时间较长的剧集保留更长时间,以便模特可以从中学习,并通过降低学习速度来花更多时间学习。
结论和实用性:
尽管在我们的日常生活中,我们并不挣扎着寻找回家的路,我们也知道目的地,但与深度学习领域相比,冰湖或强化学习领域中的任何其他案例都被批评为与企业世界无关。
强化学习本身依赖于深度学习世界中现有的方法。在强化学习中,我们看待问题的方式是不同的。
作为欺诈检测的一个示例,我们将不得不创建一个环境,其中包含欺诈者和客户的丰富信息。然后,我们将需要一个代理人谁将试图检测和解决欺诈的个人资料。
这将使我们能够根据欺诈可能存在且不在我们覆盖范围内的可能性来训练模型。
如果你已经到了这一步,感谢你阅读这个故事,你可以在这里获得完整代码。
来源:
非常感谢马克西姆·拉潘,他的书“深度强化学习实践”帮助我开始了强化学习的世界。
使用神经网络寻找作家的风格
使用 Genius API 训练歌词的网络模型
迈克尔·达茨、邓肯·格拉布斯和姬满·金
介绍
每个作家都有自己的风格。成为一个知名且受人尊敬的作家的部分关键是磨练这种风格,创造出完全属于你和你的生活经历的东西。音乐作为一种艺术形式,允许一种完全独特的表达形式,一些艺术家在他们的作品中确实是无与伦比的。作为热爱音乐的学生,我们已经看到了神经网络在文本分类方面的能力,我们想测试这样一个网络的边界。
仅仅通过看歌词,你能区分范·莫里生和鲍勃·迪伦的歌曲吗?(维基百科)
我们正在研究的问题对一个人来说已经够难了。单看歌词,你能说出是谁写的吗?
从这些歌词中,可能很难看出是谁写的,除非你对乐队和相关的词曲作者都非常熟悉。
事实上,我们甚至很难做出一个有根据的猜测——我们需要更多的背景知识,然后才能开始给出答案。
这些歌词显然来自甲壳虫乐队的“挪威的森林(这只鸟已经飞了)”,由列侬和麦卡特尼共同创作。
考虑到这一点,我们不仅要在广泛的艺术家上训练我们的网络,还要对他们的目录进行深度采样,这样我们才能提供模型需要的背景,以便给出答案。
我们通过这个神经网络项目的目标是看看一个网络是否能够发现和学习艺术家的风格,并能够预测谁写了一组歌词。这个想法是,给定足够的数据,模型可以根据流行艺术家的歌词进行训练,并能够将后来的输入分类为给定的艺术家。
在我们开始之前…
本文假设您对神经网络及其概念有基本的了解。我们将讨论编程语言 Python,以及我们用来构建网络的各种库。
至于数据,我们使用了 Genius API——一个允许我们连接到网站并收集所需数据的接口。我们能够使用 LyricsGenius Python 库访问这个 API 这使得查询变得更加容易。我们假设观众熟悉用于创建神经网络的库,如 Keras 和 TensorFlow。
Keras 是一个高级神经网络 API,用 Python 编写,能够运行在 TensorFlow、CNTK 或……
keras.io](https://keras.io/) [## API 文档| TensorFlow Core v2.1.0
TensorFlow 提供了几种语言的 API,用于构建和执行 TensorFlow 图。巨蟒…
www.tensorflow.org](https://www.tensorflow.org/api_docs)
收集数据
这种方法的第一步是收集数据。虽然在 Kaggle 等网站上有许多歌词存储库,但我们发现,虽然这些文件中有许多艺术家,但他们没有足够的每位艺术家的歌曲,无法让网络对歌词风格有更深入的了解。
我们决定使用 Genius 的数据,这是一个歌词网站,人们可以在上面添加注释和评论歌曲。Genius 是由用户编写的,类似于维基百科,但在被审核为正确之前,也会与官方歌词数据和其他来源进行交叉引用。如前所述,Genius 是使用 LyricsGenius Python 库查询的。
lyricsgenius 为存储在 Genius.com 上的歌曲、艺术家和歌词数据提供了一个简单的接口。在使用这个之前…
github.com](https://github.com/johnwmillr/LyricsGenius)
Genius 有一个非常大的众包歌词库,不仅可以很容易地找到各种各样的艺术家,而且如果他们的唱片目录足够大,还可以给我们足够的数据。考虑到我们选择调查的艺术家,找到大量的歌曲样本并不是什么大问题。
鲍勃·迪伦和琼·贝兹,两位美国最著名的民谣歌手(维基百科)
我们想用这些数据确定的一件事是,这些歌曲主要是由表演艺术家创作的。现在一个艺人有一个词曲创作团队是很常见的,这当然有助于形成风格,但也可能会脱离艺人的个人风格。也就是说,我们选择了职业生涯跨度很长的艺术家,主要是像鲍勃·迪伦这样的创作歌手。然而,我们发现这不仅难以持续,因为在任何特定的轨道上也可能有未被编辑的作家。
考虑到这一点,我们选择了 10 位知名艺术家开始,并从他们的 100 首歌曲中收集歌词。我们选择了有深度唱片的艺术家,他们每个人都能轻松地给我们 100 首歌。根据 Genius 的 API,这些歌词来自 Genius 网站上他们最受欢迎的 100 首歌曲。
我们为这个项目选择的艺术家
方法
收集完数据后,我们必须清理它。Genius API 不仅提供了歌曲的歌词,还提供了注释数据,这些数据对我们的项目并不重要。使用一个脚本,我们清理了文件,这样我们就只有歌词的原始文本,而没有其他内容。这被编译成 JSON 文件。
我们的 JSON 清理脚本
考虑到数据的大小,以及歌曲长度的范围,我们也选择将歌曲限制在 100 个词以内。这个限制将为每首歌曲提供一个标准,以防一些艺术家倾向于更长的歌曲。一旦数据被清除,我们需要一种方法将数据输入到我们的网络中。我们通过标记给定歌曲中的所有歌词来做到这一点。所以每个单词都有一个值,可以根据我们的需要馈入网络。
歌曲长度有很大的可变性。
符号化
标记化的一般思想是为每个单词创建一个唯一的数字表示,以便可以输入到网络中。在这种情况下,每首歌曲将被表示为一个数字向量,而每个艺术家将被表示为一个 10 向量的一键编码。我们会把这些输入到网络中,作为模型训练的一部分。
我们标记输入的方法
网络
在项目开始时,我们从 Keras python 库中的一个简单的顺序网络开始。虽然我们已经得到了结果,网络的性能很差。我们发现网络很快就达到了一个上限,不会再改善了。
顺序模型的输出
正如您在这里看到的,我们的训练准确性高于验证准确性,这是可以预期的,但总体而言,这两个值都非常低,只有 20%的准确性。产量如此之低,我们认为最好寻找一种新的方法。
如何开发 LSTM 递归神经网络模型的文本分类问题在 Python 中使用 Keras 深…
towardsdatascience.com](/multi-class-text-classification-with-lstm-1590bee1bd17)
找到这篇文章后,我们选定了一个 LSTM 网络,它可以在文本分类中提供更好的结果。使用 LSTMs 是解决这类问题的一种非常常见的方法,并且已经得到了广泛的研究。LSTMs 对于这种类型的问题很常见,因为它们可以记住过去的数据序列。
正如您在下面的结果中所看到的,训练准确率非常接近 100%,而验证准确率上限在 40%左右。不过,应该提到的是,这些结果是在 30 个时期后获得的,而我们之前的模型需要数百个时期。
也就是说,当我们发现我们的训练精度非常高,而我们的验证精度相对较低时,我们再次遇到了障碍。只有 40%的验证准确率和超过 90%的训练准确率,网络显然是过度拟合的。
我们新的 LSTM 模型的输出
为了解决这个问题,我们相信我们需要更多的数据和更广泛的种类。例如,包括整首歌曲而不在 100 个单词处切断它们,或者向输入中添加歌曲的不同度量,例如平均单词长度和情感。虽然这些变化是可能的,但对于我们可用的基本技术和有限的存储来说是困难的。最重要的是,网络可以通过试错法以小的方式进行修改,以便在这种特定的环境中运行良好。
结论和进一步的项目
在这个项目之后,我们可以得出结论,我们的文本分类离能够分析歌曲歌词这样的风格化散文还有很长的路要走,特别是在我们能够使用的少量数据的情况下。尽管我们收集的结果很新颖,但我们发现再次探讨这个话题需要更多的数据。也就是说,这个话题是有潜力的。
虽然我们没有达到预期的业绩,但通过这次调查,我们还是学到了很多东西。在训练网络后,我们输入了它以前见过和没见过的艺术家的歌词,结果很有趣,给出的结果会比有根据的猜测更好。
虽然电视网之前看过披头士和泰勒·斯威夫特,但没看过德雷克和 ACDC。通过输入网络从未见过的数据,我们可以从一个新的角度了解我们的模型如何对歌词进行分类。当德雷克输入歌词时,模型输出这首歌是李尔·韦恩写的,这是一个可以理解的猜测。
虽然当 AC/DC 的“黑色归来”输入时,模型输出这首歌是 j .科尔写的。关于模型学习有一点要说——当我们输入已经被网络看到的歌曲时,正确的艺术家被输出。
德雷克,“上帝的计划”->李尔·韦恩
AC/DC,《黑色归来》-> J .科尔
甲壳虫乐队,《嘿,裘德》->甲壳虫乐队
泰勒·斯威夫特,《情人》->泰勒·斯威夫特
如前所述,是有潜力的。不仅在歌词分类中,而且在 NLP 文本作者分类的更广泛的问题中。这可以被情报机构用来识别谁写了电子邮件或短信,或者被谷歌和苹果这样的公司用来自动识别新电子邮件和短信的作者。
点击查看 Github 上的所有源代码和数据。
查找和可视化地理空间数据聚类
如何使用 geopandas 和 matplotlib 绘制地理位置坐标和聚类中心
处理地理空间数据时,查找纬度和经度坐标的聚类通常很有用,这可以作为机器学习模型的数据预处理步骤,也可以作为分段分析的一部分。但是,一些与查找地理空间聚类相关的常见问题包括:
- 哪种聚类算法最适合您的数据集?
- 哪些坐标属于哪些集群?
- 每个集群的边界在哪里/坐标是如何分离的?
我最近参加了一个来自 2017 年的 Kaggle 竞赛,主要从地理空间和时间特征来预测出租车旅行持续时间(见帖子此处)。我做的一个预处理步骤是将地点分成 20 个组,并找出每个组中的接送人数,以获得组密度/交通的代理。
在本文中,我将展示如何使用 matplotlib 和 geopandas 在地图上可视化经纬度坐标和聚类中心。下面是我的数据集的不同聚类的样子,不同的值从 2 到 25 个聚类不等。不同颜色的点表示拾取位置以及使用 K-Means 聚类识别的它们所属的聚类,红色的叉表示聚类中心。
k 值从 2 到 25 的聚类坐标
选择聚类算法
有几种无监督学习方法可以从数据集中找到具有相似属性的聚类,包括 K-Means 聚类、凝聚聚类和 DBSCAN。由于我正在处理一个几乎有 150 万个数据点的大型数据集,所以我选择使用 scikit-learn 的MiniBatchKMeans
,这是 K-Means 聚类的一个版本,它使用迷你批次来加速这个过程。
K-Means 聚类中的一个参数是指定聚类的数量( k )。寻找 k 最优值的一种流行方法是肘法,在这种方法中,绘制距离平方和与 k 值的关系图,并选择拐点(收益递减点)。
ssd = []for i in range(2, 26):
km = MiniBatchKMeans(n_clusters=i)
km.fit_predict(df_pickup_filtered)
ssd.append(km.inertia_)
该图显示了距离平方和与 K 值(K 均值算法中的聚类数)的关系
elbow 方法建议,对于这个数据集来说, k 的最佳值是 6。由于纽约是一个大城市,6 个集群是否足够细化?为了进行检查,我将继续观察应用于该地理空间数据集的不同 k 值的聚类。
可视化集群
为了在纽约市的地图上可视化地理位置聚类,我编写了一个函数,允许您在纽约市的地图上绘制您的经纬度坐标和聚类中心。以下是该功能的细分:
- 将地理位置数据框架转换成地理数据库数据框架
这个数据集中的地理位置来自一个. csv 文件,我用 python 中的 pandas 导入了这个文件。为了将它绘制到地图上,我们必须首先将这个常规的熊猫数据帧转换成地理熊猫数据帧
geo_df = gpd.GeoDataFrame(df.drop(['longitude', 'latitude'], axis=1), crs={'init': 'epsg:4326'}, geometry=[Point(xy) for xy in zip(df.longitude, df.latitude)])
2。导入城市或地区的形状文件
Geopandas 具有可在国家级别导入的形状文件,但要获得更详细的信息,您必须下载一个形状文件并使用 geopandas 手动导入。
在我的例子中,我去了 NYC OpenData 并在Export > Download > Download Geospatial Data > Shapefile
下下载了 shapefile。您可能希望将形状文件移动到可以从 Python 轻松访问的目录中,但请记住移动整个目录,因为 geopandas 无法仅使用。shp 文件!
获得形状文件后,您可以使用 geopandas 导入它们,并将其添加到您的绘图中。我将 shapefile 的 zorder 设置为 1,以表示它应该在我稍后将使用更高的 zorder 绘制的数据点之后。
# Set figure size
fig, ax = plt.subplots(figsize=(10,10))
ax.set_aspect('equal')
# Import NYC Neighborhood Shape Files
nyc_full = gpd.read_file('./shapefiles/neighborhoods_nyc.shp')
nyc_full.plot(ax=ax, alpha=0.4, edgecolor='darkgrey', color='lightgrey', label=nyc_full['boro_name'], zorder=1)
3。在城市地图上绘制坐标
随着城市地图的绘制,我们现在可以将我们的纬度和经度坐标添加到我们的绘图中!我们所要做的就是在我们的 geopandas 数据帧上调用.plot()
,并将 zorder 设置为 2,以便我们的坐标位于城市地图的顶部。你可以自定义地图的颜色方案,matplotlib 的颜色图中有很多可供选择。
geo_df.plot(ax=ax, column=cluster, alpha=0.5, cmap='viridis', linewidth=0.8, zorder=2)
4。绘制聚类中心
为了绘制聚类中心,您必须首先将我们的 geopandas 数据框架中的聚类中心列转换为一系列地理点。在这之后,我们可以在地图上绘制这个,并将设置为 3,这样聚类中心就可见了,并且在其他所有东西的上面。
if centers is not None:
centers_gseries = GeoSeries(map(Point, zip(centers[:,1], centers[:,0])))
centers_gseries.plot(ax=ax, alpha=1, marker='X', color='red', markersize=100, zorder=3)
5。显示并保存图形
最后,通过调用plt.show()
显示图表,并向图表添加标签。还有,别忘了保存!
plt.title(title)
plt.xlabel('longitude')
plt.ylabel('latitude')
plt.show()
if filename is not None:
fig.savefig(f'{filename}', bbox_inches='tight', dpi=300)
就是这样!下面是整个函数的代码片段。
摘要
以下是查找和可视化地理位置数据聚类的步骤的快速回顾:
- 选择一种聚类算法,并将其应用于您的数据集。
- 将您的 pandas 地理位置坐标和聚类中心数据框架转换为 geopandas 数据框架。
- 下载并导入城市或地区的形状文件。
- 在城市地图上标出地理坐标。
- 绘制聚类中心。
- 显示并保存剧情!
可视化地理位置聚类是理解数据的一种很好的方式。您还可以使用plot_geolocation_by_cluster
函数来可视化不同的聚类算法如何分割您的数据集。要访问完整的源代码,请点击下面参考文献下的“完整笔记本”选项。
参考
寻找生物数据集来启发你的下一个生物信息学项目
无论是基因组学还是脑电图数据,网上有大量免费的数据集!
信息专家在整个生物学领域提供不可替代的专业知识。毫不奇怪,大学为学生提供越来越多的机会来学习这些技术。虽然大学课程和在线课程提供了非常需要的背景,但它们可能不会给你提供足够的实践机会。毕竟,如果你想成为一名生物信息学家,真实数据集的经验是非常宝贵的。
随着许多新技术的突破,许多新技术的成本下降了。因此,科学家们被数十亿字节的生物数据淹没了。从 EEG 大脑信号到基因组信息的一切都需要处理和分析。显然需要专家来理解和处理这些数据。如果你正开始你的生物信息学之旅,本指南将为你提供一些拥有大型数据集的资源来发展你的技能。
如果您正在寻找教程来学习这些数据所需的基础知识和技能,我推荐以下资源:
开放神经系统:大脑记录
还记得埃隆·马斯克最近对他的脑机接口公司 Neuralink 的更新吗?神经科学的许多子领域的研究人员使用类似的、尽管不那么高通量的技术来测量大脑活动。这对于了解大脑如何对不同刺激做出反应的研究尤其重要,甚至对于癫痫发作的预测也是如此。
如果你有兴趣了解如何解码这些信号以及开发预测模型,你会在这里找到大量的数据集。你可以找到脑电图(EEG)、脑磁图(MEG)、皮层脑电图(ECoG)和颅内脑电图(iEEG)的链接。
这些数据集的处理通常发生在 MATLAB 和 Python 中。
作者截图
RNA 测序数据集
随着技术的进步,高通量 RNA 测序的成本大幅下降。因此,在许多不同的测序平台上,有一个公众可访问的数据集的聚宝盆。我建议关注 Illumina 平台,因为它是当今许多研究人员最常见的选择。您可能遇到过不同的 Python 和 R 包来处理 RNA-seq 数据。现在是测试这些技能的时候了,将这些技能添加到你的投资组合中。
如果你对大脑特别感兴趣,艾伦脑图计划有几个数据集可用。否则,你会通过基因表达综合数据集库找到不同生物的数千个数据集。
作者截图|所有这些数据就等着你去细读了!
微生物组序列数据集
随着 RNA-seq 技术的出现,对微生物组的兴趣增加了。基因表达综合数据库中有许多数据集,用于测量胃肠、粪便、唾液或环境微生物组。也有大量的工具作为 R 包提供给你开放的数据集来练习。看看这些 R 包:
- 策划元数据数据
- HMP16SData :人类微生物组项目 16S 数据
- 微生物组
单细胞 RNA 测序数据集
分子转录组学最显著的创新之一是单细胞 RNA 测序。它让我们能够评估单个细胞中哪些基因是活跃的,让我们能够对它们进行表征和分组。因为这种技术相对年轻,所以可用于实践的数据集较少。尽管如此,结合可用的教程,它们足以练习数据处理、分析和可视化。这些数据集可以在这里找到。R 中的 scRNAseq 包也允许您访问这些数据。
你还在等什么?网上有许多免费的课程和教程可以与这些数据集配对!你可以从今天开始!
快乐数据挖掘!
在时间序列数据中寻找相关性
理解 ML
如何找到不同长度的时间序列向量与预测结果之间的相关性?
如果你曾经做过数据分析,你很可能知道数据相关性的概念。有许多方法可以计算数据之间的相关性,其中大多数已经在流行的数据科学工具包中实现。今天我想向大家展示的是如何找出不同长度的时间序列向量与目标结果(或任何其他值)之间的相关性。
当试图设计依赖于时间序列数据的模型时,这可能会很方便。我给你举个例子。假设您正在处理天气数据。你的目标是预测未来某一时刻的人口数量。这些人口并不依赖于当前的天气状况,而是依赖于过去。
数据样本
这是我们数据集中的一些样本。它显示了五个连续的时间段以及每个时间段的结束时间。我们的目标是预测每个时间段的人口数量。通常为了解决这个问题,我们需要设计某种模型。模型本身并不那么重要,重要的是找到我们应该把什么样的特性注入其中。
我们知道,当前的人口数量并不取决于当前的条件,而是取决于整个生命周期的条件。我们可以搜索关于该主题的出版物,并尝试计算出正确的数据量。过了一会儿,我们认为我们的人口可能取决于过去 4 周的温度、6 周的降水量和过去 2 周的湿度。这没问题,但是有没有更好的方法来找出数据中的相关性呢?我们甚至可以检查我们的月经是否正确吗?
标准相关性的问题
当考虑数据相关性时,我们通常会考虑一个数字和另一个数字之间的相关性。偶尔,我们可能会计算分类变量之间的相关性。这个案子不一样。如果我们考虑一系列这样的温度:
[21,22,21,25,19]
每个数字出现的顺序很重要。如果我们想用一些累计值(比如平均值或移动平均值)来代替整个系列,那是行不通的。
[21, 25, 19, 22, 21]
这给出了相同的平均值,但清楚地显示了不同的情况。另一个问题是选择向量的正确长度。当提供一个更长的向量时,比较信息增益就不那么容易了。
[16, 18, 22, 15, 17, 21, 22, 21, 25, 19]
常见的做法是为模型提供一个很长的向量,让它自己找出相关性。这是可行的,但在时间序列的情况下,我们通常没有那么多的训练数据(我们不能只是创造更多)。即使我们收集过去 5 年中每天的数据,我们也有(平均)1826 个(T2)记录。如果你想创建一个输入向量很长的深度模型,这个值太低了。
预测能力评分(PPS)
最近,一种不同的想法越来越受欢迎。它被称为预测能力得分(PPS ),基于计算数据集中每个属性的预测能力。预测能力是对决策树模型在预测变量的帮助下预测目标变量的成功程度的衡量。
当你计算一个变量(A)的 PP 预测另一个变量(B)时,我们必须把我们的变量 B 当作目标,把 A 当作唯一的特征。之后,我们将创建一个决策树(回归器或分类器)并计算有意义的指标(如回归问题的 MAE 或分类的 F1)。
基本上,你必须对每一对变量重复这个过程。分数的标准化是可选的,因为通常原始分数已经有了意义。在大多数情况下,您不必为所有可能的特性组合计算 PPS。只计算每个特征和目标之间的 PPS 就够了。在我们的示例中,我们将计算成对的 PPS:(温度,人口), (Perc,人口),(湿度,人口)。
这种方法的唯一问题是它不能解决我们的问题:)
扩展 PPS
如果我们看一下标准 PPS,我们能够检查一个变量的预测能力。我们的问题有点不同,让我给你看看是什么样子的。
我们的目标是人群,标准的 PPS 方法只会显示每个特征的一个项目的分数。
没关系,但我们可以做得更好。试着找出这个向量和目标的最后 x 值之间的关联。让我们从最后一行开始,因为对于这一行,我们有以前的数据。
前 4 行仍然有问题,因为我们没有前 5 行来获取数据。有两种解决方案:
- 删除这些行
- 创建数据
第一个选项很简单,通常,当您有超过 100 行时,它不会影响预测的精度。如果您想使用第二种方法,您可以使用移动平均或其他方法来填充数据。目前,我们只打算采用第一种方案。
如何用 sklearn 创建决策树?
要创建 DT,我们可以使用sklearn
库并执行如下代码:
from sklearn.tree import DecisionTreeRegressor
from sklearn.model_selection import cross_val_score
X = [
[22, 26, 29, 27, 22],
[15, 22, 26, 29, 27],
[19, 15, 22, 26, 29],
[25, 19, 15, 22, 26]
]
Y = [76, 12, 53, 352]regressor = DecisionTreeRegressor(random_state=0)
score = cross_val_score(
regressor,
X,
Y,
cv=2, #change that base on the data size
scoring='neg_mean_absolute_error'
)
因此,我们应该得到一些负的 MAE 值。
我们要计算什么?
现在的问题是“我们应该使用多少以前的数据点来获得最好的分数?”。我们可以创建不同长度的向量,并比较每个向量的得分。
如果我们只查看温度特征,我们应该得到如下数据集
Temp_five = [
[22, 26, 29, 27, 22],
[15, 22, 26, 29, 27],
[19, 15, 22, 26, 29],
[25, 19, 15, 22, 26]
]
Temp_four = [
[26, 29, 27, 22],
[22, 26, 29, 27],
[15, 22, 26, 29],
[19, 15, 22, 26]
]
Temp_three = [
[29, 27, 22],
[26, 29, 27],
[22, 26, 29],
[15, 22, 26]
]
Temp_two = [
[27, 22],
[29, 27],
[26, 29],
[22, 26]
]
目标总是不变的,唯一改变的是一组特性。此时,我们计算每个长度的分数,并比较结果以获得临时向量的正确长度。
让我们假设结果是这样的:
基于此,我们可以确定温度向量的正确长度为 4 (最小误差)。现在,我们对每一个单独的特征执行类似的过程,并得出最终的特征集。
粗体选择显示一个目标为 76 的训练样本的一组特征。设计 NN 时,我们可以假设 14 个(4 个温度+ 2 个 Perc + 8 个湿度)输入特性。因此,我们针对底部 3 个样本的训练集将如下所示:
X = [
[26, 29, 27, 22, 0, 0, 55, 88,
97, 75, 53, 40, 38, 36],
[22, 26, 29, 27, 0, 0, 100, 55,
88, 97, 75, 53, 40, 38],
[15, 22, 26, 29, 0, 0, 95, 100,
55, 88, 97, 75, 53, 40]
]Y = [
76,
12,
53
]
现实生活中的例子
如果您想知道这种方法在真实数据中的表现,这里有一个例子:
每一列代表一个特征,每一行代表从该特征构建的向量的不同长度。在这个例子中,我计算了每个特征的 3 到 51 个元素之间的向量的 MAE。
我应该选择哪些功能?
选择正确的功能有几个规则。第一个(也是最明显的一个)是选择 MAE 得分最低的特性。我们可以对这些列进行排序,并开始选择具有最低值的列。问题是“有多少列?”。答案可能不会让你惊讶,看情况:)。当您有更多的训练数据时,您可以允许您的模型更大,因此,选择更多的功能。如果你只有少量的训练数据,你就不能设计一个有> 200 个特征的模型,因为你进入了维数灾难的领地。
另一件事是每列的长度。正如你在这个例子中看到的,reanalysis_specific_humidity_g_per_kg
是2 minimum values of MAE
的一个有用的特性(我们最好的特性之一)。当我们遇到这种情况时,我们通常选择较短的向量。所以决定选择长度为 14 而不是 27 的向量,即使两者具有相同的 MAE (30)值。
另一个要讨论的是最后一栏。有些列不应该被视为矢量,而应该作为一个单独的特征来使用。weekofyear
列包含给定训练示例的周数。向模型发送周数向量是没有意义的,因为它总是每周增加 1。但是看一下这个专栏仍然很重要,因为它清楚地显示了长度是如何影响准确性的。
一些权衡
有时,在选择向量长度时,您可能需要做出一些权衡。看特征 15 ( station_min_temp_c
)。它的长度为 3,得分为 35 MAE,然后长度为 26,得分高于 35 MAE。两个分数之间的差别只有 1 并且我们增加了 23 个额外的特性只是为了得到那 1 MAE。你必须记住,当构建一个具有多个特征的模型时,输入向量的最终长度是你选择的所有向量的总和。将输入长度增加 23 会迫使您拥有更多训练数据和更大的模型。在这种情况下,我个人会选择 3 个项目向量而不是 26 个,或者只是测试两个不同的模型。如果从 3 个项目变成 26 个项目时结果没有改善,你应该使用 3,因为它产生一个更简单的假设(根据奥卡姆剃刀规则)。
选择没有扩展 PPS 的功能时出错
我想告诉你的最后一件事是,如果没有这种方法,选择特征时是多么容易出错。让我们看看第 4 列(reanalysis_dew_point_temp_k
)和第 11 列(reanalysis_tdtr_k
)。你只要看着它们就能知道第 4 列有更好的预测能力。但是如果你手动(或随机)选择这些向量的长度,你可能会使reanalysis_dew_point_temp_k
比reanalysis_tdtr_k
更差。如果事先不知道这个特性,您可以选择它的长度为 3,这样我们得到的 MAE 为 38,比第 21 行第 11 列的 37 还要差。这样,你就把你最好的特性之一变得和你最差的特性一样有用了。
结论
PPS 的扩展版本是一个强大的工具,用于在构建模型时选择一组要素。有时,即使没有这方面的专业知识,也可能导致对数据事件的更深入理解。即使可能需要一段时间来计算不同长度的输入向量的所有 PPS,这也是值得的。EDA ( 探索性数据分析)仍然是每一个数据科学/机器学习项目中最重要的部分之一,你不应该跳过它,或者仅仅局限于默认的工具集。
在 Python 中寻找大熊猫的远亲
作者通过 Flickr 拍摄的照片
计算机科学和数据科学中偶尔会遇到的一个问题是,需要在一组唯一的数字中找到一对彼此相距最远的数字。这些数字对被称为距离对,或最大距离对。
谢天谢地,有了 Python 和 Pandas,我们可以相对容易地在一组唯一值中找到距离较远的一对。让我们从导入 NumPy 和 Pandas 开始,它们将用于生成和操作我们的数据。
import numpy as np
import pandas as pd
接下来,我们将随机生成 7 个介于 100000 和 999999 之间的整数作为one_dim
。
np.random.seed(123)
one_dim = np.random.randint(100000, 999999, size=7)
one_dim*array([873630, 377869, 128030, 117730, 292476, 294278, 770737])*
np.random.seed(123)
语句保证随机数生成器将产生可再现的值。变量one_dim
是一个 NumPy 数组,其中有 7 个随机整数,代表一组一维值,用于检查最大距离对。
使用以下步骤可以找到距离远的对:
- 取集合与其自身的笛卡尔积,并对每一对应用距离算法。
- 求笛卡尔积距离集中的最大值。
- 确定原始集合中哪些对产生最大距离。
集合与其自身的笛卡儿积可以表示为熊猫数据帧,其中数据帧的索引和列标题是集合中的值。
df = pd.DataFrame(index=test, columns=test)
df+------+------+------+------+------+------+------+------+
| |**873630**|**377869**|**128030**|**117730**|**292476**|**294278**|**770737**|
+------+------+------+------+------+------+------+------+
|**873630**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**377869**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**128030**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**117730**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**292476**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**294278**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**770737**| NaN | NaN | NaN | NaN | NaN | NaN | NaN |
+------+------+------+------+------+------+------+------+
这将创建一个 n x n 数据帧,其中 n 是集合中值的数量。因为这个数据帧是在没有数据的情况下创建的,所以所有的值都是空的(NaN)。
下一步是应用距离算法abs(a - b)
,其中a
和b
都是原始集合中的值。将此算法应用于数据帧中的每个单元格相当于计算原始集合中每个值之间的距离。
我们通过使用 DataFrame 对象的apply()
方法来实现这一点,其中的参数是一个可调用的函数。由于距离算法很简单,一个λ函数就足够了。使用apply()
总是比使用嵌套的for
循环更快,因为apply()
是一个同时应用于一列或一行中每个值的矢量化操作。本质上,apply()
是一个 O(n)时间操作,其中 n 与行数成比例,嵌套的for
循环是一个 O(n)时间操作。
diff = df.apply(lambda col: abs(col.name - col.index))
diff+------+------+------+------+------+------+------+------+
| |**873630**|**377869**|**128030**|**117730**|**292476**|**294278**|**770737**|
+------+------+------+------+------+------+------+------+
|**873630**|0 |495761|745600|755900|581154|579352|102893|
|**377869**|495761|0 |249839|260139|85393 |83591 |392868|
|**128030**|745600|249839|0 |10300 |164446|166248|642707|
|**117730**|755900|260139|10300 |0 |174746|176548|653007|
|**292476**|581154|85393 |164446|174746|0 |1802 |478261|
|**294278**|579352|83591 |166248|176548|1802 |0 |476459|
|**770737**|102893|392868|642707|653007|478261|476459|0 |
+------+------+------+------+------+------+------+------+
这做了什么?apply()
方法对每一列执行 lambda 函数,并从列的索引(向量)中减去列的名称(标量值)。
这用原始组中每对之间的绝对值距离填充数据帧。注意对角线上的所有值都是 0,因为一个数减去它自己就是 0。这也表明数据帧被分成两部分,每一部分是另一部分的镜像三角形。这意味着最大距离在数据帧中出现两次,每个三角形一次。
下一步是找到最大距离。这是通过调用 DataFrame 的max()
方法来完成的,首先在每一列上,然后在结果序列的每个值上。
max = diff.max().max()*755900*
现在我们知道了最大距离,最后一步是确定一维集合中的哪两对形成最大距离。因为数据帧的索引和列标题是一维集合中的值,所以数据帧可以被过滤为最大距离值。
因为最大距离值在数据帧中出现两次,所以过滤数据帧将产生 2 x 2 数据帧,其中索引和列标题中的值都是距离对。
filtered = (
diff[diff == max]
.dropna(how='all')
.dropna(how='all', axis=1)
)
filtered+------+------+------+
| |**873630**|**117730**|
+------+------+------+
|**873630**| NaN |755900|
|**117730**|755900| NaN |
+------+------+------+
最后,获取距离对就像获取过滤后的数据帧的索引一样简单。
pairs = filtered.index.to_list()
pairs*[873630, 117730]*
这很有效,是一个非常有效的解决方案,但是只适用于一维值的集合。如果我们想将这种方法应用于一组二维值呢?事实证明这并没有什么不同,只需要小小的改动。让我们从生成一组新的二维值开始。
two_dim = np.random.randint(100, size=(7, 2))
two_dim*array([[83, 57],
[86, 97],
[96, 47],
[73, 32],
[46, 96],
[25, 83],
[78, 36]])*
与一维情况相比,第一个不同之处在于数据帧索引必须是一维的。我们可以通过创建一个表示我们的二维值集的参考数据帧来解决这个问题,并在笛卡尔积中使用这个参考数据帧的索引。
ref = pd.DataFrame.from_records(two_dim, columns=('x', 'y'))
ref+----+----+----+
| | **x** | **y** |
+----+----+----+
| **0** | 83 | 57 |
| **1** | 86 | 97 |
| **2** | 96 | 47 |
| **3** | 73 | 32 |
| **4** | 46 | 96 |
| **5** | 25 | 83 |
| **6** | 78 | 36 |
+----+----+----+
接下来,我们将使用参考数据帧的索引创建笛卡尔乘积数据帧。
df2 = pd.DataFrame(index=ref.index, columns=ref.index)
df2+------+------+------+------+------+------+------+------+
| |**0** |**1** |**2** |**3** |**4** |**5** |**6** |
+------+------+------+------+------+------+------+------+
|**0** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**1** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**2** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**3** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**4** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**5** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
|**6** | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
+------+------+------+------+------+------+------+------+
与一维情况相比的第二个不同之处是,lambda 函数需要换成二维距离算法。这只是勾股定理。
diff2 = df2.apply(
lambda col: np.sqrt(
abs(ref.iloc[col.name]['x'] - ref.iloc[col.index]['x']) ** 2 +
abs(ref.iloc[col.name]['y'] - ref.iloc[col.index]['y']) ** 2
)
)
diff2+------+------+------+------+------+------+------+------+
| |**0** |**1** |**2** |**3** |**4** |**5** |**6** |
+------+------+------+------+------+------+------+------+
|**0** |0.0000|40.112|16.401|26.926|53.759|63.561|21.587|
|**1** |40.112|0.0000|50.990|66.287|40.012|62.586|61.522|
|**2** |16.401|50.990|0.0000|27.459|70.007|79.605|21.095|
|**3** |26.926|66.287|27.459|0.0000|69.462|70.036|6.4031|
|**4** |53.759|40.012|70.007|69.462|0.0000|24.698|68.000|
|**5** |63.561|62.586|79.605|70.036|24.698|0.0000|70.838|
|**6** |21.587|61.522|21.095|6.4031|68.000|70.838|0.0000|
+------+------+------+------+------+------+------+------+
这需要一些解释。这里的 lambda 函数就是勾股定理:c = √(abs(a) + abs(b)),但是参考数据帧中的 x 和 y 值是通过它们的索引值——ref.iloc[col.name]['x']
(标量值)和ref.iloc[col.index]['x']
(向量)取的。
接下来,我们将得到最大值,和以前一样。
max = diff2.max().max()
max*79.605*
获得距离对的工作方式相同,但是笛卡尔乘积数据帧的索引值需要换成参考数据帧中相应的 x 和 y 值。
filtered2 = (
diff2[diff2 == max]
.dropna(how='all')
.dropna(how='all', axis=1)
)
filtered2+------+------+------+
| |**2** |**5** |
+------+------+------+
|**2** | NaN |79.605|
|**5** |79.605| NaN |
+------+------+------+
最后,得到距离较远的一对。
pairs = [ref.iloc[idx].to_list() for idx in filtered2.index]
pairs*[[96, 47], [25, 83]]*
就是这样!
为 CharityML 项目寻找捐助者
Udacity 数据科学家纳米学位计划项目
https://www . ledgerinsights . com/WP-content/uploads/2019/09/charity-810 x476 . jpg
这个项目是数据科学家纳米学位项目 Udacity 的一部分:为 CharityML 项目寻找捐赠者,目标是对美国人口普查收集的数据应用监督学习技术,以帮助一个虚构的慈善组织 CharityML 确定最有可能为他们的事业捐款的人
让我们从使用 CRISP-DM 流程(数据挖掘的跨行业流程)开始:
- 业务理解
- 数据理解
- 准备数据
- 数据建模
- 评估结果
- 部署
业务理解
CharityML 是一个虚构的慈善组织,它希望通过向所在地区的居民发送信件来扩大潜在的捐助者群体,但只发送给最有可能捐款的人。在向社区中的人们发送了近 32000 封信后,CharityML 确定他们收到的每一笔捐款都来自年收入超过 50000 美元的人。因此,我们的目标是建立一个算法,以最好地识别潜在的捐赠者,并减少发送邮件的开销
数据理解
数据集由 45222 条记录组成,来自 UCI 机器学习库。该数据集由 Ron Kohavi 和 Barry Becker 捐赠,发表在文章*“提高朴素贝叶斯分类器的准确性:决策树混合”*中
数据集属性
以前 5 条记录为例
概括起来,其特点是:
- 年龄:连续
- 工作类:私人,自我雇佣非公司,自我雇佣公司,联邦政府,地方政府,州政府,无薪,从未工作
- 教育水平:学士、部分大学、11 年级、HS-grad、Prof-school、Assoc-acdm、Assoc-voc、9 年级、7-8 年级、12 年级、硕士、1-4 年级、10 年级、博士、5-6 年级、学前
- 教育编号:连续
- 婚姻状况:已婚配偶、离婚、未婚、分居、丧偶、无配偶、已婚配偶
- 职业:技术支持、工艺维修、其他服务、销售、行政管理、专业教授、清洁工、机器操作员、行政文员、农业渔业、运输搬运、私人服务、保安服务、武装部队
- 关系:妻子、亲生子女、丈夫、非家庭成员、其他亲属、未婚
- 种族:黑人、白人、亚洲太平洋岛民、美洲印第安人、爱斯基摩人、其他
- 性别:女,男
- 资本收益:连续
- 资本损失:连续
- 每周小时数:连续
- 母国:美国、柬埔寨、英国、波多黎各、加拿大、德国、美国外围地区(关岛-USVI 等)、印度、日本、希腊、韩国、中国、古巴、伊朗、洪都拉斯、菲律宾、意大利、波兰、牙买加、越南、墨西哥、葡萄牙、爱尔兰、法国、多米尼加共和国、老挝、厄瓜多尔、台湾、海地、哥伦比亚、匈牙利、危地马拉、尼加拉瓜、苏格兰、泰国、南斯拉夫、萨尔瓦多、特立尼达和多巴哥&秘鲁、香港、荷兰
- 收入 : > 50K,< =50K
正如我们从初步分析中看到的,我们的数据集是不平衡的,因为大多数人的收入不超过 50,000 美元,因此,正如我们将在天真预测部分更好地解释的那样,这可能会对我们将要开发的模型的准确性产生影响
对数据的初步分析
变换偏斜的连续特征
算法可能对这些值的分布很敏感,如果范围没有被适当地标准化,算法可能表现不佳,因此通常的做法是对数据应用对数变换,以便非常大和非常小的值不会对学习算法的性能产生负面影响。对于人口普查数据集,有两个特征符合这一描述:capital-gain
和capital-loss
偏态分布capital-gain
和capital-loss
对数变换分布capital-gain
和capital-loss
归一化数字特征
对数据进行缩放不会改变每个要素分布的形状。我们将在age
、education-num
、hours-per-week
、capital-gain
和capital-loss
上使用sk learn . preprocessing . minmax scaler来实现这一点
准备数据
使用一键编码方案转换分类变量
独热编码示例
与往常一样,我们现在将数据(包括要素及其标签)分成训练集和测试集。80%的数据将用于训练,20%用于测试
数据建模
生成朴素预测器的目的只是为了显示没有任何智能的基础模型是什么样子。如前所述,通过观察数据的分布,可以清楚地看出,大多数人的年收入不到 5 万美元。因此,总是预测'0'
(即个人收入低于 50k)的模型通常是正确的
朴素预测结果
数据集不平衡的事实也意味着精确度没有太大帮助,因为即使我们获得高精确度,实际预测也不一定那么好。在这种情况下通常推荐使用精确和召回
让我们比较 3 个模型的结果:
- 决策树
- 支持向量机
- AdaBoost
性能指标
混淆矩阵
如前所述,我们关注的是模型精确预测那些收入超过 5 万美元的人的能力,这比模型回忆那些人的能力更重要。就Accuracy
和F-score
而言,AdaBoostClassifier 是对测试数据表现最好的一个。此外 AdaBoostClassifier 的训练速度也非常快,如时间训练集大小直方图所示
现在我们将使用 sklearn.grid_search 对模型进行微调。GridSearchCV
模型调整
最后,我们可以找出哪些特征提供了最强的预测能力。通过只关注少数关键特征和目标标签之间的关系,我们简化了对现象的理解。我们可以使用feature_importance_
来实现
评估结果
我们的目标是预测一个人的年收入是否超过 5 万美元,因为满足这一要求的人更愿意向慈善机构捐款。在清理数据并将它们建模为准备用于 ML 训练的数据集之后,我们测试了三个不同模型的性能。考虑到 F-1 评分最佳模型是 AdaBoostClassifier
赞助一些 真正的慈善 组织
我想利用这篇文章谈谈我真正关心的一些真正的慈善 组织:
意大利多发性硬化症协会(AISM)是一个治疗多发性硬化症的非营利组织
T21 急救组织是一个人道主义的非政府组织,为战争、贫困和地雷的受害者提供免费医疗
救助儿童会通过更好的教育、医疗保健和经济机会来提高儿童的生活质量。它还在自然灾害、战争和其他冲突期间提供紧急援助
https://www.savethechildren.it/
澄清一下,我和这家公司没有任何商业关系
**注意:**代码可以在这个 github 仓库中找到
使用机器学习发现重复的 Quora 问题
埃文·丹尼斯在 Unsplash 上的照片
Quora 是一个令人惊叹的平台,互联网公司可以在这里提问、回答、关注和编辑问题。这使人们能够相互学习,更好地了解世界。每个月大约有 1 亿人访问 Quora,所以很多人问类似措辞的问题也就不足为奇了。quora 让它的关注者为同一个问题写一个答案并不是更好的一面。因此,如果有一个系统能够检测到一个新问题与已经回答的问题相似,那就更好了。
所以我们的问题陈述是预测一对问题是否重复。我们将使用各种机器学习技术来解决这个问题。这个博客不是一个完整的代码演练,但是我将解释我用来解决这个问题的各种方法。你可以从我的 Github 库看看我的代码。
一些业务限制
- 错误分类的成本可能非常高。也就是说,如果一个用户问了一个特定的问题,而我们提供了其他的答案,那就不好了。会影响生意的。这是最重要的约束。
- 我们想要一对问题被复制的概率,这样你就可以选择任何选择的阈值。因此,根据使用情况,我们可以改变它。
- 我们没有任何延迟要求。
- 可解释性是部分重要的。即我们不想让用户知道为什么一对问题是重复的。但是如果我们知道会更好。
绩效指标
这里我们有一个二元分类任务,我们想预测一对问题是否重复。我们将使用日志损失作为衡量标准。有意义因为我们预测的是概率值,所以使用对数损失作为度量是有意义的。这是我们的主要 KPI(关键绩效指标)。我们还将使用混淆矩阵来衡量绩效。
对数损失只不过是可能性乘积对数的负值
探索性数据分析
数据
我们有大约 404290 个数据点和 6 列。这 6 列/特征是:
- id:问题对的唯一 id
- qid1:第一题的 id。
- qid2:第二个问题 id
- 问题 1:第一个问题
- 问题 2:第二个问题
- is_duplicate:两者是否重复。
当最初接近时,我检查丢失值。我发现 3 行中有缺失值(在问题 1 和问题 2 中)。所以我放弃了那几行。接下来,我检查任何重复的行。但是没有这样的争吵。
目标变量分析
目标分布
很明显,我们有不平衡的数据,重复问题的数量超过了非重复问题。
问题分析
在分析了这些问题后,我得出了以下结论:
独特问题与重复问题
Total number of unique questions is 537929
Number of questions that repeated more than 1 time is 111778 which is 20.779322178205675%
The maximum number of times a question occured is 157
之后,我试着绘制了问题出现次数的直方图和问题数量的日志。我们可以看到,大多数问题的出现频率大约为< 60. We can see there is 1 question that occurs 167 times, 1 question that occurs 120 times 1 question that occurs 80 times, and so on.
log histogram of question appearances
Now we have a broad understanding of data. Next, I created some basic feature features before preprocessing the data.
Basic Feature Engineering
I created the following features:
- freq _ qid 1= qid 1 的频率。
- freq _ qid 2= qid 2 的频率,问题 1 出现的次数。
- Q1 len= Q1 的长度
- q2len= Q2 的长度
- q1_n_words =问题 1 的字数
- q2_n_words =问题 2 的字数
- word_Common =(问题 1 和问题 2 中常见唯一词的个数)。
- word_Total =(问题 1 总字数+问题 2 总字数)
- word _ share=(word _ common)/(word _ Total)
- freq _ Q1+freq _ Q2= qid 1 和 qid2 的频率总和
- freq _ Q1-freq _ Q2= qid 1 和 qid2 的绝对频率差
工程特征分析
相似和不相似问题中的单词共享
我们可以看到,随着“份额”这个词的增加,出现类似问题的可能性越来越大。我们知道,对于 pdf 来说,它们重叠的越多,区分类别的信息就越少。从直方图中,我们可以看到单词 share 具有一些区分相似和不相似类的信息。
相似和不相似问题中的常用词
我们可以看到,common_words 没有足够的信息来区分类别。重复和非重复问题的 word_common 的历史图重叠。没有太多的信息可以检索,因为大多数的 pdf 文件是重叠的。
高级特征工程
现在,我们将使用现有数据创建一些高级功能。在此之前,我们将清理我们的文本数据。作为文本预处理的一部分,我已经删除了停用词、标点符号、特殊字符如“₹",“$”,"€”等,并且我还应用了词干来获得更多的概括。接下来,我设计了以下功能。
注意:在下面的特征中, tocken 表示通过拆分文本获得的单词,单词表示不是停用词的单词。
- CWC _ min:Q1 和 Q2 常用字数与最小字数长度的比值
cwc_min =常用字数/ (min(len(q1_words),len(q2_words)) - CWC _ max:common _ word _ count 与 Q1 和 Q2 最大字数长度的比值
CWC _ max = common _ word _ count/(max(len(Q1 _ words),len(q2_words)) - CSC _ min:common _ stop _ count 与 Q1 和 Q2 停车计数最小长度之比
CSC _ min = common _ stop _ count/(min(len(Q1 _ stops),len(q2_stops)) - CSC _ max:common _ stop _ count 与 Q1 和 Q2
停车计数最大长度的比值CSC _ max = common _ stop _ count/(max(len(Q1 _ stops),len(q2_stops)) - CTC _ min:common _ token _ count 与 Q1 和 Q2 令牌计数的最小长度之比
CTC _ min = common _ token _ count/(min(len(Q1 _ tokens),len(q2_tokens)) - CTC _ max:common _ token _ count 与 Q1 和 Q2 令牌计数最大长度之比
CTC _ max = common _ token _ count/(max(len(Q1 _ tokens),len(q2_tokens)) - last_word_eq :检查两个问题的最后一个单词是否相等
last _ word _ eq = int(Q1 _ tokens[-1]= = Q2 _ tokens[-1]) - first_word_eq :检查两个问题的首字是否相等
First _ word _ eq = int(Q1 _ tokens[0]= = Q2 _ tokens[0]) - abs_len_diff : Abs。长度差
ABS _ len _ diff = ABS(len(Q1 _ tokens)—len(Q2 _ tokens)) - mean_len :两个问题的平均令牌长度
mean _ len =(len(Q1 _ tokens)+len(Q2 _ tokens))/2 - 有趣的部分来了。模糊率取决于 Levenshtein 距离。直观地说,如果从一个实例变成另一个实例所需的相应编辑很大,模糊比率就会很小。也就是说,大多数相似词的模糊率是相似的。
eg: s1 = “mumbai is a great place” s2 = "mumbai is a nice place"
fuzz ratio = 91
- 模糊比率在某些情况下不能解决问题。
fuzz.ratio("YANKEES", "NEW YORK YANKEES") ⇒ 60
fuzz.ratio("NEW YORK METS", "NEW YORK YANKEES") ⇒ 75
s1 和 s2 的意思相同。但是它们的起毛率可以更小。所以我们会发现部分句子的比率会很高。在这种情况下,它被称为模糊部分比率。
fuzz.partial_ratio("YANKEES", "NEW YORK YANKEES") ⇒ 60
- token_sort_ratio :在其他一些情况下,甚至 fuzz partial ratio 也会失败。
例如:
fuzz.partial_ratio("MI vs RCB","RCB vs MI") ⇒ 72
实际上这两个句子意思相同。但是模糊率给出了较低的结果。因此,更好的方法是对令牌进行排序,然后应用模糊比率。
fuzz.token_sort_ratio("MI vs RCB","RCB vs MI") ⇒ 100
- token_set_ratio :还有另一种类型的模糊比率,即使在上述所有方法都失败的情况下,它也会有所帮助。就是令牌集比率。
为此,我们必须首先找到以下内容:
t0 ->找出 sentance1 和 sentance2 的交集词并排序。
t1-> t0+sentance 1 中的其余令牌
T2-> t0+sentance 2 中的剩余令牌
tocken _ set _ ratio = max(fuzz _ ratio(to,t1),fuzz_ratio(t1,T2),fuzz_ratio(t0,t2))
- longest _ substr _ Ratio:Q1 和 Q2 令牌计数中最长公共子串长度与最小长度之比。
s1-> hai, today is a good day
s2-> No, today is a bad day
这里最长的公共子串是“今天是一个”。所以我们有 longest _ substring _ ratio = 3/min(6,6)= 0.5
longest _ substr _ ratio = len(最长公共子串)/ (min(len(q1_tokens),len(q2_tokens))
更多数据分析
现在我们将绘制重复句和非重复句的词云。为了更好地理解,我在删除了停用词后绘制了它。
重复句子的词云
非重复句子的词云
单词越大,语料库中的重复频率就越大。我们可以看到,像唐纳德·特朗普、卢比、最佳方式这样的词在重复句中经常重复,而像差异、印度、使用等这样的词在非重复句中经常重复。
’ ctc_min ‘,’ cwc_min ‘,’ csc_min ‘,’ token_sort_ratio '的配对图
配对图
从 pair 图中,我们可以看到,在区分重复和非重复句子的所有特征中,都有一些有用的信息。其中 token sort ratio 和 ctc min 做得更好。
问题之间字数的绝对差异
问题之间字数的绝对差异
我们可以看到,大多数问题的区别就在于一个词。差别巨大的问题只有极少数。
TSNE 可视化
接下来,我尝试对数据进行低维可视化。我随机采样了 5000 个数据点,并使用 TSNE 进行低维可视化。我只使用了我们最近设计的功能来观察它对分析的影响。我们看到,在一些地区,阶级和阶层划分得很清楚。因此,我们可以说,现在我们的模型中有很多信息来执行良好的分类。
注意:你总是可以试验更多的数据点和困惑(如果你有足够的计算能力),因为它会给出更多的信息。
TSNE 可视化
列车测试分离
我们做了 70:30 的分割。也就是说,我们把 70%的数据点用于训练,剩下的 30%用于测试。
向量化文本数据
在使用数据创建模型之前,我们必须对文本数据进行矢量化。为此,我们使用了两种方法
- TFIDF 矢量化
- TFIDF 加权手套矢量化
在将这些矢量与我们创建的初始特征合并后,我们保存了单独的文件。
机器学习模型
让我们进入这个博客最有趣的部分——创建机器学习模型。现在我们有两个数据帧用于训练——一个使用 tfidf,另一个使用 tfidf 加权手套向量。
逻辑回归
TFIDF 功能:
在对 TFIDF 数据进行训练逻辑回归时,我们最终得到训练的对数损失约为 0.43,测试的对数损失约为0.53。我们的混淆精度和召回矩阵如下所示:
混淆矩阵/精确矩阵/召回矩阵
每个人都必须知道如何解释正常的混淆矩阵。我不想对它进行解释。让我们看看如何解释精度矩阵。上图中,第二个是精度矩阵。
直观上,精度意味着在所有预测为正的点中,有多少实际上是正的。这里我们可以看到,所有预测为 1 类的标签中,有 24.6%属于 2 类,剩下的 75.4 %属于 1 类。类似地,对于预测为第 2 类的所有点,69.2%属于第 2 类,30.02%属于第 1 类。这里,类 1 的精度是 0.754,类 2 的精度是 0.30。
我们的第三个矩阵是回忆矩阵。直观回忆是指,在属于一类的所有点中,有多少是正确预测的。在召回矩阵中,在属于类别 1 的所有标签中,86.5%被预测为类别 1,13.5%被预测为类别 2。同样,在所有属于 class2 的原始点中,59.9%属于 class2,其余属于 class1。
TFIDF 加重手套:
在超参数调整之后,我们最终得到的对数损失大约是测试的 0.39 和训练的 0.38。
混淆矩阵/精确矩阵/召回矩阵
从两个召回矩阵中,我们可以看到召回值较低。让我们看看它如何执行线性 SVM。
线性 SVM
TFIDF 功能:
列车日志损失:0.3851
测试日志损失:0.3942
混淆矩阵:
混淆矩阵/精确矩阵/召回矩阵
TFIDF 加重手套:
列车日志损失:0.3876
测试日志损失:0.395
混淆矩阵:
混淆矩阵/精确矩阵/召回矩阵
我们可以看到,无论是逻辑回归还是线性 SVM,我们的回忆值都很低。但是这两个模型都没有过度拟合。所以我在这里想到了一个偏高的问题。如果我们选择一些提升方法,我们可以克服这一点,可以获得更好的召回值。出于这个目的,我在 tfidf 和 tfidf 加重手套功能上试用了 XGBoost。
XGBOOST
TFIDF 功能:
列车日志损失:0.457
测试日志损失:0.516
混淆矩阵:
混淆矩阵/精确矩阵/召回矩阵
TFIDF 加重手套特征:
列车日志损失:0.183
测试日志损失:0.32
混淆矩阵:
混淆矩阵/精确矩阵/召回矩阵
我们可以看到,使用 Xgboost 后,两个类的召回率都略有提高。在所有这些 xgboost 手套向量表现更好。
结果
要查看完整的代码,你可以访问我的 GitHub 库。
参考
- 应用课程
使用蒙特卡罗模拟寻找期望值:简介
使用 Python 中的蒙特卡罗模拟解决常见概率难题教程
如果你对解决概率难题感兴趣,很有可能你会遇到一些难题,这些难题要求你在观察到所需的结果之前找到预期的试验次数。
如果你已经解决了足够多的问题,你就有可能知道如何通过分析来解决它们。我希望这篇文章能让你用不同的方法解决同样的问题,如果你想用分析的方法解决问题,给你锦囊妙计。
但是首先,蒙特卡罗(MC)方法是什么?根据维基百科,
蒙特卡罗方法是一种广泛的计算算法,它依靠重复的随机抽样来获得数值结果。基本概念是用随机性来解决原则上可能是确定性的问题。”
让我们用一个简单而实际的问题来进一步理解 MC。如何使用 MC 来估计π的值?
- 画一个正方形,画一个半径等于正方形边长的圆的四分之一圆
- 在正方形表面上均匀分布给定数量的点
- 计算圆内的点数
- 找出落在这个圆内的点与总点数的比率。理论上,这个比例是 π /4。将所述比率乘以 4 以得到 π 的值。
直观上,我们可以看到,随着我们在正方形表面上散布的点数的增加,精确度也在增加。对于无限多的点,该比率接近 π /4。
维基百科上用户 nicoguaro 的 GIF
压断骆驼背的稻草
这个谜题源自著名的习语,讲的是骆驼如何在最后一根稻草看似微小的附加重量下屈服。
数学上,假设稻草被一根一根地放在骆驼背上。吸管的重量同样可能是 0 到 1 之间的任何真实值。当稻草的重量超过 1 磅时,骆驼的背就会折断。求最后一根稻草重量的期望值。
你可能会想,最后一根稻草的预期重量会和 0.5 有什么不同吗,0.5 是单根稻草重量的预期值。答案是肯定的,因为较重的稻草比较轻的稻草更容易压断骆驼的背。因此,直觉上,最后一根稻草的预期重量大于 0.5。
在继续下一步之前,试着分析性地解决这个问题,看看你是否能找到正确的答案。
蒙特卡洛方法
使用 Python,让我们通过在骆驼背上添加吸管来模拟折断骆驼的背。
免责声明:在模拟这个谜题时,没有骆驼受到伤害。
定义函数 break_camel_back()返回压断骆驼背的稻草的重量和模拟压断骆驼背 n 次的 expected _ weight _ of _ last _ straw(n)并返回每次压断骆驼背的稻草的平均重量。对于 n 的大值,这个函数的输出就是我们问题的答案。
https://gist . github . com/aditator/62 ddda 3369 acf8d 66331 c 854 F5 A8 b 963
Camel.py 的输出
可以看出,对于大的值(在这种情况下为 2 ⁹),期望值接近 0.64 左右的值,符合我们的直觉。
确切的期望值是 2-e/2,大约是 0.640859(感谢那些通过分析成功解决这个问题的人)。如果你不能解析地解决它,不要担心,你可以在这里找到解决方案。
附加练习:调整代码以找到相同重量分布下折断骆驼背的预期 根 。(答案是 e)
获得“TXT”图案所需的投掷硬币次数
找出你需要翻转的次数的期望值,以便看到图案“TXT”,其中 T 是反面,X 是正面或反面。
(你将继续投掷硬币,直到你观察到 TTT 或 THT,并数出你投掷硬币的次数)
蒙特卡洛方法
定义 coin_toss()函数,该函数模拟在随机库中选择的帮助下投掷硬币。将 res 初始化为 3(获得 TXT 模式的最小投掷次数),并返回发生这种情况时的投掷次数。
像前面一样,定义 expected_tosses()来返回生成“TXT”模式所需的平均投掷次数。
https://gist . github . com/aditator/C5 EC 83 dbb BAC 77 ab 6897 EAA 86 b 7 b 50 e 3
TXT.py 的输出
可以看出,对于大值(在这种情况下为 2 ⁹),预期值趋向于 6.8 左右的值。
在分析上,这可以很容易地用一组线性方程来解决。
由 brilliant.org 的用户 Geoff Piling 发布
在求解 E 的方程之后,我们发现答案是 34/5 (6.8),并且 MC 模拟与结果一致。
就是这样!
我们已经证实蒙特卡罗方法是模拟简单随机事件的有力工具。这些方法的应用不仅仅局限于概率谜题,而是跨越了金融、计算生物学、数据科学、工程学,甚至定律!
请在评论中告诉我你的想法,或者你希望我详细阐述什么。
我会推荐初学者从这里开始。