TowardsDataScience 博客中文翻译 2016~2018(一百六十八)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

临床自然语言处理导论:用出院总结预测医院再入院

原文:https://towardsdatascience.com/introduction-to-clinical-natural-language-processing-predicting-hospital-readmission-with-1736d52bc709?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

医生总是写下关于他们病人的临床记录——最初,这些记录写在纸上,锁在柜子里。对数据科学家来说幸运的是,医生现在可以在电子病历中输入他们的笔记。这些笔记代表了大量的知识和见解,可用于使用自然语言处理(NLP)的预测模型,以改善患者护理和医院工作流程。作为一个例子,我将向您展示如何通过出院总结来预测再次入院。

本文面向对医疗数据科学感兴趣的人。完成本教程后,您将学习

  • 如何为机器学习项目准备数据
  • 如何使用词袋方法预处理非结构化笔记
  • 如何建立一个简单的预测模型
  • 如何评估你的模型的质量
  • 如何决定改进模型的下一步

我最近读了 Rajkomar 等人的伟大论文“电子健康记录的可扩展和精确的深度学习”(论文发表于https://arxiv.org/abs/1801.07860)。作者利用医院数据建立了许多最先进的深度学习模型,以预测住院死亡率(AUC = 0.93-0.94)、30 天计划外再入院(AUC = 0.75-76)、延长住院时间(AUC = 0.85-0.86)和出院诊断(AUC = 0.90)。AUC 是一个数据科学性能指标(下面将详细介绍),越接近 1 越好。很明显,预测再入院是最困难的任务,因为它的 AUC 较低。我很好奇,如果将流量自由文本摘要与简单的预测模型结合使用,我们可以得到多好的模型。

如果你想在 Jupyter 笔记本上跟随 Python 代码,请随意从我的 github 下载代码。

模型定义

这篇博文将概述如何建立一个分类模型,利用自由文本的出院总结来预测哪些患者有 30 天无计划再入院的风险。

数据集

我们将利用 MIMIC-III(重症监护医疗信息集市 III)数据库。这个令人惊叹的免费医院数据库包含了 2001 年至 2012 年马萨诸塞州波士顿贝丝以色列女执事医疗中心收治的超过 50,000 名患者的去身份数据。为了访问该项目的数据,您需要通过此链接请求访问权限(【https://mimic.physionet.org/gettingstarted/access/】T4)。

在本项目中,我们将利用以下 MIMIC III 表格

  • 入院—包含入院和出院日期的表格(每个入院都有一个唯一的标识符 HADM_ID)
  • NOTEEVENTS —包含每次住院的所有注释(与 HADM_ID 的链接)

为了保持匿名,每个患者的所有日期都被转移到很远的将来,但是患者的两个连续事件之间的时间被保存在数据库中。这一点很重要,因为它保持了特定患者两次住院之间的时间。

由于这是一个受限制的数据集,我不能公开分享原始患者数据。因此,我将只向您展示人为的单个患者数据或汇总描述。

步骤 1:为机器学习项目准备数据

我们将按照以下步骤为我们的机器学习项目准备来自录取和 NOTEEVENTS 模拟表的数据。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,我们使用 pandas 数据帧加载录取表:

# set up notebook
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt# read the admissions table
df_adm = pd.read_csv('ADMISSIONS.csv')

该表中感兴趣的主要列有:

  • SUBJECT_ID:每个主题的唯一标识符
  • HADM_ID:每次住院的唯一标识符
  • 入院时间:入院日期,格式为 YYYY-MM-DD hh:mm:ss
  • 出院时间:相同格式的出院日期
  • 死亡时间:相同格式的死亡时间(如果存在)
  • 入院类型:包括择期、急诊、新生儿、急症

下一步是将日期从字符串格式转换成日期时间。我们使用errors = ‘coerce’标志来考虑缺失的日期。

# convert to dates
df_adm.ADMITTIME = pd.to_datetime(df_adm.ADMITTIME, format = '%Y-%m-%d %H:%M:%S', errors = 'coerce')
df_adm.DISCHTIME = pd.to_datetime(df_adm.DISCHTIME, format = '%Y-%m-%d %H:%M:%S', errors = 'coerce')
df_adm.DEATHTIME = pd.to_datetime(df_adm.DEATHTIME, format = '%Y-%m-%d %H:%M:%S', errors = 'coerce')

下一步是获取下一个计划外入院日期(如果存在)。这将遵循几个步骤,我将向您展示一个人造病人会发生什么。首先,我们将按照入院日期对数据帧进行排序

# sort by subject_ID and admission date
df_adm = df_adm.sort_values(['SUBJECT_ID','ADMITTIME'])
df_adm = df_adm.reset_index(drop = True)

对于单个患者,数据帧可能是这样的:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以使用 groupby shift 操作符来获取每个 SUBJECT_ID 的下一个许可(如果存在的话)

# add the next admission date and type for each subject using groupby
# you have to use groupby otherwise the dates will be from different subjects
df_adm['NEXT_ADMITTIME'] = df_adm.groupby('SUBJECT_ID').ADMITTIME.shift(-1)# get the next admission type
df_adm['NEXT_ADMISSION_TYPE'] = df_adm.groupby('SUBJECT_ID').ADMISSION_TYPE.shift(-1)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意上一次录取没有下一次录取。

但是,我们要预测计划外的再次录取,所以我们应该过滤掉选修的下一次录取。

# get rows where next admission is elective and replace with naT or nan
rows = df_adm.NEXT_ADMISSION_TYPE == 'ELECTIVE'
df_adm.loc[rows,'NEXT_ADMITTIME'] = pd.NaT
df_adm.loc[rows,'NEXT_ADMISSION_TYPE'] = np.NaN

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后回填我们移除的值

# sort by subject_ID and admission date
# it is safer to sort right before the fill in case something changed the order above
df_adm = df_adm.sort_values(['SUBJECT_ID','ADMITTIME'])# back fill (this will take a little while)
df_adm[['NEXT_ADMITTIME','NEXT_ADMISSION_TYPE']] = df_adm.groupby(['SUBJECT_ID'])[['NEXT_ADMITTIME','NEXT_ADMISSION_TYPE']].fillna(method = 'bfill')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

然后我们可以计算下一次入院的天数

df_adm['DAYS_NEXT_ADMIT']=  (df_adm.NEXT_ADMITTIME - df_adm.DISCHTIME).dt.total_seconds()/(24*60*60)

在我们 58976 例住院患者的数据集中,有 11399 例再次入院。对于那些再次入院的患者,我们可以绘制入院间隔天数的直方图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

现在我们已经准备好处理 NOTEEVENTS.csv 了

df_notes = pd.read_csv("NOTEEVENTS.csv")

感兴趣的主要列有:

  • 主题 ID
  • HADM_ID
  • 类别:包括“出院总结”、“回波”、“心电图”、“护理”、“医生”、“康复服务”、“病例管理”、“呼吸”、“营养”、“常规”、“社会工作”、“药房”、“咨询”、“放射科”、“T1”、“护理/其他”
  • 正文:我们的临床笔记专栏

由于我不能显示单个音符,我将在这里描述它们。数据集有 2,083,180 行,表明每次住院都有多个记录。在注释中,为了保密,日期和 PHI(姓名、医生、地点)已被转换。还有特殊字符,如\n(换行符)、数字和标点符号。

由于每次住院都有多张票据,我们需要选择使用哪种票据。为了简单起见,让我们使用放电摘要,但是如果我们愿意,我们可以通过连接它们来使用所有的注释。

# filter to discharge summary
df_notes_dis_sum = df_notes.loc[df_notes.CATEGORY == 'Discharge summary']

由于下一步是合并入院表上的记录,我们可能会假设每次入院都有一个出院总结,但我们可能应该检查一下。我们可以用一个 assert 语句来检查这一点,结果失败了。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这一点上,您可能想要研究为什么有多个摘要,但是为了简单起见,让我们只使用最后一个

df_notes_dis_sum_last = (df_notes_dis_sum.groupby(['SUBJECT_ID','HADM_ID']).nth(-1)).reset_index()
assert df_notes_dis_sum_last.duplicated(['HADM_ID']).sum() == 0, 'Multiple discharge summaries per admission'

现在我们准备合并录取和注释表。我使用左合并来解决音符丢失的问题。在很多情况下,合并后会得到多行(尽管我们在上面已经处理过了),所以我喜欢在合并后添加 assert 语句

df_adm_notes = pd.merge(df_adm[['SUBJECT_ID','HADM_ID','ADMITTIME','DISCHTIME','DAYS_NEXT_ADMIT','NEXT_ADMITTIME','ADMISSION_TYPE','DEATHTIME']],
                        df_notes_dis_sum_last[['SUBJECT_ID','HADM_ID','TEXT']], 
                        on = ['SUBJECT_ID','HADM_ID'],
                        how = 'left')
assert len(df_adm) == len(df_adm_notes), 'Number of rows increased'

10.6 %的录取通知书丢失了(df_adm_notes.TEXT.isnull().sum() / len(df_adm_notes)),所以我进一步调查了一下

df_adm_notes.groupby('ADMISSION_TYPE').apply(lambda g: g.TEXT.isnull().sum())/df_adm_notes.groupby('ADMISSION_TYPE').size()

并发现 53%的新生儿入院缺少出院小结,而其他新生儿的这一比例为 4%。在这一点上,我决定取消新生入学。最有可能的是,这些失踪的新生儿入院记录的出院总结存储在模拟数据集之外。

对于这个问题,我们要对未来 30 天内是否会收治一个病人进行分类。因此,我们需要创建一个带有输出标签的变量(1 =重新接纳,0 =不重新接纳)

df_adm_notes_clean['OUTPUT_LABEL'] = (df_adm_notes_clean.DAYS_NEXT_ADMIT < 30).astype('int')

快速计数阳性和阴性结果为 3004 个阳性样本,48109 个阴性样本。这表明我们有一个不平衡的数据集,这在医疗保健数据科学中是常见的。

准备数据的最后一步是将数据分成训练集、验证集和测试集。为了获得可重复的结果,我让 random_state 始终为 42。

# shuffle the samples
df_adm_notes_clean = df_adm_notes_clean.sample(n = len(df_adm_notes_clean), random_state = 42)
df_adm_notes_clean = df_adm_notes_clean.reset_index(drop = True)# Save 30% of the data as validation and test data 
df_valid_test=df_adm_notes_clean.sample(frac=0.30,random_state=42)df_test = df_valid_test.sample(frac = 0.5, random_state = 42)
df_valid = df_valid_test.drop(df_test.index)# use the rest of the data as training data
df_train_all=df_adm_notes_clean.drop(df_valid_test.index)

由于患病率如此之低,我们希望防止模型总是预测为阴性(非再入院)。为此,我们有几个选项来平衡训练数据

  • 对底片进行子采样
  • 过度采样阳性
  • 创建合成数据(如 SMOTE)

由于我没有对您计算机的 RAM 大小做出任何限制,我们将对负面数据进行子采样,但我鼓励您尝试其他技术,如果您的计算机或服务器可以处理它,看看您是否可以获得改进。(如果你尝试这样做,请在下面发表评论!)

# split the training data into positive and negative
rows_pos = df_train_all.OUTPUT_LABEL == 1
df_train_pos = df_train_all.loc[rows_pos]
df_train_neg = df_train_all.loc[~rows_pos]# merge the balanced data
df_train = pd.concat([df_train_pos, df_train_neg.sample(n = len(df_train_pos), random_state = 42)],axis = 0)# shuffle the order of training samples 
df_train = df_train.sample(n = len(df_train), random_state = 42).reset_index(drop = True)

步骤 2:使用词袋方法对非结构化笔记进行预处理

现在,我们已经创建了具有标签和注释的数据集,我们需要预处理我们的文本数据,以将其转换为对机器学习模型有用的东西(例如数字)。我们将使用单词袋(BOW)方法。

BOW 基本上将笔记分解成单个单词,并计算每个单词出现的次数。你的数字数据就变成了一些单词的计数,如下所示。BOW 是做 NLP 分类最简单的方法。在我读过的大多数博客文章中,对于 NLP 分类任务,更高级的技术很难胜过 BOW。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在这个过程中,需要做出的选择很少

  • 如何对单词进行预处理
  • 如何统计单词
  • 使用哪些单词

没有适合所有 NLP 项目的最佳选择,所以我建议在构建自己的模型时尝试一些选项。

您可以用两种方式进行预处理

  • 修改原始数据帧文本列
  • 作为管道的一部分进行预处理,这样就不会编辑原始数据

我将向您展示如何做到这两个,但我更喜欢第二个,因为它需要大量的工作才能达到这一点。

让我们定义一个函数,通过用空格填充缺失的注释并删除换行符和回车符来修改原始数据帧

def preprocess_text(df):
    # This function preprocesses the text by filling not a number and replacing new lines ('\n') and carriage returns ('\r')
    df.TEXT = df.TEXT.fillna(' ')
    df.TEXT = df.TEXT.str.replace('\n',' ')
    df.TEXT = df.TEXT.str.replace('\r',' ')
    return df# preprocess the text to deal with known issues
df_train = preprocess_text(df_train)
df_valid = preprocess_text(df_valid)
df_test = preprocess_text(df_test)

另一种选择是作为管道的一部分进行预处理。这个过程包括使用一个标记器和一个矢量器。记号赋予器将单个音符分解成单词列表,矢量器获取单词列表并对单词进行计数。

我们将使用nltk包中的word_tokenize作为默认的记号赋予器,它基本上基于空格和一些标点符号来分解注释。下面显示了一个示例:

import nltk
from nltk import word_tokenize
word_tokenize('This should be tokenized. 02/02/2018 sentence has stars**')

带输出:

[‘This’, ‘should’, ‘be’, ‘tokenized’, ‘.’, ‘02/02/2018’, ‘sentence’,
 ‘has’, ‘stars**’]

默认情况下,一些标点符号被分开,数字留在句子中。我们将编写自己的记号赋予器函数来

  • 用空格替换标点符号
  • 用空格替换数字
  • 小写所有单词
import string
def tokenizer_better(text):
    # tokenize the text by replacing punctuation and numbers with spaces and lowercase all words

    punc_list = string.punctuation+'0123456789'
    t = str.maketrans(dict.fromkeys(punc_list, " "))
    text = text.lower().translate(t)
    tokens = word_tokenize(text)
    return tokens

有了这个标记符,我们就可以从原来的句子中得到

['this', 'should', 'be', 'tokenized', 'sentence', 'has', 'stars']

你可以做的另外的事情将会是词汇化或词干化,但是那是更高级的,所以我将跳过它。

既然我们有了将自由文本转换成令牌的方法,我们就需要一种方法来计算每个流量摘要的令牌数。我们将使用 scikit-learn 包中内置的CountVectorizer 。这个矢量器只是计算每个单词在笔记中出现的次数。还有一个TfidfVectorizer ,它考虑了单词在所有笔记中的使用频率,但对于这个项目,让我们使用更简单的一个(我在第二个项目中也得到了类似的结果)。

例如,假设我们有 3 个音符

sample_text = ['Data science is about the data', 'The science is amazing', 'Predictive modeling is part of data science']

本质上,您可以使用 CountVectorizer 来学习数据中的单词,并转换数据以创建每个单词的计数。

from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(tokenizer = tokenizer_better)
vect.fit(sample_text)# matrix is stored as a sparse matrix (since you have a lot of zeros)
X = vect.transform(sample_text)

矩阵 X 将是一个稀疏矩阵,但是如果你把它转换成一个数组(X.toarray(),你会看到这个

array([[1, 0, 2, 1, 0, 0, 0, 0, 1, 1],
       [0, 1, 0, 1, 0, 0, 0, 0, 1, 1],
       [0, 0, 1, 1, 1, 1, 1, 1, 1, 0]], dtype=int64)

其中有 3 行(因为我们有 3 个音符)和每个单词的计数。您可以看到带有vect.get_feature_names()的列名

['about', 'amazing', 'data', 'is', 'modeling', 'of', 'part', 'predictive', 'science', 'the']

我们现在可以在临床笔记上安装 CountVectorizer。只使用训练数据是很重要的,因为您不希望包含在验证和测试集中出现的任何新单词。有一个名为 max_features 的超参数,您可以设置它来限制矢量器中包含的单词数量。这将使用前 N 个最常用的单词。在第 5 步中,我们将对此进行调整以查看其效果。

# fit our vectorizer. This will take a while depending on your computer. from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(max_features = 3000, tokenizer = tokenizer_better)# this could take a while
vect.fit(df_train.TEXT.values)

我们可以看看最常用的词,我们会发现这些词中的许多可能不会为我们的模型增加任何价值。这些词被称为停用词,我们可以用 CountVectorizer 轻松地(如果我们想的话)删除它们。不同的自然语言处理语料库都有常用的停用词列表,但是我们将根据下面的图片来创建自己的停用词列表。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

my_stop_words = ['the','and','to','of','was','with','a','on','in','for','name',                 'is','patient','s','he','at','as','or','one','she','his','her','am',                 'were','you','pt','pm','by','be','had','your','this','date',                'from','there','an','that','p','are','have','has','h','but','o',                'namepattern','which','every','also']

如果您愿意,可以随意添加自己的停用词。

from sklearn.feature_extraction.text import CountVectorizer
vect = CountVectorizer(max_features = 3000, 
                       tokenizer = tokenizer_better, 
                       stop_words = my_stop_words)
# this could take a while
vect.fit(df_train.TEXT.values)

现在我们可以把笔记转换成数字矩阵。在这一点上,我将只使用训练和验证数据,所以我还不想看它如何在测试数据上工作。

X_train_tf = vect.transform(df_train.TEXT.values)
X_valid_tf = vect.transform(df_valid.TEXT.values)

我们还需要我们的输出标签作为单独的变量

y_train = df_train.OUTPUT_LABEL
y_valid = df_valid.OUTPUT_LABEL

从滚动条的位置可以看出……和往常一样,为预测模型准备数据需要花费 80%的时间。

第三步:建立一个简单的预测模型

我们现在可以建立一个简单的预测模型,该模型利用我们的词汇输入,预测患者是否会在 30 天内再次入院(是= 1,否= 0)。

这里我们将使用逻辑回归模型。逻辑回归是 NLP 任务的一个很好的基线模型,因为它可以很好地处理稀疏矩阵并且是可解释的。我们有一些额外的选择(称为超参数),包括 C 和 penalty,C 是正则化系数,penalty 告诉我们如何测量正则化。正则化本质上是一种试图最小化过度拟合的技术。

# logistic regression
from sklearn.linear_model import LogisticRegression
clf=LogisticRegression(C = 0.0001, penalty = 'l2', random_state = 42)
clf.fit(X_train_tf, y_train)

我们可以用拟合的模型计算每个样本的再入院概率

model = clf
y_train_preds = model.predict_proba(X_train_tf)[:,1]
y_valid_preds = model.predict_proba(X_valid_tf)[:,1]

步骤 4:评估模型的质量

在这一点上,我们需要衡量我们的模型表现如何。有几种不同的数据科学性能指标。如果你感兴趣,我写了另一篇博文详细解释了这些。由于这篇文章很长,我将开始展示结果和数据。您可以查看 github 帐户中生成这些数字的代码。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于预测为阳性的阈值 0.5,我们得到以下性能

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

对于当前选择的超参数,我们确实有一些过度拟合。需要指出的一点是,两组数据的精度之间的主要差异是由于我们平衡了训练集,而验证集是原始分布。目前,如果我们列出一份预计会再次入院的患者名单,我们会发现他们是我们随机选择患者的两倍(精确度与患病率)。

上面没有显示的另一个性能指标是 AUC 或 ROC 曲线下面积。我们当前模型的 ROC 曲线如下所示。实际上,ROC 曲线允许您在改变您定义的预测阳性与预测阴性的阈值时,看到真阳性率和假阳性率之间的权衡。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

步骤 5:改进模型的后续步骤

此时,您可能想在测试集上计算性能,看看自己做得如何。但是等等!我们做了许多选择(下面是几个),我们可以改变这些选择,看看是否有改进:

  • 我们应该花时间获取更多数据吗?
  • 如何标记—我们应该使用词干吗?
  • 如何向量化—我们应该改变字数吗?
  • 如何正则化逻辑回归——我们应该改变 C 还是惩罚?
  • 用哪个型号?

当我试图改进我的模型时,我阅读了许多其他博客帖子和文章,以了解人们如何解决类似的问题。当你这样做的时候,你开始看到可视化数据的有趣方式,我强烈推荐你在自己的项目中坚持使用这些技术。

对于使用 BOW+逻辑回归的 NLP 项目,我们可以绘制最重要的单词,看看我们是否可以获得任何洞察力。对于这一步,我借用了洞察数据科学篇不错的 NLP 文章中的代码。当你看最重要的单词时,我看到两件直接的事情:

  • 哎呀!我忘了排除那些因为‘过期’出现在负面清单中而死亡的病人。目前,我将忽略这一点,并在下面修复它。
  • 还有一些我们可能应该删除的其他停用词(‘应该’,‘如果’,‘它’,‘一直’,‘谁’,‘期间’,’ x ')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们想要改进模型时,我们希望以数据驱动的方式进行。你可以花很多时间在“预感”上,那不会以失败告终。要做到这一点,建议选择一个用于决策单一性能指标。对于这个项目,我将选择 AUC。

对于上面的第一个问题,我们可以绘制一条学习曲线来了解添加更多数据的影响。吴恩达有一套很棒的 Coursera 课程,讨论高偏差和高方差模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

first learning curve with C = 0.0001

我们可以看到,我们有一些过度拟合,但添加更多的数据可能不会大幅改变验证集的 AUC。知道这一点很好,因为这意味着我们不应该花几个月的时间来获取更多的数据。

我们可以做的一些简单的事情是尝试看看我们的一些超参数(max_featuresC)的影响。我们可以运行网格搜索,但是因为我们这里只有两个参数,我们可以分别查看它们,看看效果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Effect of C

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Effect of max_features

我们可以看到,增加 C 和 max_features 会导致模型很快过度拟合。我选择 C = 0.0001,max_features = 3000,此时验证集开始趋于平稳。

在这一点上,你可以尝试一些其他的事情

  • 将子采样改为过采样
  • 向记号赋予器添加词干或词汇化
  • 测试几种不同的 sci-kit 学习模型
  • 连接所有的注释,而不是最后的出院小结
  • 尝试 LSTMs 等深度学习方法
  • 查看您认为错误的出院总结

步骤 6:完成你的模型并测试它

我们现在将使用超参数选择来拟合我们的最终模型。我们也将排除死于再平衡的患者。

rows_not_death = df_adm_notes_clean.DEATHTIME.isnull()df_adm_notes_not_death = df_adm_notes_clean.loc[rows_not_death].copy()
df_adm_notes_not_death = df_adm_notes_not_death.sample(n = len(df_adm_notes_not_death), random_state = 42)
df_adm_notes_not_death = df_adm_notes_not_death.reset_index(drop = True)# Save 30% of the data as validation and test data 
df_valid_test=df_adm_notes_not_death.sample(frac=0.30,random_state=42)df_test = df_valid_test.sample(frac = 0.5, random_state = 42)
df_valid = df_valid_test.drop(df_test.index)# use the rest of the data as training data
df_train_all=df_adm_notes_not_death.drop(df_valid_test.index)assert len(df_adm_notes_not_death) == (len(df_test)+len(df_valid)+len(df_train_all)),'math didnt work'# split the training data into positive and negative
rows_pos = df_train_all.OUTPUT_LABEL == 1
df_train_pos = df_train_all.loc[rows_pos]
df_train_neg = df_train_all.loc[~rows_pos]# merge the balanced data
df_train = pd.concat([df_train_pos, df_train_neg.sample(n = len(df_train_pos), random_state = 42)],axis = 0)# shuffle the order of training samples 
df_train = df_train.sample(n = len(df_train), random_state = 42).reset_index(drop = True)# preprocess the text to deal with known issues
df_train = preprocess_text(df_train)
df_valid = preprocess_text(df_valid)
df_test = preprocess_text(df_test)
my_new_stop_words = ['the','and','to','of','was','with','a','on','in','for','name',              'is','patient','s','he','at','as','or','one','she','his','her','am',                 'were','you','pt','pm','by','be','had','your','this','date',                'from','there','an','that','p','are','have','has','h','but','o',                'namepattern','which','every','also','should','if','it','been','who','during', 'x']from sklearn.feature_extraction.text import CountVectorizervect = CountVectorizer(lowercase = True, max_features = 3000, 
                       tokenizer = tokenizer_better,
                      stop_words = my_new_stop_words)# fit the vectorizer
vect.fit(df_train.TEXT.values)X_train_tf = vect.transform(df_train.TEXT.values)
X_valid_tf = vect.transform(df_valid.TEXT.values)
X_test_tf = vect.transform(df_test.TEXT.values)y_train = df_train.OUTPUT_LABEL
y_valid = df_valid.OUTPUT_LABEL
y_test = df_test.OUTPUT_LABELfrom sklearn.linear_model import LogisticRegressionclf=LogisticRegression(C = 0.0001, penalty = 'l2', random_state = 42)
clf.fit(X_train_tf, y_train)model = clf
y_train_preds = model.predict_proba(X_train_tf)[:,1]
y_valid_preds = model.predict_proba(X_valid_tf)[:,1]
y_test_preds = model.predict_proba(X_test_tf)[:,1]

这会产生以下结果和 ROC 曲线。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

结论

恭喜你!你建立了一个简单的 NLP 模型(AUC = 0.70)来预测基于医院出院总结的再入院,这个模型仅比使用所有医院数据的最先进的深度学习方法(AUC = 0.75)稍差。如果你有任何反馈,请在下面留下。

如果你对医疗保健领域的深度学习 NLP 感兴趣,我推荐阅读 https://arxiv.org/abs/1711.10663的 Erin Craig 的文章

参考

利用电子健康记录进行可扩展和精确的深度学习。拉杰科马尔 A,柳文欢 E,陈 K,等数字医学(2018)。DOI:10.1038/s 41746–018–0029–1。地点:【https://www.nature.com/articles/s41746-018-0029-1

MIMIC-III,一个免费的重症监护数据库。Johnson AEW,Pollard TJ,Shen L,Lehman L,Feng M,Ghassemi M,Moody B,Szolovits P,LA 和 Mark RG。科学数据(2016)。DOI: 10.1038/sdata.2016.35 可在:http://www.nature.com/articles/sdata201635获得

机器学习中的数据预处理导论

原文:https://towardsdatascience.com/introduction-to-data-preprocessing-in-machine-learning-a9fa83a5dc9d?source=collection_archive---------0-----------------------

数据预处理初学者指南

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Markus Spiske on Unsplash

数据预处理是机器学习中不可或缺的一步,因为数据的质量和从中获得的有用信息会直接影响模型的学习能力;因此,在将数据输入模型之前,对数据进行预处理是非常重要的。

我将在本文中介绍的概念是-

  1. 处理空值
  2. 标准化
  3. 处理分类变量
  4. 一键编码
  5. 多重共线性

您可以获得完整的代码(。ipynb) 这里

处理空值—

在任何真实世界的数据集中,总是很少有空值。无论是回归、分类还是任何其他类型的问题,都没有关系,没有模型能够独自处理这些 NULL 或 NaN 值,因此我们需要干预。

在 python 中,NULL 用 NaN 表示。所以不要混淆这两者,它们可以互换使用。

首先,我们需要检查我们的数据集中是否有空值。我们可以使用 isnull()方法来实现。

df.isnull()      
# Returns a boolean matrix, if the value is NaN then True otherwise Falsedf.isnull().sum() 
# Returns the column names along with the number of NaN values in that particular column

我们有各种方法来处理这个问题。解决这个问题最简单的方法是删除包含空值的行或列。

df.dropna()

dropna()接受各种参数,比如—

  1. axis —如果要删除行,我们可以指定 axis = 0;如果要删除列,我们可以指定 axis=1。
  2. how —如果我们指定 how = 'all ',那么只有当所有值都是 NaN 时,才会删除行和列。默认情况下,how 设置为“any”。
  3. thresh——它确定阈值,因此如果我们指定 thresh=5,那么具有少于 5 个实数值的行将被丢弃。
  4. subset-如果我们有 4 列 A、B、C 和 D,那么如果我们指定 subset=[‘C’],那么只有 C 值为 NaN 的行将被删除。
  5. 就地-默认情况下,不会对数据框进行任何更改。因此,如果您希望这些更改反映到您的数据帧中,那么您需要使用 inplace = True。

但是,从数据集中删除行和列并不是最佳选择,因为这会导致大量信息丢失。如果您有 300,000 个数据点,那么删除 2-3 行不会对您的数据集产生太大影响,但是如果您只有 100 个数据点,并且其中 20 个数据点对于特定字段具有 NaN 值,那么您不能简单地删除这些行。在现实世界的数据集中,某个特定字段有大量 NaN 值的情况经常发生。

例如,假设我们从调查中收集数据,那么可能会有一个可选字段,假设 20%的人留为空白。因此,当我们获得数据集时,我们需要了解剩余的 80%的数据仍然是有用的,因此,与其丢弃这些值,我们需要以某种方式替换缺失的 20%的值。我们可以在插补的帮助下做到这一点。

插补—

插补就是简单地替换我们数据集缺失值的过程。我们可以通过定义我们自己的定制函数来实现这一点,或者我们可以通过使用 sklearn 提供的simple imputr类来简单地执行插补。

from sklearn.impute import SimpleImputer
imputer = SimpleImputer(missing_values=np.nan, strategy='mean')
imputer = imputer.fit(df[['Weight']])
df['Weight'] = imputer.transform(df[['Weight']])

。这里使用的值返回数据帧的 numpy 表示。
仅返回数据框中的值,轴标签将被移除。

标准化—

这是另一个完整的预处理步骤。在标准化中,我们转换我们的值,使平均值为 0,标准差为 1。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image by author

考虑上面的数据帧,这里我们有 2 个数值:年龄体重。因为年龄是以年为单位,体重是以公斤为单位,所以它们不在一个等级上,因为体重更有可能大于年龄;因此,我们的模型将赋予权重更多的权重,这不是理想的情况,因为年龄也是一个不可或缺的因素。为了避免这个问题,我们执行标准化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image by author

简单来说,我们只需计算这些值的平均值和标准差,然后对于每个数据点,我们只需减去平均值,然后除以标准差。

示例—

考虑数据帧 1 中的列年龄。为了标准化该列,我们需要计算平均值和标准偏差,然后我们将使用上述公式转换每个年龄值。

我们不需要手动完成这个过程,因为 sklearn 提供了一个名为 StandardScaler 的函数。

from sklearn.preprocessing import StandardScaler
std = StandardScaler()
X = std.fit_transform(df[['Age','Weight']])

这里需要注意的重要一点是,我们需要标准化训练和测试数据。

  • fit_transform 相当于先使用 fit,再使用 transform。
  • fit 函数计算平均值和标准差,transform 函数实际上标准化数据集,我们可以使用 fit_transform 函数在一行代码中完成此过程。

这里要注意的另一件重要的事情是,当处理测试数据时,我们将只使用 transform 方法。

处理分类变量—

处理分类变量是机器学习的另一个重要方面。分类变量基本上是离散而非连续的变量。例如,商品的颜色是一个离散变量,而价格是一个连续变量。

分类变量进一步分为两种类型—

  • 有序分类变量 —这些变量可以排序。ex——T 恤衫的尺寸。我们可以说 M < L < XL。
  • 名义分类变量 —这些变量不能排序。前——t 恤的颜色。我们不能说蓝色是绿色,因为比较这两种颜色没有任何意义,因为它们没有任何关系。

这里需要注意的重要一点是,我们需要不同地预处理序数和名词性分类变量。

处理有序分类变量—

首先,我们需要创建一个数据框架。

df_cat = pd.DataFrame(data = 
                     [['green','M',10.1,'class1'],
                      ['blue','L',20.1,'class2'],
                      ['white','M',30.1,'class1']])
df_cat.columns = ['color','size','price','classlabel']

这里,列“size”和“classlabel”是顺序分类变量,而“color”是名义分类变量。

有两个非常简单和整洁的技术来转换顺序 cv。

  1. 使用 map()函数—
size_mapping = {'M':1,'L':2}
df_cat['size'] = df_cat['size'].map(size_mapping)

这里 M 将用 1 代替,L 用 2 代替。

2.使用标签编码器—

from sklearn.preprocessing import LabelEncoder
class_le = LabelEncoder()
df_cat['classlabel'] =
class_le.fit_transform(df_cat['classlabel'].values)

这里,class1 用 0 表示,class2 用 1 表示。

处理名词性分类变量的方式不正确—

大多数人犯的最大错误是他们无法区分序数型和名义型简历。因此,如果您对名义变量使用相同的 map()函数或 LabelEncoder,那么模型将认为名义变量之间存在某种关系。

所以如果我们使用 map()来映射颜色,就像-

col_mapping = {'Blue':1,'Green':2}

然后根据模型,绿色>蓝色,这是一个毫无意义的假设,模型会给出考虑这种关系的结果。所以,虽然你会用这种方法得到结果,但它们不会是最佳的。

处理名义分类变量的正确方法—

处理名义 cv 的正确方法是使用一键编码。使用独热编码最简单的方法是使用 get_dummies()函数。

df_cat = pd.get_dummies(df_cat[['color','size','price']])

在这里,我们传递了“size”和“price”以及“color ”,但是 get_dummies()函数非常聪明,它将只考虑字符串变量。所以它只是转换“颜色”变量。

现在,你一定想知道这到底是什么一次性编码。所以让我们试着去理解它。

一键编码—

因此,在一键编码中,我们主要做的是创建“n”列,其中 n 是名义变量可以接受的唯一值的数量。

例如,在这里,如果颜色可以是蓝色、绿色和白色,那么我们将只创建三个新列,即颜色 _ 蓝色、颜色 _ 绿色和颜色 _ 白色,如果颜色是绿色,那么颜色 _ 蓝色和颜色 _ 白色列的值将是 0,颜色 _ 绿色列的值将是 1。

因此,在 n 列中,只有一列的值为 1,其余的列的值都为 0。

一键编码是一个非常酷和简洁的技术,但是只有一个问题与之相关,那就是多重共线性。因为你们一定都认为这是一个相当沉重的词,所以一定很难理解,所以让我来验证一下你们新形成的信念。多重共线性确实是一个有点棘手但极其重要的统计学概念。这里的好处是,我们不需要真正理解多重共线性的所有本质细节,我们只需要关注它将如何影响我们的模型。因此,让我们深入了解多重共线性的概念,以及它将如何影响我们的模型。

多重共线性及其影响—

当我们的数据集中存在彼此高度依赖的要素时,就会出现多重共线性。在这种情况下,我们有一些特征-

color_blue,color_green 和 color_white,这些都是相互依赖的,并且会影响我们的模型。

如果数据集存在多重共线性,则无法使用权重向量来计算特征重要性。

多重共线性会影响我们模型的可解释性。

我认为,在机器学习的背景下,这些信息已经足够了。但是,如果您仍然不相信,您可以访问下面的链接,了解与多重共线性相关的数学和逻辑。

[## 12.1 -什么是多重共线性?| STAT 501

如课程概述中所述,只要回归模型中有两个或多个预测因子,就存在多重共线性…

newonlinecourses.science.psu.edu](https://newonlinecourses.science.psu.edu/stat501/node/344/)

现在,我们已经了解了多重共线性的含义,接下来让我们尝试了解如何识别它。

  • 识别多重共线性的最简单方法是绘制一对图,您可以观察不同要素之间的关系。如果两个要素之间存在线性关系,则它们之间存在强相关性,并且数据集中存在多重共线性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image by author

此处(体重,BP)与(BSA,BP)密切相关。您也可以使用相关矩阵来检查特征的紧密相关性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Image by author

我们可以观察到,体重与 BP、BSA 与 BP 之间存在很强的协整关系(0.950)(0.875)。

避免多重共线性的简单技巧-

我们可以使用 drop_first=True 来避免多重共线性问题。

df_cat = pd.get_dummies(df_cat[['color','size','price']],drop_first=True)

这里 drop_first 将删除第一列颜色。所以这里蓝色将被去掉,我们只有绿色和白色。

这里需要注意的重要一点是,我们不会丢失任何信息,因为如果 color_green 和 color_white 都是 0,那么这意味着颜色一定是蓝色的。因此,我们只能借助这两栏来推断全部信息,因此这三栏之间的强相关性被打破了。

说完这些,我们就到了本文的结尾。非常感谢你阅读它。

您可以获得完整的代码()。ipynb) 此处为

如果你愿意,你可以鼓掌。这是免费的。

我的 LinkedInTwitterGithub
你可以登陆我的网站了解更多关于我和我的工作。

德鲁伊介绍,你的大规模互动分析

原文:https://towardsdatascience.com/introduction-to-druid-4bf285b92b5a?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我大约在 2 年前发现了德鲁伊( http://druid.io )。

当时我在 SuperAwesome 工作,我们需要一个解决方案来替换我们现有的基于 Mongo 的报告系统,该系统已经显示出了它的疲态。由于数据基数大,我们的 MongoDB 实现没有很好地扩展,存储成本使我们认为它不是这项工作的最佳工具。

当时,我们每天处理大约 1 亿个事件,我们的一些报告需要 30 秒才能生成。我们目前每天处理数十亿个 事件,大部分时间报告花费不到 1 秒

我们在 MongoDB 中的数据被迁移了。存储在 MongoDB 中的数据使用了大约 60GB 的磁盘空间,当在 Druid 中进行索引时,相同的数据仅代表 600MB 。没错。存储容量减少 100 倍

这篇文章将解释什么是 Druid,为什么你应该关心它,一个关于它如何工作的高级概述,以及一些关于如何开始和实现不到 1 秒的查询时间的信息!

德鲁伊?那是电子游戏吗?

不。但这并不能说明它是 WoW 中的一个类;这使得有时很难找到资源。

为了描述德鲁伊,我只是引用他们的网站:

Apache Druid(孵化)是一个用于事件驱动数据的高性能分析数据存储。德鲁伊的核心设计结合了来自【OLAP】/分析数据库时间系列数据库搜索系统 的思想,创建一个统一的运营分析系统。**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Druid according to their website

如果要我用自己的话来描述:

Druid 是一个关于类固醇的实时柱状时间序列数据库,伸缩性非常好。

显然还有其他可用的数据库来存储时间序列数据,但这不是本文的目的。我只想向你介绍这一个,因为我有这方面的经验,不像其他的。(我当时很快尝试了一下,但我肯定不习惯比较或讨论它们。)

谁在用德鲁伊?我还是第一次听说这件事。

德鲁伊正在被科技市场的一些大玩家使用。druid 网站维护着一份在其架构中使用 Druid 的公司列表。

以下是部分清单:

  • 元市场:他们创造了德鲁伊来驱动他们的程序报告。
  • 网飞:监控他们的基础设施。它们每小时摄取大约 2TB。
  • AirBNB :快速获得用户的互动信息。
  • Optimizely : Druid 为优化个性化的结果仪表板提供动力。
  • 沃尔玛:他们发表了一篇关于他们事件分析流的好文章。
  • 很多其他人…

什么时候应该考虑用德鲁伊?

如果你有以下问题,你应该使用德鲁伊:

  • 要存储的时间序列数据
  • 数据具有较高的基数
  • 您需要能够快速查询这些数据
  • 您想要支持流数据

几个好的用例示例:

  • 数字营销(广告数据)
  • 产品中的用户分析和行为
  • 应用性能管理
  • OLAP 和商业智能)
  • 物联网和设备指标

关于数据存储方式的快速说明

您的数据存储在中。段是不可变的。一旦创建,就不能更新。(您可以创建一个新版本的段,但这意味着要为该期间的所有数据重新编制索引)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Roll-up explained simply

您可以配置如何创建这些段(每天一个,每小时一个,每月一个等等)。您还可以定义段内数据的粒度。如果您知道每小时需要的数据,您可以配置您的段来自动累计数据。

在段内,数据按时间戳、维度和指标存储。

  • 时间戳:时间戳(是否汇总)
  • 维度:维度用于拼接或过滤数据。常见维度的几个例子有城市、州、国家、设备 Id、活动 Id、…**
  • 指标:指标是完成的计数器/聚合。sof 指标的几个例子可以是点击量、浏览量、响应时间、…**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A druid segment: http://druid.io/docs/latest/design/segments.html

德鲁伊默认支持多种可能的聚合,比如 first、last、doubleSum、longMax、… 也有自定义/实验聚合可用,比如 近似直方图DataSketch ,或者你自己的!您可以轻松地将自己的聚合实现为 Druid 的插件。

你可以在德鲁伊文档中读到更多关于数据如何存储在段内的信息:http://druid.io/docs/latest/design/segments.html

它是如何在引擎盖下工作的?

每个 Druid 安装都是一个集群,需要运行多个组件。Druid 集群可以运行在一台机器上(非常适合开发),或者完全分布在几台到几百台机器上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Druid Architecture from http://druid.io/docs/latest/design/

让我们首先从 Druid 所需的外部依赖性开始:

  • 元数据存储:SQL 驱动的数据库,如 PostgreSQL 或 MySQL。它用于存储关于段的信息、一些加载规则,以及保存一些任务信息。Derby 可以用于开发。
  • 动物园管理员:动物园管理员需要在德鲁伊建筑的不同组件之间进行交流。某些类型的节点使用它来向其他节点传输它们的状态和其他信息。
  • 深度存储:深度存储用于保存所有的分段文件,以便长期保存。支持多种存储,例如 S3、HDFS、本地挂载……其中一些是本地可用的,而另一些则需要安装扩展

现在让我们来看看在一个 Druid 集群中运行的不同节点类型:

  • 历史:它们正在加载集群中可用的部分或全部段。然后,他们负责响应对这些段的任何查询。他们不接受任何书写。
  • 中层经理:他们负责索引你的数据,不管是流式的还是批量摄取的。当一个段被索引时,它们还能够响应对这些段的任何查询,直到切换到一个历史节点。
  • 经纪人:这是查询界面。它处理来自客户端的查询,并将它们分派到托管相关段的相关历史和中间管理器节点。最后,在发送给客户端之前,它会将结果合并回来。
  • 协调者:协调者在这里管理集群的状态。当需要通过 zookeeper 加载段时,它们会通知历史节点,或者在集群中重新平衡段。
  • 霸主:负责管理所有的索引任务。他们协调中层管理人员,并确保数据的发布。注意:现在有一种方法可以在与协调器相同的进程中运行霸王。
  • ****路由器(可选):霸王、经纪人、协调人前面的某种 API 网关。正如你可以直接询问这些,我真的不认为有任何必要。

中层管理人员的实时指数化通常与 Kafka 一起运行,但也可以使用其他 fire hose(rabbit MQ,RocketMQ,…)作为扩展。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

运行查询时会发生什么?

现在让我们看看当一个查询被发送到代理时会发生什么。

该查询将包含关于间隔(时间段)、维度和所需指标的信息。

1)查询命中代理。代理知道所请求间隔的相关段在哪里(即,需要来自历史节点 A 的 2 个段,来自历史节点 B的 2 个段,并且它还需要来自在中间管理器 A 中发布的当前索引段的数据)。**

2)查询被发送到所有需要的节点(在我们的例子中是历史 A历史 B中间管理者 A )。

3)这些节点中的每一个都将执行请求的聚合,并根据查询拼接数据,然后将结果发送回代理。

4)然后,根据查询,在代理中合并数据,并将其返回给客户端。

由于经纪人中层经理、历史节点的查询接口是一样的(如果你愿意,可以直接向历史节点发送查询。你可能得不到你所期望的所有数据。),调试你的段,或者测试单个历史节点,真的很容易。代理只是发送相同的查询,但是简单地改变请求间隔以从每个其他节点只获得它需要的数据。

限制

即使最好的数据库也有局限性。这就是生活。

其中一些是我在过去两年和德鲁伊一起工作时发现的:

  • 窗口功能,如滚动平均。您必须在自己的 API 中实现它。
  • 不可能连接数据。但是如果你真的有这个用例,你可能做错了。
  • 你可能需要在它前面有某种 API,只是为了将你的 id 重新映射到用户可读的信息。由于数据库主要是附加的,我不会保存某个东西的值,而只是一个引用(活动 id 而不是活动名称,除非您的数据在您的数据库中也是只读的)。有可能直接在德鲁伊里做这个的方法,但是我还没试过。

关于性能和基础设施管理的说明

说实话,德鲁伊是“相当野兽”。根据您拥有的数据量,可能需要一个相当大的基础设施来维持亚秒级的查询时间。

一旦有了更多的数据,您还需要使用进程的配置(堆、CPU、缓存、线程……)。

在我看来,这也是德鲁伊的不足之处。他们还没有任何简单的工具来配置和维护不同的服务器(他们的云产品中有https://imply.io/product,但我还没有尝试过)。你可能需要用 Chef、Ansible、Puppet、Kubernetes 等工具设置自己的工具来实现自动化。

在 SuperAwesome,我们决定使用Kubernetes结合 掌舵 来尽可能自动化我们的德鲁伊部署。如果你喜欢解决那类问题,SuperAwesome正在招聘 全栈工程师 DevOps 工程师

我在哪里可以试着学习德鲁伊?

我目前正在编写和编辑一个关于德鲁伊的视频课程。这里有。确保查看计划并注册,以便在计划上线时得到通知!

你也可以在我的博客上订阅我未来的帖子,因为我可能会谈论更多关于德鲁伊的事情,还会发布关于德鲁伊职业的更新。

与此同时,还有一些其他有趣的链接可供参考:

  • 德鲁伊快速入门:【http://druid.io/docs/latest/tutorials/index.html】T2
  • **关于德鲁伊的演讲/论文列表:【http://druid.io/docs/latest/misc/papers-and-talks.html **
  • 德鲁伊的暗示分布:https://docs.imply.io/on-prem/quickstart

来源

进化算法简介

原文:https://towardsdatascience.com/introduction-to-evolutionary-algorithms-a8594b484ac?source=collection_archive---------0-----------------------

自然选择最优化

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Daniele Levis Pelusi on Unsplash

进化算法是一种基于启发式的方法,用于解决多项式时间内无法轻松解决的问题,例如经典的 NP 难问题,以及其他任何需要太长时间才能彻底处理的问题。当单独使用时,它们通常应用于组合问题;然而,遗传算法经常与其他方法一起使用,作为一种快速的方法,为另一种算法找到某种程度上最佳的开始位置。

假设你熟悉自然选择的过程,那么进化算法(进一步称为 EA )的前提非常简单。一个进化算法包含四个步骤:初始化、选择、遗传算子和终止。这些步骤大致对应于自然选择的一个特定方面,并提供了简单的方法来模块化这种算法类别的实现。简而言之,在进化过程中,更适合的成员会生存和繁殖,而不适合的成员会死去,不会为下一代的基因库做出贡献,就像自然选择一样。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

语境

在本文的范围内,我们通常将问题定义为:我们希望找到使某个适应度函数最大化的元素的最佳组合,并且一旦我们已经运行了某个最大迭代次数的算法,或者我们已经达到了某个适应度阈值,我们将接受最终的解决方案。这种场景显然不是使用 EA 的唯一方式,但是它确实包含了离散情况下的许多常见应用程序。

初始化

为了开始我们的算法,我们必须首先创建解的初始群体。群体将包含问题的任意数量的可能解决方案,通常称为成员。它通常是随机创建的(在问题的约束范围内),或者,如果任务的一些先验知识是已知的,大致围绕被认为是理想的东西。群体包含广泛的解决方案是很重要的,因为它本质上代表一个基因库;因此,如果我们希望在算法的过程中探索许多不同的可能性,我们应该致力于让许多不同的基因存在。

选择

一旦群体被创建,群体的成员现在必须根据适应度函数被评估。适应度函数是一种函数,它接受成员的特征,并输出解决方案可行性的数字表示。创建适应度函数通常非常困难,找到一个准确表示数据的好函数非常重要;这是非常具体的问题。现在,我们计算所有成员的适应度,并选择一部分得分最高的成员。

多目标函数

EAs 还可以扩展到使用多种健身功能。这使过程有些复杂,因为当使用多个适应度函数时,我们不是能够识别单个最佳点,而是以一组最佳点结束。最优解的集合被称为帕累托边界,并且包含同样最优的元素,在这个意义上,没有一个解优于边界中的任何其他解。一个决策器随后被用于根据问题的上下文或其他一些度量来缩小单一解决方案的范围。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

遗传算子

这一步真的包括两个子步骤:交叉和变异。选择顶级成员(通常是前 2 名,但这个数字可以变化)后,这些成员现在用于在算法中创建下一代。使用被选择的父母的特征,新的孩子被创造出来,它是父母的品质的混合物。根据数据的类型,这样做通常很困难,但通常在组合问题中,可以混合组合并从这些输入中输出有效的组合。现在,我们必须将新的遗传物质引入这一代。如果我们不做这关键的一步,我们将很快陷入局部极值,无法获得最佳结果。这一步是突变,而我们做到这一点,非常简单,通过改变一小部分孩子,使他们不再完美地反映父母的基因子集。突变通常是随机发生的,因为儿童接受突变的机会以及突变的严重程度是由概率分布决定的。

结束

最终,算法必须结束。这通常发生在两种情况下:或者算法已经达到某个最大运行时间,或者算法已经达到某个性能阈值。此时,选择并返回最终解决方案。

例子

现在,为了说明这一过程的结果,我将展示一个 EA 运行的例子。下面的 gif 展示了几代恐龙通过优化身体结构和施加肌肉力量来学习行走。从左到右,世代增加,因此越靠右,行走过程越优化。尽管早期的恐龙不能行走,但 EA 能随时间通过突变和交叉将恐龙进化成能行走的形态。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

博弈论导论(第一部分)

原文:https://towardsdatascience.com/introduction-to-game-theory-part-1-1a812d898e84?source=collection_archive---------3-----------------------

两人序贯博弈——优势策略、纳什均衡、合作与背叛

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source

博弈论一般是指对描述逻辑决策者行为的数学模型的研究。它被广泛应用于经济学、政治学、政治学、计算机科学等多个领域,可以用来对很多现实世界的场景进行建模。一般来说,一个游戏指的是这样一种情况,一组玩家中的每一个都有一组可能的选择,其中任何一个玩家的结果部分取决于其他玩家的选择。

同步游戏

博弈论中的一种主要游戏类型是同时游戏,在这种游戏中,两个玩家同时行动(或者如果他们不这样做,后一个玩家不知道前一个玩家的行动,使其有效地成为同时)。连续博弈通常用范式来表示,对于一个有两个玩家并且每个玩家有 N 种可能移动的博弈,它由一个 N x N 矩阵组成,其中每个条目是一个二元组,包含每个玩家的收益。

为了说明这一点,考虑下面的例子。这是一种叫做囚徒困境的顺序游戏,每个囚犯都可以选择要么背叛另一个囚犯以减轻处罚(坦白),要么为另一个囚犯掩饰并希望另一个囚犯也这样做(撒谎)。在矩阵的每个单元中,元组的第一个元素表示囚犯 1 的收益,第二个元素表示囚犯 2 的收益。人们通过首先识别每个玩家将做出的选择(坦白或撒谎)来阅读这个收益矩阵,然后定位对应于该行和列的矩阵条目。例如,如果囚犯 1 选择坦白,囚犯 2 选择撒谎,你可以读取第一行第二列的矩阵条目,给囚犯 1 的收益是 0,给囚犯 2 的收益是-10。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在同时进行的游戏中,每个玩家都必须根据他对另一个玩家会做什么的假设来做决定。请记住,在博弈论中,我们假设玩家是理性的决策者,他们希望自己的收益最大化。预测游戏结果的一种方法是为每个玩家确定优势策略。优势策略是对给定参与人来说最好的策略,不管其他参与人的选择如何,所以不管囚犯 2 做什么,囚犯 1 的优势策略就是囚犯 1 的最优策略。

在囚徒困境博弈中,我们可以观察到双方的优势策略都是坦白。首先,注意这个收益矩阵是对称的,所以每个参与人的每个选择都有相同的收益。这意味着当确定优势策略时,我们只需要考虑一个玩家的优势策略,因为它也将是另一个玩家的优势策略。现在,为了找出一号囚犯(和二号囚犯)的优势策略,我们需要找出一号囚犯在二号囚犯可能的选择中的最佳选择。如果 2 号囚犯选择坦白,1 号囚犯坦白的收益是-8,撒谎的收益是-10,所以他会选择坦白。如果 2 号囚犯选择撒谎,1 号囚犯坦白后收益为 0,撒谎后收益为-1,所以他会再次选择坦白。因此,一号囚犯有一个优势策略,就是总是坦白,因为不管二号囚犯怎么选择,坦白是一号囚犯的最佳选择。同样的分析也适用于囚犯 2 的优势策略。所以在囚徒困境博弈中,两个囚徒最终都会选择坦白。

因此,(坦白,坦白)选项是一个 T2 纳什均衡。纳什均衡是一组选择,在这些选择中,没有人会因为只改变自己的选择而有所收获。既然我们已经知道坦白是两个囚犯的优势策略,我们就已经知道交换对双方都没有好处。因此,由于每个参与人都在使用他的优势策略,那套选择就是纳什均衡。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

囚徒困境博弈是一个例子,在这个例子中,两个理性的决策者会选择而不是 合作 ( 缺陷),尽管合作(双方都选择谎言)会给双方带来更好的收益((-8,-8)对(-1,-1))。在这样一个不合作的博弈中,通过选择他们自己的个体优势策略,两个囚犯无法做出实际上是最优的选择。个人的理性策略与社会或全球的最优策略相冲突。一般来说,像囚徒困境这样的同时博弈为我们提供了研究冲突与合作的形式化方法。这种导致缺乏合作的特殊情况出现在几个领域,如政治、经济和生物学。这些例子说明,虽然在许多现实世界的情况下“最好”的选择可能是合作,但作为个体思考的理性参与者会选择不相互合作,因为他们无法信任另一个参与者会合作。

遗传算法简介—包括示例代码

原文:https://towardsdatascience.com/introduction-to-genetic-algorithms-including-example-code-e396e98d8bf3?source=collection_archive---------0-----------------------

遗传算法是一种受查尔斯·达尔文的自然进化理论启发的启发式搜索。这种算法反映了自然选择的过程,即选择最适合的个体进行繁殖,以产生下一代的后代。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

自然选择的概念

自然选择的过程始于从群体中选择最适合的个体。他们产生的后代继承了父母的特征,并将被添加到下一代。如果父母有更好的健康状况,他们的后代会比父母更好,有更好的生存机会。这一过程不断迭代,最终会找到具有最适合个体的一代。

这个概念可以应用于搜索问题。我们考虑一个问题的一组解决方案,并从中选择最佳方案。

遗传算法中考虑了五个阶段。

  1. 原始群体
  2. 适应度函数
  3. 选择
  4. 交叉
  5. 变化

原始群体

这个过程从一组被称为群体的个体开始。每个个体都是你想要解决的问题的解决方案。

一个个体由一组被称为基因的参数(变量)来表征。基因连成一串形成染色体(解)。

在遗传算法中,一个个体的基因组用一串字母来表示。通常,使用二进制值(1 和 0 的字符串)。我们说我们在染色体中编码基因。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Population, Chromosomes and Genes

适应度函数

适应度函数决定个体的适应度(个体与其他个体竞争的能力)。它给每个人一个健康分数。一个个体被选择繁殖的概率是基于它的适合度分数。

选择

选择阶段的思路是选择最适的个体,让他们把自己的基因传递给下一代。

两对个体(父母)基于他们的适应性分数被选择。高适合度的个体有更多的机会被选择繁殖。

交叉

交叉是遗传算法中最重要的阶段。对于每对要交配的亲本,从基因中随机选择一个交叉点

例如,假设交叉点为 3,如下所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Crossover point

后代是通过在他们之间交换父母的基因来创造的,直到到达交叉点。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Exchanging genes among parents

新的后代被添加到种群中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

New offspring

变化

在某些新形成的后代中,他们的一些基因可能以低随机概率发生突变。这意味着位串中的一些位可以翻转。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Mutation: Before and After

变异的发生是为了保持群体的多样性,防止过早收敛。

结束

如果群体已经收敛(不产生与上一代明显不同的后代),则算法终止。然后说遗传算法为我们的问题提供了一套解决方案。

评论

人口数量是固定的。随着新一代的形成,最不适应的个体死亡,为新的后代提供空间。

这些阶段的顺序被重复,以在每一代中产生比上一代更好的个体。

伪代码

START
Generate the initial population
Compute fitness
REPEAT
    Selection
    Crossover
    Mutation
    Compute fitness
UNTIL population has converged
STOP

Java 实现示例

下面给出了一个遗传算法在 Java 中的实现示例。请随意摆弄代码。

给定一组 5 个基因,每个基因可以保存二进制值 0 和 1 中的一个。

适应值计算为基因组中存在的 1 的数量。如果有五个 1,那么它是最适合的。如果没有 1,那么它有最小的适合度。

这种遗传算法试图最大化适应度函数,以提供由最适合的个体组成的群体,即具有五个 1 的个体。

注意:在这个例子中,在交叉和变异之后,最不适合的个体从新的最适合的后代中被替换。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sample output where the fittest solution is found in the 32nd generation

编辑

mem ento【https://github.com/memento/GeneticAlgorithm】查看这一令人敬畏的遗传算法实现,以及每一代基因库的可视化。

非常感谢 mem ento 与我分享这份报告,并让我添加文章的链接。

图像处理简介:构建一个简单的数字识别器

原文:https://towardsdatascience.com/introduction-to-image-processing-building-a-simple-digit-recognizer-b0c74d70d85d?source=collection_archive---------11-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Toa Heftiba on Unsplash

它必须从某个地方开始

数字识别并不是什么困难或高级的事情。有点像“你好,世界!”程序——不是很酷,但是你可以从这里开始。所以我决定分享我的工作,同时更新知识——这是我很久以前玩的图像。

数据导入和探索

我们从导入所有必需的包开始。

import pandas as pd
import random
import numpy as np
import matplotlib.pyplot as plt
from tqdm import tqdm%matplotlib inline

包含 2 万个手写数字的 MNIST 数据集是这项任务的“Hello World”数据集,它已经预加载在 Colaboratory(基于云的 Python 笔记本,奇妙的东西 BTW)中,所以我们将使用它。这里不需要发明轮子。

# load data
df = pd.read_csv('sample_data/mnist_train_small.csv', header=None)df.head()Out[7]: 
   0    1    2    3    4    5    6   ...   778  779  780  781  782  
0    6    0    0    0    0    0    0 ...     0    0    0    0    0    
1    5    0    0    0    0    0    0 ...     0    0    0    0    0    
2    7    0    0    0    0    0    0 ...     0    0    0    0    0    
3    9    0    0    0    0    0    0 ...     0    0    0    0    0    
4    5    0    0    0    0    0    0 ...     0    0    0    0    0 
len(df)
Out[9]: 20000

正如我们从 head()方法中看到的,数据集中的第一列包含标签和图像的其余像素 28×28——这就是为什么我们多了 784 列。每次修改后检查数据集的长度也是有用的,以确保我们做的一切都是正确的。

接下来,让我们可视化我们的像素,并观看我们的图像。每次运行下面的代码时,我们都使用 randint()来选择随机图像。此外,我们必须将我们的像素转换为 numpy 数组(现在它的类型是 Series ),并将其调整为 28×28 的大小,以便能够绘制它们。

ix = random.randint(0, len(df)-1)
label, pixels = df.loc[ix][0], df.loc[ix][1:]
img = np.array(pixels).reshape((28,28))
print('label: ' + str(label))
plt.imshow(img)label: 9
<matplotlib.image.AxesImage at 0x7ff9ac6fda20>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

数据预处理

现在,为了让我们的生活稍微轻松一点,我们将把我们的数据帧转换成只有两列——标签和图像,其中图像是一个像素的 numpy 数组。此外,我们将减少数据帧的大小,以加快计算速度(首先,我们要确保一切正常,然后我们开始玩模型)

# transforming df for easier manipulation
labels, imgs = [], []
for index, row in df.iterrows():
    label, pixels = row[0], row[1:]
    img = np.array(pixels)
    labels.append(label)
    imgs.append(img)

df2 = pd.DataFrame({'label': labels, 'img': imgs})
df2 = df2[:1000] # checking images using new df structure
ix = random.randint(0, len(df2)-1)
img = df2.loc[ix].img.reshape((28,28))
label = df2.loc[ix].label
print('label: ' + str(label))
plt.imshow(img)label: 9
<matplotlib.image.AxesImage at 0x7ff9a9b997f0>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当我们准备好数据后,我们想把它分成两个数据集:一个用来训练我们的模型,另一个用来测试它的性能。最好的方法是使用 sklearn 。我们设置了一个 test_size=0.2 ,这是该操作的标准值(通常对于测试,我们会留下 20–30%的数据),这意味着对于训练,仍然是 80%。设置 shuffle=True 也是一个很好的做法,因为一些数据集可能有有序的数据,所以模型将学习识别 0 和 1,但不会知道例如 8 的存在。

from sklearn.model_selection import train_test_split
train_df, test_df = train_test_split(df2, test_size=0.2, shuffle=True)print(len(train_df), len(test_df))
800 200train_df.head()Out[12]: 
     label                                                img
296      9  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
488      2  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
124      7  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
862      7  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...
421      9  [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, ...

建立模型

我们检查了数据集的长度和头部——都很好,我们可以开始构建我们的模型了。为此,我们需要安装 pytorch 。如果我们转到“代码片段”并开始在那里键入*“pyt”*,它将显示“安装[pytorch]”,因此我们可以将其插入到我们的笔记本中。如果有人已经安装了 pytorch ,可以跳过这一步。

# http://pytorch.org/
from os.path import exists
from wheel.pep425tags import get_abbr_impl, get_impl_ver, get_abi_tag
platform = '{}{}-{}'.format(get_abbr_impl(), get_impl_ver(), get_abi_tag())
cuda_output = !ldconfig -p|grep cudart.so|sed -e 's/.*\.\([0-9]*\)\.\([0-9]*\)$/cu\1\2/'
accelerator = cuda_output[0] if exists('/dev/nvidia0') else 'cpu'

!pip install -q http://download.pytorch.org/whl/{accelerator}/torch-0.4.1-{platform}-linux_x86_64.whl torchvision# importing torch and setting up the device
import torch
device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")print(device)

接下来,我们必须将数据转换成 pytorch 数据集。torch.utils.data.Dataset是表示数据集的抽象类。自定义数据集应继承数据集并重写以下方法:

  • __len__以便len(dataset)返回数据集的大小。
  • __getitem__支持索引,以便dataset[i]可用于获取其样本
# create torch dataset
from torch.utils.data import Dataset

class MNISTDataset(Dataset):
    def __init__(self, imgs, labels):
        super(MNISTDataset, self).__init__()
        self.imgs = imgs
        self.labels = labels

    def __len__(self):
        return len(self.imgs)

    def __getitem__(self, ix):
        img = self.imgs[ix]
        label = self.labels[ix]
        return torch.from_numpy(img).float(), labeldataset = {
    'train': MNISTDataset(train_df.img.values, train_df.label.values),
    'test': MNISTDataset(test_df.img.values, test_df.label.values)
} 

len(dataset['train'])
800# again checking image, now based on torch dataset
ix = random.randint(0, len(dataset['train'])-1)
img, label = dataset['train'][ix]
print(img.shape, img.dtype)
print(label)
plt.imshow(img.reshape((28,28)))torch.Size([784]) torch.float32
6
<matplotlib.image.AxesImage at 0x7ff99eeeed30>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

pytorch 的美妙之处在于它定义模型的简单性。我们用输入和输出定义我们的层,我们添加一些批量标准化来改进我们的模型(这是一种向神经网络中的任何层提供零均值/单位方差输入的技术)和激活函数,在这种情况下 ReLU。

对于第一个输入,我们有 784 个神经元(每个像素一个神经元)和 512 个输出(这个几乎是随机的——我尝试了几个不同的值,这个表现得很好,所以我离开了)。下一层将有 512 个输入(input _ layer[n+1]= = output _ layer[n])和 256 个输出,接下来有 256 个输入和 128 个输出,最后一层有 128 个输入和 10 个输出(每个神经元代表 10 个数字中的一个)

# create model
import torch.nn as nn

def block(in_f, out_f):
  return nn.Sequential(
      nn.Linear(in_f, out_f),
      nn.BatchNorm1d(out_f),
      nn.ReLU(inplace=True),
      #nn.Dropout(),
  )

model = nn.Sequential(
  block(784,512),
  block(512,256),
  block(256,128),
  nn.Linear(128, 10)
)

model.to(device)

现在我们需要为我们的模型创建一些额外的参数:

  • 标准—计算损失函数,在我们的例子中是 CrossEntropyLoss
  • 优化器—设置学习率
  • 调度器——如果模型没有随时间改进,更新学习率(非常强大的技术,允许我们随时调整系统)
  • data loader——py torch 的类,为数据集提供单进程或多进程迭代器
from torch.utils.data import DataLoader
import torch.optim as optim
from torch.optim.lr_scheduler import StepLR, ReduceLROnPlateau

criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.1)
scheduler = ReduceLROnPlateau(optimizer, 'max', factor=0.1, patience=3, min_lr=0.0001, verbose=True)

dataloader = {
    'train': DataLoader(dataset['train'], batch_size=32, shuffle=True, num_workers=4),
    'test': DataLoader(dataset['test'], batch_size=32, shuffle=False, num_workers=4),
}

训练和评估模型

有了这些,我们就可以开始训练和评估我们的模型了。虽然我们定义了 100 个时期,但是如果模型没有随着时间的推移而改进,那么停止循环也是有用的。这里我们已经设置了early_stop = 10,所以如果模型连续 10 个纪元没有改变,我们将停止训练过程。

训练过程:我们通过将每个图像和标签分配给先前定义的设备来迭代我们的训练数据,我们给我们的模型一个图像,它试图找到正确的类(preds),我们清除所有梯度(zero_grad())并计算损失函数和梯度(loss),执行优化步骤并将新值附加到total_loss数组。

测试过程:我们迭代测试数据,进行预测,计算模型的损失和准确性。在torch.max()中,我们寻找最大值的索引,因为它将代表一个数字的类别,在我们的例子中,它将匹配标签。然后,通过比较标签和预测,我们计算我们的模型的准确性。

每当我们找到最佳模型时,我们就保存它,如果我们点击early_stop,我们就退出并报告结果。通常它不需要所有的 100 个纪元。

# train
best_acc, stop, early_stop = 0, 0, 10
for e in range(100):

    model.train()
    total_loss = []
    for imgs, labels in tqdm(dataloader['train']):
        imgs, labels = imgs.to(device), labels.to(device)
        preds = model(imgs)
        optimizer.zero_grad()
        loss = criterion(preds, labels)
        loss.backward()
        optimizer.step()
        total_loss.append(loss.data)

    model.eval()
    val_loss, acc = [], 0.
    with torch.no_grad():
        for imgs, labels in tqdm(dataloader['test']):
            imgs, labels = imgs.to(device), labels.to(device)
            preds = model(imgs)
            loss = criterion(preds, labels)
            val_loss.append(loss.data)
            _, preds = torch.max(preds, 1)
            acc += (preds == labels).sum().item()

    acc /= len(dataset['test'])
    if acc > best_acc:
        print('\n Best model ! saved.')
        torch.save(model.state_dict(), 'best_model.pt')
        best_acc = acc
        stop = -1

    stop += 1
    if stop >= early_stop:
        break

    scheduler.step(acc)

    print('\n Epoch {}, Training loss: {:4f}, Val loss: {:4f}, Val acc: {:4f}'.format(
        e + 1, np.array(total_loss).mean(), np.array(val_loss).mean(), acc))

print('\n Best model with acc: {}'.format(best_acc)) Out[n]:
Epoch 30, Training loss: 0.015759, Val loss: 0.397337, Val acc: 0.910000
100%|██████████| 25/25 [00:01<00:00, 22.10it/s]
100%|██████████| 7/7 [00:00<00:00, 73.41it/s]Best model with acc: 0.91

当我们找到我们的最佳模型并保存它时,我们可以通过向它输入新数据来玩它,并观察它的表现。

# test
model.load_state_dict(torch.load('best_model.pt'))
model.to(device)
model.eval()

ix = random.randint(0, len(dataset['test'])-1)
img, label = dataset['test'][ix]
pred = model(img.unsqueeze(0).to(device)).cpu()
pred_label = torch.argmax(pred)
print('Ground Truth: {}, Prediction: {}'.format(label, pred_label))
plt.imshow(img.reshape((28,28)))Ground Truth: 5, Prediction: 5
<matplotlib.image.AxesImage at 0x7ff9a9ced748>

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

就像一开始说的,这是一个图像识别的“Hello World ”,我们没有使用卷积神经网络,它通常用于这样的任务,只是入门级别的理解流程。我通常不处理图像,所以如果有错误,请告诉我。对我来说,这是一次很好的复习,希望对其他人也有帮助。

你可以在 GitHub 上找到 Python 笔记本的代码

原载于 2018 年 11 月 14 日【sergilehkyi.com】

Python 中使用 Plotly 的交互式时间序列可视化简介

原文:https://towardsdatascience.com/introduction-to-interactive-time-series-visualizations-with-plotly-in-python-d3219eb7a7af?source=collection_archive---------3-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(Source)

使用强大的 plotly 可视化库启动和运行

总有一天,即使是最喜爱的工具,也有必要放弃。Matplotlib 实现了快速创建简单图表的目的,但我对定制图表或做一些看似简单的事情(如让 x 轴正确显示日期)所需的代码量感到沮丧。

有一段时间,我一直在寻找一个替代方案——不是完全的替代方案,因为 Matplotlib 对探索仍然有用——理想情况下,一个具有交互元素的库,让我专注于我想展示的内容,而不是陷入如何展示它的细节中。进入 plotly ,一个声明式可视化工具,带有一个易于使用的 Python 库用于交互式图形。

在本文中,我们将通过创建基本的时间序列可视化来介绍 plotly 库。这些图表虽然很容易制作,但将是完全交互式的图表,随时可供展示。在这个过程中,我们将学习该库的基本思想,这将使我们能够快速构建令人惊叹的可视化效果。如果你一直在寻找 matplotlib 的替代品,那么正如我们将看到的,plotly 是一个有效的选择。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Interactive Visualization made with a few lines of Plotly code

本文的完整代码在 GitHub 上有。您还可以在 nbviewer 上查看带有交互元素的笔记本。本文中使用的数据是我在 Cortex Building Intelligence 工作时获得的匿名建筑能源时间序列数据。如果你想用你的网络开发技能来帮助建筑节能,那么联系我们,因为我们正在招聘

Plotly 简介

Plotly 是一家制作可视化工具的公司,包括一个 Python API 库。(Plotly 还制作了 Dash ,一个用 Python 代码构建交互式网络应用的框架)。对于本文,我们将坚持在 Jupyter 笔记本中使用plotly Python 库,并在在线 plotly 编辑器中润色图像。当我们制作一个 plotly 图形时,默认情况下会在网上发布,这使得分享可视化变得容易。

你需要创建一个免费的 plotly 帐户,给你 25 个公共图表和 1 个私人图表。一旦达到配额,您必须删除一些旧图表来制作新图表(或者您可以在离线模式下运行,图像只出现在笔记本中)。安装 plotly ( pip install plotly)并运行以下命令来验证库,替换用户名和 API 密钥:

import plotly# Authenticate with your account
plotly.tools.set_credentials_file(username='########',                                              
                                  api_key='******')

标准 plotly 导入以及离线运行的设置如下:

import plotly.plotly as py
import plotly.graph_objs as go# Offline mode
from plotly.offline import init_notebook_mode, iplot
init_notebook_mode(connected=True)

当我们在离线模式下制作图时,我们会在图像的右下角获得一个链接,以导出到 plotly 在线编辑器进行润色和共享。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example of image in the notebook with link to edit in plotly.

Plotly 的优势

plotly(Python 库)使用声明式编程,这意味着我们编写代码描述我们想要做什么而不是如何做。我们提供基本框架和最终目标,并让 plotly 指出实现细节。在实践中,这意味着构建一个形象花费的精力更少,使我们能够专注于呈现什么以及如何解释它。

如果你不相信这种方法的好处,那么去看看几十个例子,比如下面的用 50 行代码做的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

US City Populations (Source)

时间序列数据

对于这个项目,我们将使用来自我在Cortex Building Intelligence工作的真实世界建筑数据(数据已经匿名)。由于季节性、每日和每周模式以及天气条件的剧烈影响,建筑能源数据对时间序列分析提出了有趣的挑战。有效地可视化这些数据可以帮助我们了解建筑的反应以及哪里有节能的机会。

(注意,我交替使用术语“功率”和“能量”,尽管能量是做功的能力,而功率是能量消耗的比率。从技术上讲,功率以千瓦(KW)为单位,电能以千瓦时(KWh)为单位。你知道的越多!)

我们的数据在数据帧中,在列上有一个多索引,用于跟踪传感器类型和传感器编号。该索引是一个日期时间:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Time Series Building Data

使用多索引数据框架是完全不同的另一篇文章(这里有文档),但是我们不会做任何太复杂的事情。要访问单个列并绘制它,我们可以执行以下操作。

import pandas as pd # Read in data with two headers
df = pd.read_csv('building_one.csv', header=[0,1], index_col=0)# Extract energy series from multi-index
energy_series = df.loc[:, ('Energy', '3')]# Plot
energy_series.plot()

默认绘图(由 matplotlib 提供)如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这并不可怕,尤其是对于一行代码来说。但是,没有交互性,视觉上也不够吸引人。是时候进入剧情了。

基本时间序列图

就像散景一样,制作一个基本的情节需要在 plotly 中做更多的工作,但作为回报,我们得到了更多,比如内置的交互性。

我们从一个数据对象开始构建一个图。即使我们想要一个折线图,我们也使用go.Scatter()。Plotly 足够聪明,如果我们超过 20 个点,它会自动给我们一个线图!对于最基本的图形,我们只需要 x 和 y 值:

energy_data = go.Scatter(x=energy_series.index,
                         y=energy_series.values)

然后,我们使用默认设置和一些标题创建一个布局:

layout = go.Layout(title='Energy Plot', xaxis=dict(title='Date'),
                   yaxis=dict(title='(kWh)'))

(我们使用与{'x': 'value'}相同的dict(x = 'value')语法)。

最后,我们可以创建我们的图形,并在笔记本中交互显示它:

fig = go.Figure(data=[energy_data], layout=layout)
py.iplot(fig, sharing='public')

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Basic time series plot in plotly

马上,我们有了一个完全交互式的图表。我们可以探索模式,检查单个点,并将绘图下载为图像。请注意,我们甚至不需要指定轴的类型或范围,plotly 为我们做了完全正确的事情。我们甚至不需要额外的工作就可以得到格式良好的悬停消息。

此外,该图会自动导出到 plotly,这意味着我们可以与任何人共享该图表。我们还可以单击“编辑图表”,在在线编辑器中打开它,在一个易于使用的界面中进行我们想要的任何更改:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Online editor interface

如果您在在线编辑器中编辑图表,那么您可以为您创建的精确图表和样式自动生成 Python 代码!

改善情节

即使是 Plotly 中一个基本的时间序列图也令人印象深刻,但我们可以用多几行代码来改进它。例如,假设我们想要比较建筑物的蒸汽使用量和能源。这两个量有非常不同的单位,所以如果我们把它们放在同样的尺度上,就不会有结果。在这种情况下,我们必须使用第二个 y 轴。在 matplotlib 中,这需要大量的格式化工作,但是在 Plotly 中我们可以很容易地做到。

第一步是添加另一个数据源,但是这次指定yaxis='y2'

# Get the steam data
steam_series = df.loc[:, ("Steam", "4")]# Create the steam data object
steam_data = go.Scatter(x=steam_series.index,
                        y=steam_series.values,
                        # Specify axis
                        yaxis='y2')

(我们还添加了一些其他参数来改进样式,这可以在笔记本中看到)。

然后,当我们创建布局时,我们需要添加第二个 y 轴。

layout = go.Layout(height=600, width=800,
                   title='Energy and Steam Plot',
                   # Same x and first y
                   xaxis=dict(title='Date'),
                   yaxis=dict(title='Energy', color='red'),
                   # Add a second yaxis to the right of the plot
                   yaxis2=dict(title='Steam', color='blue',
                               overlaying='y', side='right')
                   )fig = go.Figure(data=[energy_data, steam_data], layout=layout)
py.iplot(fig, sharing='public')

当我们显示图表时,我们在同一张图表上得到蒸汽和能量,轴的比例适当。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

通过一点在线编辑,我们得到了一个成品:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Finished plot of energy and steam.

绘图注释

绘图注释用于调出可视化的各个方面以引起注意。例如,我们可以在查看一周的数据时,突出显示每天的高蒸汽消耗量。首先,我们将蒸汽传感器划分为一周(称为steam_series_four)并创建一个格式化的数据对象:

# Data object
steam_data_four = go.Scatter(
                     x=steam_series_four.index,
                     y=steam_series_four.values,
                     line=dict(color='blue', width=1.1),
                     opacity=0.8,
                     name='Steam: Sensor 4',
                     hoverinfo = 'text',
                     text = [f'Sensor 4: {x:.1f} Mlbs/hr' for x in
                             steam_series_four.values])

然后,我们将找到该传感器的每日最大值(代码见笔记本):

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了构建注释,我们将使用 list comprehension 为每个日最大值添加一个注释(four_highs就是上面的系列)。每个注释需要一个位置(xytext):

# Create a list of annotations
four_annotations = [dict(x = date, y = value, 
           xref = 'x', yref = 'y', 
           font=dict(color = 'blue'),
           text = f'{format_date(date)}<br> {value[0]:.1f} Mlbs/hr')
                    for date, value in zip(four_highs.index, 
                                           four_highs.values)]four_annotations[:1]**{'x': Timestamp('2018-02-05 06:30:00'),
  'y': 17.98865890412107,
  'xref': 'x',
  'yref': 'y',
  'font': {'color': 'blue'},
  'text': 'Mon <br> 06:30 AM<br> 18.0 Mlbs/hr'}}**

(文本中的<br>为 html,由 plotly 读取并显示)。

我们可以修改注释的其他参数,但是我们会让 plotly 处理细节。向绘图添加注释就像将它们传递给layout一样简单:

layout = go.Layout(height=800, width=1000, 
                   title='Steam Sensor with Daily High Annotations',
                   annotations=four_annotations)

在在线编辑器中稍作后期处理后,我们最终的剧情是:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Final plot with steam sensor annotations

额外的注释可以通过显示蒸汽使用的每日峰值出现的时间,让我们深入了解我们的数据。反过来,这将允许我们向建筑工程师提出蒸汽启动时间建议。

关于 plotly 最好的部分是,我们可以快速获得一个基本的绘图,并通过多一点代码来扩展功能。当我们想要添加更多的功能时,对基本情节的前期投资是有回报的。

结论

我们只是触及了我们在《T4》中能做的事情的表面。我将在以后的文章中探索其中的一些功能,而参考笔记本了解如何添加更多的交互性,比如选择菜单。最终,我们可以用 Python 代码在 Dash 中构建可部署的 web 应用程序。目前,我们知道如何在 plotly 中创建基本但有效的时间序列可视化。

这些图表为我们的小代码投资提供了很多,通过修改和在线分享这些图表,我们可以构建一个完整的、像样的产品。

尽管我并不是要放弃 matplotlib——单线条形图和折线图很难被击败——但很明显,将 matplotlib 用于自定义图表并不是一个好的时间投资。相反,我们可以使用其他库,包括 plotly,来有效地构建全功能的交互式可视化。在图表中查看数据是数据科学的乐趣之一,但编写代码通常是痛苦的。幸运的是,使用 plotly,Python 中的可视化非常直观,甚至可以愉快地创建和实现图形的目标:直观地理解我们的数据。

一如既往,我欢迎反馈和建设性的批评。可以通过 Twitter @koehrsen_will 或者通过我的个人网站 willk.online 找到我。

机器学习中的 Python 迭代器介绍

原文:https://towardsdatascience.com/introduction-to-iterators-and-generators-in-python-for-data-science-and-machine-learning-bce75e136360?source=collection_archive---------8-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Ricardo Gomez Angel on Unsplash

从事机器学习和人工智能的人非常依赖 Python 中的迭代器(和生成器)。它们是语言的核心概念,在机器学习包中使用很多,如 scikit-learnKeras 。理解它们是如何工作的以及为什么 Pythonistas 们使用它们会给你带来两个好处:

  1. 你可以更有效地使用它们。
  2. 你可以更快地理解与他们相关的问题。这种理解将为您节省大量的代码编写和调试时间。

我将分两步给你必要的背景知识。首先,我向您介绍一些基本概念,包括一些简单的例子。其次,我将向您介绍来自 scikit-learn 的两个示例性实现。在这一步中,我将向您展示源代码的简化版本。这种方法将让您了解开发人员如何将这些抽象概念转化为现实生活中的工具。

迭代器的一般概念

什么是迭代器?

迭代器是 Python 对象,一次返回一个元素。每次你向迭代器请求下一个项时,它都会调用它的__next__方法。如果有另一个值可用,迭代器将返回它。如果没有,它会引发一个StopIteration异常。

这种行为(只在被要求时返回下一个元素)有两个主要优点:

  1. 迭代器需要更少的内存空间。他们记住了上一个值和到达下一个值的规则,而不是记住一个(可能很长的)序列的每一个元素。
  2. 迭代器不检查它们产生的序列有多长。例如,他们不需要知道一个文件有多少行或者一个文件夹中有多少个文件来遍历它们。

重要的一点是:不要混淆迭代器和可迭代对象。Iterables 是可以通过使用它们的__iter__方法创建迭代器的对象。这就是 Python 在 for-loops 中做的事情:

for classifier in ["XGBoost", "Logistic Regression", "SVM"]:
    if classifier == "XGBoost":
        print(f"{classifier} is the best! Maybe.")
    else:
        print(f"{classifier} is fun. Somehow.")

在内部,Python 调用在in之后提交的任何东西的__iter__方法。然后在 while 循环中对创建的迭代器使用next,直到引发StopIteration异常。你可以在这里找到完整的解释和这里。在 Python 中可以构建多种类型的 for 循环的原因是它们有一个实现的__iter__方法。

Iterables 很方便,但是它们没有“纯”迭代器的优点。例如,你转换成迭代器的链表已经占用了内存。如果可以的话,尽量直接使用迭代器而不是可迭代的。

什么是发电机?

生成器是构建迭代器的一种简化方式。不是实现迭代协议,生成器是用yield语句返回值的函数。yieldreturn的区别在于,生成器会跟踪它们的局部变量。每次生成器到达yield时,都会返回值。然后,它会记住函数中变量的当前状态,并等待下一次调用。

机器学习包中的生成器

我想向您展示两个例子在 scikit-learn 中的实现。不过在 Keras 或者 Tensorflow 中也有例子。如果你想加深理解,我鼓励你去寻找它们。

示例 1: KFold

机器学习的主要挑战之一是避免过度拟合。许多算法都有超参数或修改来解决这个问题,但最重要的概念是交叉验证。对于一个很好的概述,我推荐这篇文章:

[## 在 Python 中训练/测试分割和交叉验证

大家好!在我上一篇关于 Python 中线性回归的文章之后,我认为写一篇文章是很自然的…

towardsdatascience.com](/train-test-split-and-cross-validation-in-python-80b61beca4b6)

在这里,我们正在寻找 K 倍交叉验证。其想法是将数据集分割成多个折叠,并使用每个折叠一次来测试在剩余折叠上训练的模型。例如,如果您使用三个折叠,模型将在其中两个上训练,并使用一个进行测试。

这里使用生成器的原因是,您不必一开始就记住所有的索引组合。知道在相应的回合中测试哪些指数就足够了。其余的将用于培训。

让我们看一下scikit-learn 的KFold 的源代码(第 357 到 434 行)来看看生成器是如何实现的:

class KFold(...):
    def __init__(...):
        ...
    def _iter_test_indices(...):
        ...
        current = 0
        for fold_size in fold_sizes:
            start, stop = current, current + fold_size
            yield indices[start:stop]
            current = stop

靠近类定义的末尾有一个yield语句,表示一个生成器函数。方法的名称_iter_test_indices 表明生成器只产生测试文件夹的索引。正如我之前所写的,训练将在所有其他指数上进行,因此没有必要显式计算它们。

第一次调用生成器时,它从索引 0 ( current=0)开始,加上折叠的大小,得到这个折叠的最后一个索引。然后产生这些指数。下一次,在运行另一轮 for 循环之前,它查找它的局部变量并将current设置为来自上一次迭代的stop的值。

示例 2:梯度增强分类器

梯度提升背后的基本思想是组合足够多的弱学习者来获得强模型。与并行训练许多学习者的 bagging 方法(如 random forest)相反,boosting 以迭代方式工作。它训练一个弱学习者,评估它的主要弱点,并试图在下一轮中弥补它们。

这种算法的迭代特性迫切需要生成器。让我们检查一下GradientBoostingClassifier的源代码,更具体地说是第 1693 到 2156 行。为了简单起见,我们只关注GradientBoostingClassfier类中的一个特定生成器(第 2151 行):

def staged_predict_proba(...):
    ...
    for score in self._staged_decision_function(X):
          yield self.loss_._score_to_proba(score)

我在这里省略了很多代码,但基本思想保持不变。梯度增强阶段是迭代过程中的一个步骤。这个生成器在每一步都监视测试集上的错误。这里使用生成器的原因是,您不必定义该模型的特定实例中有多少个阶段。

摘要

当然,迭代器、可迭代对象和生成器还有很多。我最喜欢的关于迭代器和其他 Python 对象之间关系的博文是 Datacamp 的这篇:

[## Python 迭代器教程

迭代器是 Python 无处不在的灵魂。它们无处不在,你一定在某个节目中见过它们…

www.datacamp.com](https://www.datacamp.com/community/tutorials/python-iterator-tutorial)

我希望这篇博文能帮助你掌握基本思想。我还希望源代码示例能够缩小基本概念和实际实现之间的差距。

感谢阅读!如果你喜欢这篇文章,留下一些吧👏🏻并分享一下!让我知道你在评论和 推特 上的想法。我也很乐意连接上LinkedIn。再次感谢,继续学习!

k 近邻介绍

原文:https://towardsdatascience.com/introduction-to-k-nearest-neighbors-3b534bb11d26?source=collection_archive---------3-----------------------

什么是 k 近邻(kNN),一些有用的应用,以及它是如何工作的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

k-最近邻(kNN) 分类方法是机器学习中最简单的方法之一,也是向你介绍机器学习和分类的一个很好的方式。在最基本的层面上,本质上是通过在训练数据中找到最相似的数据点进行分类,并基于它们的分类做出有根据的猜测。虽然理解和实现起来非常简单,但这种方法已经在许多领域得到了广泛的应用,例如在推荐系统语义搜索异常检测中。

正如我们在任何机器学习问题中需要的那样,我们必须首先找到一种方法将数据点表示为特征向量。特征向量是我们对数据的数学表示,并且由于我们数据的期望特征可能不是固有的数值,因此可能需要预处理和特征工程来创建这些向量。给定具有 N 个独特特征的数据,特征向量将是长度为 N 的向量,其中向量的条目 I 表示特征 I 的数据点的值。因此,每个特征向量可以被认为是 R^N 中的一个点。

现在,与大多数其他分类方法不同,kNN 属于懒惰学习,这意味着在分类之前没有**明确的训练阶段。相反,任何概括或抽象数据的尝试都是在分类的基础上进行的。虽然这确实意味着一旦我们有了数据,我们就可以立即开始分类,但这种类型的算法存在一些固有的问题。我们必须能够将整个训练集保存在内存中,除非我们对数据集应用某种类型的约简,并且执行分类在计算上可能是昂贵的,因为算法解析每个分类的所有数据点。由于这些原因,kNN 倾向于在没有很多特征的较小数据集上工作得最好。**

一旦我们形成了我们的训练数据集,它被表示为一个 M x N 矩阵,其中 M 是数据点的数量, N 是特征的数量,我们现在可以开始分类了。对于每个分类查询,kNN 方法的要点是:

**1.** Compute a distance value between the item to be classified and every item in the training data-set**2.** Pick the k closest data points (the items with the k lowest distances)**3.** Conduct a **“majority vote”** among those data points — the dominating classification in that pool is decided as the final classification

在进行分类之前,必须做出两个重要的决定。一个是将要使用的 k 的值;这可以任意决定,或者您可以尝试交叉验证来找到一个最佳值。接下来,也是最复杂的,是将要使用的距离度量

有许多不同的方法来计算距离,因为它是一个相当模糊的概念,并且要使用的适当度量总是由数据集和分类任务来确定。然而,两个流行的是欧几里德距离余弦相似度

欧几里德距离大概是你最熟悉的一个;它本质上是通过从要分类的点中减去训练数据点而获得的向量的幅度。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

General formula for Euclidean distance

另一个常见的度量是余弦相似性。余弦相似度不是计算大小,而是使用两个向量之间的方向差异。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

General formula for Cosine similarity

选择一个度量标准通常很棘手,最好使用交叉验证来决定,除非您事先有一些明确的见解,可以导致使用一个而不是另一个。例如,对于像单词向量这样的东西,您可能希望使用余弦相似度,因为单词的方向比分量值的大小更有意义。通常,这两种方法会在大致相同的时间内运行,并且会受到高维数据的影响。

在完成上述所有工作并决定一个度量标准后,kNN 算法的结果是一个将 R^N 划分为多个部分的决策边界。每一个部分(下面有明显的颜色)代表分类问题中的一个类别。边界不需要用实际的训练示例来形成,而是使用距离度量和可用的训练点来计算。通过将 R^N 分成(小)块,我们可以计算该区域中假设数据点的最可能类别,因此我们将该块着色为在该类别的区域中。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这些信息是开始实现算法所需要的全部,这样做应该相对简单。当然,有许多方法可以改进这个基本算法。常见的修改包括加权和特定的预处理,以减少计算和减少噪声,例如用于特征提取和维数减少的各种算法。此外,kNN 方法也被用于回归任务,尽管不太常用,其操作方式与通过平均的分类器非常相似。

Kaggle 内核简介

原文:https://towardsdatascience.com/introduction-to-kaggle-kernels-2ad754ebf77?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在《人工智能历险记》的这一集里,你会发现什么是 Kaggle 内核,以及如何开始使用它们。虽然这一集没有爆米花,但我可以保证 Kaggle 内核正在爆开!

Kaggle 是一个进行和分享数据科学的平台。你可能听说过他们的一些比赛,经常有现金奖励。这也是实践数据科学和向社区学习的好地方。

什么是 Kaggle 内核?

Kaggle 内核本质上是浏览器中的 Jupyter 笔记本,可以在你眼前运行,全部免费!让我再说一遍,以防你错过,因为这太神奇了:

Kaggle Kernels 是一个在浏览器中运行 Jupyter 笔记本的免费平台!

这意味着您可以省去设置本地环境的麻烦,并且在世界上任何有互联网连接的地方,您的浏览器中都有一个 Jupyter 笔记本环境。

不仅如此,笔记本电脑的处理能力来自云中的服务器,而不是您的本地机器,因此您可以进行大量的数据科学和机器学习而不会耗尽笔记本电脑的电池!

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

http://blog.kaggle.com/2017/09/21/product-launch-amped-up-kernels-resources-code-tips-hidden-cells/

Kaggle 最近升级了所有的内核,以拥有更强的计算能力和内存,并将运行一个进程的时间延长到 60 分钟!

好了,我已经滔滔不绝地说了够了。让我们看看它实际上是什么样子。

运行中的内核

一旦我们在kaggle.com创建了一个账户,我们就可以选择一个数据集来玩,并且只需点击几下鼠标就可以运行一个新的内核或笔记本。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们在中开始的数据集是预加载在该内核的环境中的,因此不需要将数据集推送到机器中,并等待大型数据集通过网络进行复制。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

当然,如果您愿意,您仍然可以将额外的文件(最多 1GB)加载到内核中。

在我们的例子中,我们将继续使用fashion-mnist数据集。这是一个包含 10 类服装和配饰的数据集,比如裤子、包、高跟鞋、衬衫等等。有 50k 训练样本,10k 评估样本。让我们探索一下我们的 Kaggle 内核中的数据集。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

查看数据集,它以 csv 文件的形式在 Kaggle 上提供。原始数据是 28x28 像素的灰度图像,它们在 csv 文件中被展平为 784 个不同的列。该文件还包含一个表示时尚项目的索引(从 0 到 9)的列。

数据加载

由于数据集已经在环境中,并且 pandas 已经加载,让我们用它来读取这些。csv 文件转换成pandas数据帧,一个用于训练,一个用于预测。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Notice that the data is stored in the ‘input’ directory, one level up.

如果你想跟随,我的 Kaggle 内核在这里:https://www.kaggle.com/yufengg/fashion-mnist/

[## 时尚-MNIST

Kaggle 内核使用来自时尚 MNIST 的数据

www.kaggle.com](https://www.kaggle.com/yufengg/fashion-mnist/)

数据探索

既然我们已经将数据加载到 DataFrame 中,我们就可以利用它带来的所有特性,这些特性我们在前面的章节中已经介绍过了。我们将使用head()显示前 5 行,并运行describe()来了解数据集结构的更多信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Looks like the dataset is shuffled already

数据可视化

此外,最好将这些图像可视化,这样它们对我们来说就不仅仅是一排排的数字了。让我们用matplotlib来看看这些图片是什么样子的。

这里我们将使用matplotlib.pyplot库,通常导入为plt,将像素值数组显示为图像。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,这些图像虽然模糊,但仍然可以识别出它们所声称的服装和配饰。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Kaggle Kernels 允许我们在一个完全交互式的笔记本环境中工作,几乎不需要任何设置,我想强调的是,我们不需要进行任何 python 环境配置或安装库,这真的很酷!

你可以在这里看到完整的内核:https://www.kaggle.com/yufengg/fashion-mnist/

[## 时尚-MNIST

Kaggle 内核使用来自时尚 MNIST 的数据

www.kaggle.com](https://www.kaggle.com/yufengg/fashion-mnist/)

你已经使用 Kaggle 内核了吗?你最喜欢的功能、技巧和诀窍是什么?

感谢阅读本集云 AI 冒险。如果你喜欢这个系列,请为这篇文章鼓掌让我知道。如果你想要更多的机器学习动作,一定要关注 Medium 上的me或订阅 YouTube 频道来观看未来的剧集。更多剧集即将推出!

Python 中的线性回归简介

原文:https://towardsdatascience.com/introduction-to-linear-regression-in-python-c12a072bedf0?source=collection_archive---------0-----------------------

如何用 Python statsmodels & scikit-learn libraries.实现线性回归的快速教程

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Example linear regression model using simulated data

线性回归是一种基本的预测分析技术,使用历史数据来预测输出变量。它在预测建模中很受欢迎,因为它容易理解,可以用简单的英语解释。

线性回归模型在一系列行业中有许多实际应用,例如经济学(例如预测增长)、商业(例如预测产品销售、员工绩效)、社会科学(例如从性别或种族预测政治倾向)、医疗保健(例如从体重预测血压水平、从生物因素预测疾病发作)等等。

了解如何实现线性回归模型可以挖掘数据中的故事来解决重要问题。我们将使用 Python,因为它是处理和建模数据的强大工具。它有一系列用于线性回归建模的软件包。

基本的想法是,如果我们可以用一个线性回归模型来拟合观察到的数据,那么我们就可以用这个模型来预测任何未来的值。例如,假设我们从历史数据中发现,房子的价格( P )与房子的大小( S )呈线性相关——事实上,我们发现房子的价格正好是其大小的 90 倍。该等式将如下所示:

P = 90S*

有了这个模型,我们就可以预测任何房子的价格。如果我们有一栋 1500 平方英尺的房子,我们可以计算出它的价格:

P = 90 * 1500 = 135000 美元

在这篇博文中,我们涵盖了:

  1. 模型背后的基本概念和数学
  2. 如何使用模拟数据从头实现线性回归
  3. 如何用statsmodels实现线性回归
  4. 如何使用scikit-learn实现线性回归

这篇简短的教程改编自下一期 XYZPython 线性回归课程,其中包括浏览器内沙盒环境、要完成的任务以及使用公共数据集的项目。

基本概念和数学

线性回归模型中有两种变量:

  • 输入预测变量是帮助预测输出变量值的变量。就是俗称的 X
  • 输出变量是我们想要预测的变量。俗称 Y

为了使用线性回归估计 Y ,我们假设等式:

Yₑ = α + β X

其中 Y ₑ是基于我们的线性方程的 Y 的估计值或预测值。

我们的目标是找到使 YY ₑ.之间的差异最小化的参数 αβ 的统计显著值

如果我们能够确定这两个参数的最佳值,那么我们将有最佳拟合的线,我们可以用它来预测 Y 的值,给定 X 的值。

那么,我们如何估算 αβ ?我们可以用一种叫做 普通最小二乘法 的方法。

普通最小二乘法

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Green lines show the difference between actual values Y and estimate values Y

最小二乘法的目的是找到使 YY ₑ.之间的平方差之和最小的 αβ 的值这里我们不进行推导,但是使用微积分我们可以表明未知参数的值如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

其中 X 值的平均值,而ȳY 值的平均值。

如果你熟悉统计学,你可能会把 β 简单地理解为
Cov(X,Y) / Var(X)。

从头开始线性回归

在本文中,我们将使用两个 Python 模块:

  • [statsmodels](https://www.statsmodels.org/stable/index.html) —一个模块,为许多不同的统计模型的估计,以及进行统计测试和统计数据探索提供类和函数。
  • [scikit-learn](http://scikit-learn.org/stable/) —为数据挖掘和数据分析提供简单高效工具的模块。

在我们开始之前,了解如何从头开始实现这个模型是很有用的。了解包在幕后是如何工作的是很重要的,所以你不能只是盲目地实现模型。

首先,让我们模拟一些数据,看看预测值( Y ₑ)与实际值( Y )有何不同:

如果运行上述代码(例如,在 Jupyter 笔记本中),将会输出如下内容:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

为了使用 OLS 方法估计 y ,我们需要计算xmeanymeanXy ( xycov)的协方差以及 X ( xvar)的方差,然后才能确定alphabeta的值。

**Out:**
alpha = 2.0031670124623426
beta = 0.32293968670927636

太好了,我们现在有了对alphabeta的估计!我们的模型可以写成 *Yₑ = 2.003 + 0.323 X,*我们可以做出预测:

**Out:**
array([3.91178282, 2.81064315, 3.27775989, 4.29675991, 3.99534802,
       1.69857201, 3.25462968, 2.36537842, 2.40424288, 2.81907292,
       ...
       2.16207195, 3.47451661, 2.65572718, 3.2760653 , 2.77528867,
       3.05802784, 2.49605373, 3.92939769, 2.59003892, 2.81212234])

让我们对照y的实际值绘制我们的预测ypred,以便更好地直观理解我们的模型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

蓝线是我们的最佳拟合线, Yₑ = 2.003 + 0.323 X. 从这个图中我们可以看出, Xy 之间存在正的线性关系。使用我们的模型,我们可以从 X 的任何值预测 y

例如,如果我们有一个值 X = 10 ,我们可以预测:
yₑ= 2.003+0.323(10)= 5.233。

statsmodels进行线性回归

既然我们已经从头开始学习了如何实现线性回归模型,我们将讨论如何使用statsmodels库中的ols方法。

为了演示这种方法,我们将使用一个非常受欢迎的advertising数据集,该数据集是关于不同媒体的广告费用以及特定产品的销售额。你可以在这里下载这个数据集

在本例中,我们将只关注TV变量——我们将探究电视广告支出是否能预测产品的销售数量。让我们从使用read_csv()将这个 csv 文件作为pandas数据帧导入开始:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

首先,我们使用statsmodelsols函数初始化我们的简单线性回归模型。这采用公式y ~ X,其中X是预测变量(TV广告成本)y是输出变量(Sales)。然后,我们通过调用 OLS 对象的fit()方法来拟合模型。

我们不再需要自己计算alphabeta,因为这种方法会自动为我们计算!调用model.params会显示模型的参数:

**Out:**
Intercept    7.032594
TV           0.047537
dtype: float64

在我们一直使用的符号中, α 是截距, β 是斜率,即 α = 7.032, β = 0.047。

因此,模型的等式将是: *销售= 7.032+0.047 电视

简单地说,这意味着平均来说,如果我们在电视广告上花了 100 美元,我们应该可以卖出 11.73 台。

现在我们已经拟合了一个简单的回归模型,我们可以尝试使用.predict方法根据我们刚刚推导出的公式来预测销售额。

我们还可以通过绘制sales_pred与电视广告成本的对比图来可视化我们的回归模型,以找到最佳拟合线:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

我们可以看到,电视广告成本和销售额之间存在正线性关系——换句话说,在电视广告上花费更多预测了更高的销售额!

有了这个模型,我们可以从电视广告的任何花费中预测销售额。例如,如果我们将电视广告费用增加到 400 美元,我们可以预测销售量将增加到 26 台:

**Out:**
0    26.04725
dtype: float64

scikit-learn进行线性回归

我们已经学会了使用statsmodels实现线性回归模型…现在让我们学习使用scikit-learn来实现它!

对于这个模型,我们将继续使用advertising数据集,但这次我们将使用两个预测变量来创建一个多元线性回归模型。这是一个简单的线性回归模型,有一个以上的预测值,建模如下:

Yₑ = α + β₁X₁ + β₂X₂ + … + βₚXₚ, 其中 p 为预测数。

在我们的例子中,我们将使用变量TVRadio预测Sales,即我们的模型可以写成:

销售额= α + β₁TV + β₂Radio.

首先,我们初始化我们的线性回归模型,然后将模型拟合到我们的预测值和输出变量:

同样,我们不需要自己计算alphabetas的值——我们只需要为alpha调用.intercept_,为带有系数beta1beta2的数组调用.coef_:

**Out:**
alpha = 2.921099912405138
betas = [0.04575482 0.18799423]

因此,我们的模型可以写成:

*销量= 2.921+0.046 *电视+0.1880 收音机。

我们可以通过简单地使用.predict()来预测值:

**Out:**
array([20.555464, 12.345362, 12.337017, 17.617115, 13.223908,
       12.512084, 11.718212, 12.105515,  3.709379, 12.551696,
       ...
       12.454977,  8.405926,  4.478859, 18.448760, 16.4631902,
        5.364512,  8.152375, 12.768048, 23.792922, 15.15754285])

既然我们已经将多元线性回归模型拟合到我们的数据中,我们就可以根据电视和广播广告成本的任何组合来预测销售额了!例如,如果我们想知道,如果我们在电视广告上投资 300 美元,在广播广告上投资 200 美元,我们会取得多少销售额……我们所要做的就是输入这些数值!

**Out:**
[54.24638977]

这意味着,如果我们在电视广告上花 300 美元,在广播广告上花 200 美元,我们预计平均会卖出 54 台。

我希望你喜欢这个关于线性回归基础的简短教程!

我们讲述了如何在 Python 中使用statsmodelsscikit-learn来实现线性回归。在实践中,您必须知道如何验证您的模型和测量功效,如何为您的模型选择重要变量,如何处理分类变量,以及何时以及如何执行非线性转换。

我们有涵盖所有这些主题的完整课程(甚至更多!)这里在下一届 XYZ,如果你有兴趣学习更多关于 Python 线性回归的知识!

机器学习算法简介:线性回归

原文:https://towardsdatascience.com/introduction-to-machine-learning-algorithms-linear-regression-14c4e325882a?source=collection_archive---------0-----------------------

从头开始构建您自己的模型

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

人工智能最近变得流行起来。不同学科的人都在尝试应用人工智能来简化他们的任务。例如,经济学家正在使用人工智能预测未来的市场价格以获取利润,医生使用人工智能对肿瘤进行分类,气象学家使用人工智能预测天气,人力资源招聘人员使用人工智能检查申请人的简历以验证申请人是否符合工作的最低标准,等等。人工智能这种无处不在的使用背后的推动力是机器学习算法。对于任何想学习最大似然算法但还没有涉足的人来说,你来对地方了。每个机器学习爱好者开始使用的基本算法是线性回归算法。因此,我们将做同样的事情,因为它为我们建立和学习其他 ML 算法提供了一个基础。

什么是线性回归??

在了解什么是线性回归之前,让我们习惯于回归。回归是一种基于独立预测值对目标值建模的方法。这种方法主要用于预测和找出变量之间的因果关系。回归技术的主要区别在于自变量的数量以及自变量和因变量之间的关系类型。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Linear Regression

简单线性回归是一种回归分析,其中自变量的数量为 1,自变量(x)和因变量(y)之间存在线性关系。上图中的红线被称为最佳拟合直线。根据给定的数据点,我们试图绘制一条线,最好地模拟这些点。该线可以基于如下所示的线性方程进行建模。

y = a_0 + a_1 * x      ## Linear Equation

线性回归算法的目的是找到 A0 和 a1 的最佳值。在继续讨论算法之前,让我们先来看看两个重要的概念,为了更好地理解线性回归,你必须知道这两个概念。

价值函数

成本函数帮助我们计算出 a_0 和 a_1 的最佳可能值,这将为数据点提供最佳拟合线。因为我们想要 a_0 和 a_1 的最佳值,所以我们将这个搜索问题转化为最小化问题,我们希望最小化预测值和实际值之间的误差。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Minimization and Cost Function

我们选择上面的函数来最小化。预测值和地面真实值之间的差异测量误差差。我们对所有数据点的误差差求平方并求和,然后将该值除以数据点的总数。这提供了所有数据点的平均平方误差。因此,该成本函数也被称为均方误差(MSE)函数。现在,使用这个 MSE 函数,我们将改变 a_0 和 a_1 的值,使 MSE 值稳定在最小值。

梯度下降

理解线性回归需要的下一个重要概念是梯度下降。梯度下降是一种更新 A0 和 a1 以降低成本函数(MSE)的方法。想法是我们从 A0 和 a1 的一些值开始,然后我们迭代地改变这些值以降低成本。梯度下降帮助我们了解如何改变这些值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Gradient Descent

打个比方,想象一个 U 形的坑,你站在坑的最高点,你的目标是到达坑的底部。有一个难题,你只能走不连续的几步才能到达底部。如果你决定一次迈出一步,你最终会到达深渊的底部,但这需要更长的时间。如果你每次选择走更长的步,你会更快到达,但是,有可能你会越过坑的底部,而不是正好在底部。在梯度下降算法中,你走的步数就是学习率。这决定了算法多快收敛到最小值。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Convex vs Non-convex function

有时,成本函数可以是非凸函数,在这种情况下,您可能会陷入局部最小值,但对于线性回归,它始终是凸函数。

你可能想知道如何使用梯度下降来更新 a_0 和 a_1。为了更新 a_0 和 a_1,我们从成本函数中取梯度。为了找到这些梯度,我们对 a_0 和 a_1 求偏导数。现在,为了理解下面的偏导数是如何得到的,你需要一些微积分,但是如果你不需要,也没关系。你可以照原样接受。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

偏导数是梯度,它们用于更新 A0 和 a1 的值。Alpha 是学习率,它是一个必须指定的超参数。较小的学习率可以让你更接近最小值,但需要更多的时间来达到最小值,较大的学习率收敛更快,但有可能超过最小值。

密码

让我们来看看代码。我们有两个选择,我们可以使用 scikit learn 库导入线性回归模型并直接使用它,或者我们可以根据上面的等式编写自己的回归模型。与其两个选一个,不如两个都做:)

在线上有许多数据集可用于线性回归。我用的是这个链接里的那个。让我们将训练和测试数据可视化。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Training(left) and Testing(right) data

让我们从两种方法中最简单的开始,即使用 scikit learn 库来构建我们的线性回归模型。

我们使用熊猫图书馆来读取训练和测试文件。我们检索自变量(x)和因变量(y ),由于我们只有一个特征(x ),我们对它们进行整形,以便可以将它们输入到线性回归模型中。

我们使用 scikit learn 导入线性回归模型。我们根据训练数据拟合模型,并预测测试数据的值。我们使用 R2 分数来衡量我们模型的准确性。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

R2 score on testing data

现在,让我们从上面的等式建立我们自己的线性回归模型。我们将只使用 numpy 库进行计算,使用 R2 分数进行度量。

我们为 a_0 和 a_1 初始化值 0.0。对于 1000 个时期,我们计算成本,并使用成本计算梯度,并使用梯度更新 a_0 和 a_1 的值。经过 1000 个历元后,我们会得到 A0 和 a1 的最佳值,因此,我们可以用公式表示最佳拟合直线。

测试集包含 300 个样本,因此我们必须将 A0 和 a1 从 700 x1300 x1 整形。现在,我们可以使用该方程来预测测试集中的值,并获得 R2 分数。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

R2 score on testing data

我们可以观察到与前面方法相同的 R2 分数。我们还绘制了回归线以及测试数据点,以更好地直观了解我们的算法有多好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Regression line — Test data

结论

线性回归是每个机器学习爱好者都必须知道的算法,也是想学习机器学习的人的正确起点。这确实是一个简单但有用的算法。我希望这篇文章对你有帮助。

马尔可夫链简介

原文:https://towardsdatascience.com/introduction-to-markov-chains-50da3645a50d?source=collection_archive---------0-----------------------

什么是马尔可夫链,什么时候使用,它们是如何工作的

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

(Generated from http://setosa.io/ev/markov-chains/)

马尔可夫链是统计建模随机过程的一种相当常见且相对简单的方法。它们已经被用于许多不同的领域,从文本生成到金融建模。一个流行的例子是 r/SubredditSimulator ,它使用马尔可夫链来自动创建整个 subreddit 的内容。总的来说,马尔可夫链在概念上非常直观,并且非常容易理解,因为它们可以在不使用任何高级统计或数学概念的情况下实现。它们是开始学习概率建模和数据科学技术的好方法。

方案

首先,我将用一个非常常见的例子来描述它们:

Imagine that there were two possible states for weather: sunny or cloudy. **You can always directly observe the current weather state, and it is guaranteed to always be one of the two aforementioned states.**Now, you decide you want to be able to predict what the weather will be like tomorrow. Intuitively, you assume that there is an inherent ***transition*** in this process, in that the current weather has some bearing on what the next day’s weather will be. So, being the dedicated person that you are, you collect weather data over several years, and calculate that the chance of a sunny day occurring after a cloudy day is 0.25\. You also note that, by extension, the chance of a cloudy day occurring after a cloudy day must be 0.75, since there are only two possible states.You can now use this ***distribution*** to predict weather for days to come, based on what the current weather state is at the time.

这个例子说明了马尔可夫链的许多关键概念。马尔可夫链本质上由一组满足 马尔可夫性质 的转移所组成,这些转移由某种概率分布决定。

观察在这个例子中,概率分布是如何仅通过观察从当天到第二天的转变而获得的。这说明了马尔科夫属性,马尔科夫过程的独特特征,使得它们 无记忆 。这通常使他们无法成功地产生序列,其中一些潜在的趋势预计会发生。例如,虽然马尔可夫链可能能够基于词频模仿作者的写作风格,但是它将不能产生包含深层含义或主题意义的文本,因为这些是在长得多的文本序列上开发的。由于它们不能考虑先前状态的完整链,因此它们缺乏产生依赖于上下文的内容的能力。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

A visualization of the weather example

模型

形式上,马尔可夫链是一个概率自动机。状态转移的概率分布通常表示为马尔可夫链的 转移矩阵 *。*如果马尔可夫链有 N 个可能状态,那么矩阵将是一个N×N矩阵,这样条目 (I,J) 就是从状态 I 转移到状态 J 的概率。此外,转移矩阵必须是一个随机矩阵,该矩阵的每一行的元素相加必须正好为 1。这完全有意义,因为每一行代表它自己的概率分布。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

General view of a sample Markov chain, with states as circles, and edges as transitions

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Sample transition matrix with 3 possible states

此外,马尔可夫链还有一个 初始状态向量 ,表示为一个N×1矩阵(一个向量),它描述了在 N 个可能状态中的每一个状态开始的概率分布。向量的条目 I 描述了链从状态 I 开始的概率。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Initial State Vector with 4 possible states

这两个实体通常是表示马尔可夫链所需的全部。

我们现在知道了如何获得从一个状态转换到另一个状态的机会,但是如何找到在多个步骤中发生转换的机会呢?为了形式化这一点,我们现在想要确定在 M 个步骤上从状态 I 移动到状态 J 的概率。事实证明,这其实很容易发现。给定一个转移矩阵 P ,这可以通过计算通过将 P 提升到 M 的幂而获得的矩阵的条目 (I,J) 的值来确定。对于小数值的 M(T25),这可以通过手动重复乘法很容易地完成。但是对于 M 的大值,如果你熟悉简单的线性代数,一个更高效的矩阵的幂次提升方法是先对角化矩阵。

结论

既然您已经了解了马尔可夫链的基础知识,现在您应该能够轻松地用自己选择的语言实现它们。如果编码不是你的专长,还有许多更高级的马尔可夫链和马尔可夫过程的特性可以研究。在我看来,沿着理论路线的自然进展将是走向隐马尔可夫过程或 MCMC。简单的马尔可夫链是其他更复杂的建模技术的构建模块,因此有了这些知识,您现在可以转移到诸如信念建模和抽样等主题中的各种技术。

ML⁵.简介射流研究…

原文:https://towardsdatascience.com/introduction-to-ml5-js-3fe51d6a4661?source=collection_archive---------6-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Photo by Christopher Robin Ebbinghaus on Unsplash

初学者友好的网络机器学习。

本文是关于 ML⁵.的第一部分 js 学习系列,完整系列将在媒体上以文本可读形式提供,并在 YouTube 上的我的频道上以视频解释形式提供。正在更新完整的视图播放列表。

ML⁵.js 该库由纽约大学开发,于 2018 年 7 月公开发布。该库在浏览器中提供对机器学习算法、任务和模型的访问,构建在[TensorFlow.js](https://js.tensorflow.org/)之上,没有其他外部依赖性。所以,可以和 Keras 比。ML⁵.js

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

ML⁵.js 我们可以把这个比作 Keras 。Keras 背后的动机是让 python 中的 ML/DL 简单到初学者也能使用。ML⁵.的情况也类似射流研究……

这可以通过对 Tensorflow.js 库进行包装并在后端使用所有功能来实现。所以直观来说,对于 TensorFlow.js 来说是一个很好用的 API。

ML⁵.入门 js

我们可以用ml⁵.js 通过引用我们项目中它的最新版本,通过在 HTML 文件中使用如下脚本标签:

 <html>
    <head>
      <title>Getting Started</title>
      **<script src="https://unpkg.com/ml5@0.1.1/dist/ml5.min.js"></script>**
    </head> <body>
      <script> // Your code will go here </script>
    </body>
  </html>

仅此而已!💥

你已经准备好了…

请考虑在 ML5.js 上观看这个视频的详细解释:-

Source

承诺和回访

ML⁵.js 支持错误优先回调和所有方法中的承诺。

使用回调

ML⁵.js 使用一种被称为错误优先回调的模式:

**例如——**如果你使用的是imageClassifier()方法,你将需要以如下方式构建它:

错误优先回调是许多 JavaScript 库共有的约定,在 ML⁵.中实现 js 。JavaScript 语言本身并不强制这种模式。在实施之前,我们最需要了解的是 ML⁵.js 方法和函数是异步的(因为机器学习模型可能会花费大量的时间来处理输入和生成输出!).

利用承诺

ML⁵.js也支持承诺。如果没有向任何异步函数提供回调,则返回一个承诺。

有了承诺,图像分类示例可以按以下方式使用:

使用 ML⁵.进行图像分类 js

图像分类器()

ML⁵.js 可以用神经网络来识别图像的内容。ml5.imageClassifier()是创建对象的默认方法,使用预先训练的模型(如 MobileNet 等)对图像进行分类。

ML⁵.js 库从云中访问这些模型。

让我们构建一个具体的例子:-

我们将使用 p5 库和 ML⁵.js. p5 是一个强大而简单的 Javascript 库。你可以在这里找到更多细节你可以随时用 ML⁵.js. 使用普通的 JavaScript 或者你选择的其他框架作品

在开始 Javascript 部分之前,我们需要使用 NodeJS 托管一个本地服务器。

下面是代码:-

本地服务器成功启动并运行后,我们可以开始编写 HTML 和 JS 文件。

Index.html

Index.html

main.js

好了…我们已经使用 ML⁵.js. 成功实现了一个图像分类器

可以去http://localhost:8081/index . html查看结果。截图如下:-

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Screenshot of the App.

下面是上面代码的 Github Repo

** [## ADLsourceCode/ml5

GitHub 是人们构建软件的地方。超过 2800 万人使用 GitHub 来发现、分享和贡献超过…

github.com](https://github.com/ADLsourceCode/ml5)

注意:这个教程不是集中在用户界面上,而是集中在获得 ML⁵.的基础上 js 清零**。UI 可以改进,UI 没有限制。**

使用 ML⁵.js 对于图像分类来说很简单,在我的下一篇文章中,我们将关注网络摄像头视频分类&其他使用 ML⁵.js. 的 NLP 工作

请考虑观看此视频,了解使用 ML⁵.进行图像分类的详细说明 js :-

Source

我对 ML⁵.的看法射流研究…

这对熟悉 JavaScript 和 HTML 并试图在 ML/DL 世界中找到出路的程序员来说是极好的!

对于没有 ML/DL 背景,但希望了解这个领域的人来说,这让事情变得简单多了。它使得机器学习对于艺术家、创意编码者和学生等广大受众来说变得触手可及。

这方面的用例很多,我个人认为这是我们目前需要的。

如果你觉得我的文章有用,你也会觉得我在 AI 上的 You Tube 频道有用而且有趣。请考虑订阅我的频道

享受 AI。😉**

如果你喜欢我的文章,请点击👏下面的跟我上中的和&:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

如果你有任何问题,请在下面的评论里或者 推特 告诉我。订阅我的 YouTube 频道获取更多科技视频: ADL

从头开始介绍模型树

原文:https://towardsdatascience.com/introduction-to-model-trees-6e396259379a?source=collection_archive---------4-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

决策树是机器学习中一种强大的监督学习工具,用于递归地(通过特征分割)将数据分割成单独的“孤岛”,以减少您对训练集的拟合的整体加权损失。决策树分类中常用的是基尼指数损失的模态分类器,以及决策树回归的 L2 损失均值回归。然而应该另外观察的是,在树分裂过程中,决策树原则上可以采用任何 模型,即 线性回归、逻辑回归、神经网络。本文的目的是向您介绍这种更一般化的方法,名为模型树,它将允许您从您选择的任何模型中构建决策树(而不是依赖于标准的 CART 方法)!**

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 1) A schematic of using a linear regression model tree to fit a 1D training set to find segments of the training set that are well fit by a straight line.

在深入探讨为什么模型树有用和重要之前,我们在我的 Github 上提供了一个从头开始的模型树 Python 代码实现:

https://github . com/ankonzoid/learning x/tree/master/advanced _ ML/model _ tree

关于机器学习、深度学习和强化学习的更多博客、教程和项目,请查看我的 和我的 Github

模型树的目的是什么?

假设你有一些复杂的训练数据,你天真地想到了一个简单的模型来拟合这个训练集(比如线性回归或者逻辑回归)。尤其是如果您猜测的简单模型的复杂性如此之低,那么您的模型本身很有可能会不足以满足您的训练数据。然而,希望并没有在这一点上失去!模型树的目的是在你的简单模型之外建立一个决策树层次结构,试图适应你的训练集(通过特征切片创建)的几个较小部分,这样整个模型树确实很好地适应完整的训练集。

为了明确演示在常规决策树上构建模型树的有用性,考虑 4 阶一维多项式以及训练低深度线性回归模型树回归器(图 2.a)和默认 scikit-learn 默认决策树回归器(图 2.b)之间的差异。您将会注意到,在这个例子中,模型树轻松胜过 scikit-learn 决策树回归器。

在下面的图 2.a 中,我们绘制了线性回归模型树与数据的拟合度,并增加了树的深度,以找到深度为 5 的拟合度良好的数据。正如你所看到的,即使拟合在极低的树深度(即 0,1,2)下并不出色,但拟合具有直观的意义,因为它们都贪婪地试图通过覆盖多项式的大部分来减少损失,从远处看就像直线。当我们到达深度 4 和 5 时,模型树将已经很好地捕捉到数据的 x 相关性,正如从 4 阶多项式所预期的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 2.a) Linear regression model tree fit on a 4th-order polynomial

另一方面,在下面的图 2.b 中,我们绘制了 scikit-learn 的默认决策树回归器的拟合度,发现即使在较高的树深度,拟合度仍然很差,这主要是因为它不能有效地捕捉数据的 x 相关性,因为 scikit-learn 的决策树使用均值回归(不考虑 x 变量,只关心 y 值)!因此,解决方案(不使用集合方法)将是迫使树更深以更接近近似值。希望这是一个强有力的视觉提醒,无论何时你有一点点奢侈去理解你的训练数据的本质,模型树都可以极大地改善你的结果。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Fig 2.b) Decision tree regressor (scikit-learn default implementation) fit on a 4th-order polynomial

最后一点,请记住,模型树在概念上的构建方式与常规决策树相同,这意味着模型树也可能遭受与决策树相同的缺陷,这通常涉及容易过度拟合的问题,尤其是当您使用复杂的模型时。

朴素贝叶斯分类简介

原文:https://towardsdatascience.com/introduction-to-naive-bayes-classification-4cffabb1ae54?source=collection_archive---------1-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

朴素贝叶斯是一个简单、有效且常用的机器学习分类器。它是一种概率分类器,在贝叶斯设置中使用最大后验决策规则进行分类。也可以用一个非常简单的贝叶斯网络来表示。朴素贝叶斯分类器在文本分类中特别受欢迎,是垃圾邮件检测等问题的传统解决方案。

模型

任何概率分类器的目标是,利用特征 x_0 到 x_n 和类 c_0 到 c_k,确定特征在每个类中出现的概率,并返回最可能的类。因此,对于每一类,我们希望能够计算 P(c_i | x_0,…,x_n)。

为了做到这一点,我们使用贝叶斯规则。回想一下贝叶斯规则如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

在分类的上下文中,您可以用一个类 c_i 替换 A,用我们的一组特征 x_0 到 x_n 替换 B。由于 P(B)用作归一化,并且我们通常无法计算 P(x_0,…,x_n),我们可以简单地忽略该术语,而是只陈述 P(c_i | x_0,…,x_n) ∝ P(x_0,…,x_n | c_i) * P(c_i),其中∝表示“与成比例”。P(c_i)计算简单;P(x_0,…,x_n | c_i)更难计算。为了简化其计算,我们假设 x_0 到 x_n 是条件独立给定 c_i,这就允许我们说 P(x_0,…,x _ n | c _ I)= P(x _ 0 | c _ I)* P(x _ 1 | c _ I) P(x _ n | c _ I)。这个假设很可能是不正确的——因此命名为朴素贝叶斯分类器,但是该分类器在大多数情况下仍然表现良好。因此,我们对类概率的最终表示如下:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

计算各个 P(x_j | c_i)项将取决于您的要素所遵循的分布。在文本分类的背景下,其中特征可以是字数,特征可以遵循多项式分布。在其他情况下,特征是连续的,它们可能遵循高斯分布

请注意,与其他常见的分类方法相比,朴素贝叶斯中的显式训练非常少。在预测之前必须做的唯一工作是找到特征的个体概率分布的参数,这通常可以快速且确定地完成。这意味着朴素贝叶斯分类器甚至可以在高维数据点和/或大量数据点的情况下表现良好。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

分类

既然我们有了一种方法来估计给定数据点落入某个类别的概率,我们需要能够使用它来产生分类。朴素贝叶斯以非常简单的方式处理这个问题;根据数据点的特征,简单地选择具有最大概率的 c_i。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这被称为最大后验概率决策规则。这是因为,回头参考我们的贝叶斯规则公式,我们只使用 P(B|A)和 P(A)项,它们分别是似然项和先验项。如果我们只使用 P(B|A)的可能性,我们将使用一个最大可能性决策规则。

文本自然语言处理导论

原文:https://towardsdatascience.com/introduction-to-natural-language-processing-for-text-df845750fb63?source=collection_archive---------0-----------------------

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Icons source: https://iconfinder.com

看完这篇博文,你会知道一些从一些文本提取特征的基本技术,所以你可以把这些特征作为机器学习模型输入**。**

什么是 NLP(自然语言处理)?

NLP 是计算机科学和人工智能的一个子领域,涉及计算机和人类(自然)语言之间的交互。用于将机器学习算法应用于文本语音

例如,我们可以使用 NLP 创建类似于语音识别文档摘要机器翻译垃圾邮件检测命名实体识别问题回答、自动完成、预测打字等系统。

如今,我们大多数人的智能手机都有语音识别功能。这些智能手机使用 NLP 来理解所说的内容。此外,许多人使用操作系统内置语音识别的笔记本电脑。

一些例子

Cortana

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://blogs.technet.microsoft.com/microsoft_presse/auf-diesen-4-saeulen-basiert-cortanas-persoenlichkeit/

微软 OS 有一个名为 Cortana 的虚拟助手,可以识别一个自然语音。你可以用它来设置提醒、打开应用程序、发送电子邮件、玩游戏、跟踪航班和包裹、查看天气等等。

你可以从这里阅读更多关于 Cortana 命令的内容。

Siri

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.analyticsindiamag.com/behind-hello-siri-how-apples-ai-powered-personal-assistant-uses-dnn/

Siri 是苹果公司 iOS、watchOS、macOS、HomePod 和 tvOS 操作系统的虚拟助手。同样,你可以用语音 命令做很多事情:开始通话、给某人发短信、发送电子邮件、设置定时器、拍照、打开应用程序、设置闹钟、使用导航等等。

这里的是所有 Siri 命令的完整列表。

Gmail

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://i.gifer.com/Ou1t.gif

谷歌开发的著名电子邮件服务 Gmail 正在使用垃圾邮件检测过滤掉一些垃圾邮件。

Python 的 NLTK 库简介

NLTK ( 自然语言工具包)是一个领先的平台,用于构建 Python 程序来处理人类语言数据。它为众多的 语料库词汇资源提供了易用的接口。此外,它还包含一套文本处理库,用于分类、标记化、词干化、标记、解析和语义推理。最棒的是,NLTK 是一个免费、开源、社区驱动的项目。

我们将使用这个工具包来展示自然语言处理领域的一些基础知识。对于下面的例子,我假设我们已经导入了 NLTK 工具包。我们可以这样做:import nltk

文本的自然语言处理基础

在本文中,我们将讨论以下主题:

  1. 句子标记化
  2. 单词标记化
  3. 文本词汇化和词干化
  4. 停止言语
  5. 正则表达式
  6. 词汇袋
  7. TF-IDF

1.句子标记化

句子标记化(也叫句子切分就是把书面语的一串分割成其成分句子的问题。这里的想法看起来很简单。在英语和其他一些语言中,每当我们看到标点符号时,我们就可以把句子分开。

然而,即使在英语中,由于缩写使用句号字符,这个问题也不是微不足道的。当处理纯文本时,包含句点的缩写表可以帮助我们防止错误分配句子边界。在很多情况下,我们使用库来完成这项工作,所以现在不要太担心细节。

例子:

让我们来看一段关于一个著名的棋盘游戏叫做双陆棋的课文。

双陆棋是已知最古老的棋盘游戏之一。它的历史可以追溯到近 5000 年前中东的考古发现。这是一个两人游戏,每个人有 15 个跳棋,根据两个骰子的滚动在 24 个点之间移动。

要用 NLTK 应用句子标记化,我们可以使用nltk.sent_tokenize函数。

作为输出,我们分别得到 3 个组成句子。

Backgammon is one of the oldest known board games.

Its history can be traced back nearly 5,000 years to archeological discoveries in the Middle East.

It is a two player game where each player has fifteen checkers which move between twenty-four points according to the roll of two dice.

2.单词标记化

分词(也叫分词)就是把书面语的一串分割成它的成分的问题。在英语和许多其他使用某种形式拉丁字母的语言中,空格是单词分隔符的一个很好的近似。

然而,如果我们仅仅通过空间分割来实现想要的结果,我们仍然会有问题。一些英语复合名词有不同的写法,有时它们包含一个空格。在大多数情况下,我们使用一个库来实现想要的结果,所以不要太担心细节。

举例:

让我们使用上一步中的句子,看看如何对它们应用单词标记化。我们可以使用nltk.word_tokenize函数。

输出:

['Backgammon', 'is', 'one', 'of', 'the', 'oldest', 'known', 'board', 'games', '.']

['Its', 'history', 'can', 'be', 'traced', 'back', 'nearly', '5,000', 'years', 'to', 'archeological', 'discoveries', 'in', 'the', 'Middle', 'East', '.']

['It', 'is', 'a', 'two', 'player', 'game', 'where', 'each', 'player', 'has', 'fifteen', 'checkers', 'which', 'move', 'between', 'twenty-four', 'points', 'according', 'to', 'the', 'roll', 'of', 'two', 'dice', '.']

文本词汇化和词干化

出于语法原因,文档可以包含单词的不同形式,例如驱动驱动驱动。还有,有时候我们会用相关的词来表达类似的意思,比如民族国家民族

词干化词汇化的目的都是为了 屈折 形式以及有时将单词的衍生相关形式缩减为****公共基础形式

来源:https://NLP . Stanford . edu/IR-book/html/html edition/stemming-and-lemma tization-1 . html

例句:

  • 是,是,是=>
  • 狗,狗,狗的,狗的=>

应用于文本的这种映射的结果将如下所示:

  • 男孩的狗大小不同

词干化和词汇化是规范化的特例。然而,它们彼此不同。

词干通常指的是一种粗糙的 启发式 过程,它砍掉单词的词尾,希望在大多数时候都能正确实现这一目标,通常还包括去除派生词缀。

词汇化通常是指使用词汇单词的形态分析正确地做事情,通常旨在只去除屈折词尾并返回单词的基本或词典形式,这就是所谓的引理

来源:https://NLP . Stanford . edu/IR-book/html/html edition/stemming-and-lemma tization-1 . html

不同之处在于词干分析器在不了解上下文的情况下操作**,因此无法理解根据词性而具有不同含义的单词之间的差异。但是词干分析器也有一些优点,它们更容易实现,通常 T21 运行得更快。此外,降低的“精度”对于某些应用来说可能无关紧要。**

例子:

  1. “更好”这个词的引理是“好”。这一环节被词干遗漏了,因为它需要查字典。
  2. 单词“play”是单词“playing”的基本形式,因此它在词干和词汇化上都是匹配的。
  3. 单词“meeting”可以是名词的基本形式,也可以是动词的形式(“to meet”),这取决于上下文;例如,“在我们最后一次见面时”或“我们明天还会见面”。与词干提取不同,词汇化试图根据上下文选择正确的词汇。

在我们知道区别之后,让我们看一些使用 NLTK 工具的例子。

输出:

Stemmer: seen
Lemmatizer: see

Stemmer: drove
Lemmatizer: drive

停止言语

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: http://www.nepalinlp.com/detail/stop-words-removal_nepali/

停用词是在文本处理之前或之后从中过滤掉的词。在对文本应用机器学习时,这些词可以添加很多噪音。这就是为什么我们要去掉这些无关词

停用词通常是指中最常见的词如“”、”,但在一种语言中没有没有单一的停用词通用列表**。停用字词的列表可以根据您的应用而改变。**

NLTK 工具有一个预定义的停用词列表,它引用最常用的词。如果是第一次使用,需要使用这个代码下载停用词:nltk.download(“stopwords”)。一旦我们完成了下载,我们就可以从nltk.corpus加载stopwords包,并用它来加载停用词。

输出:

['i', 'me', 'my', 'myself', 'we', 'our', 'ours', 'ourselves', 'you', "you're", "you've", "you'll", "you'd", 'your', 'yours', 'yourself', 'yourselves', 'he', 'him', 'his', 'himself', 'she', "she's", 'her', 'hers', 'herself', 'it', "it's", 'its', 'itself', 'they', 'them', 'their', 'theirs', 'themselves', 'what', 'which', 'who', 'whom', 'this', 'that', "that'll", 'these', 'those', 'am', 'is', 'are', 'was', 'were', 'be', 'been', 'being', 'have', 'has', 'had', 'having', 'do', 'does', 'did', 'doing', 'a', 'an', 'the', 'and', 'but', 'if', 'or', 'because', 'as', 'until', 'while', 'of', 'at', 'by', 'for', 'with', 'about', 'against', 'between', 'into', 'through', 'during', 'before', 'after', 'above', 'below', 'to', 'from', 'up', 'down', 'in', 'out', 'on', 'off', 'over', 'under', 'again', 'further', 'then', 'once', 'here', 'there', 'when', 'where', 'why', 'how', 'all', 'any', 'both', 'each', 'few', 'more', 'most', 'other', 'some', 'such', 'no', 'nor', 'not', 'only', 'own', 'same', 'so', 'than', 'too', 'very', 's', 't', 'can', 'will', 'just', 'don', "don't", 'should', "should've", 'now', 'd', 'll', 'm', 'o', 're', 've', 'y', 'ain', 'aren', "aren't", 'couldn', "couldn't", 'didn', "didn't", 'doesn', "doesn't", 'hadn', "hadn't", 'hasn', "hasn't", 'haven', "haven't", 'isn', "isn't", 'ma', 'mightn', "mightn't", 'mustn', "mustn't", 'needn', "needn't", 'shan', "shan't", 'shouldn', "shouldn't", 'wasn', "wasn't", 'weren', "weren't", 'won', "won't", 'wouldn', "wouldn't"]

让我们看看如何从句子中去掉停用词。

输出:

['Backgammon', 'one', 'oldest', 'known', 'board', 'games', '.']

如果你不熟悉 Python 中的 列表理解。这里有另一种方法可以达到同样的效果。

然而,请记住列表理解更快,因为它们已经过优化,以便 Python 解释器在循环过程中发现可预测的模式。

你可能想知道为什么我们把我们的列表转换成一个 集合 。Set 是一种抽象数据类型,可以存储唯一的值,没有任何特定的顺序。集合中的搜索操作 比列表中的搜索操作快得多****。对于少量的单词,没有太大的区别,但是如果你有大量的单词,强烈建议使用 set 类型。****

如果你想了解更多关于不同数据结构的不同操作之间的时间消耗,你可以看看这个很棒的备忘单

正则表达式

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://digitalfortress.tech/tricks/top-15-commonly-used-regex/

正则表达式regexregexp 是定义搜索模式的字符序列。让我们看看一些基本的。

  • . -匹配除换行符之外的任意字符
  • \w -匹配
  • \d -匹配数字
  • \s -匹配空格
  • \W——配不字
  • \D -匹配而非数字
  • \S -匹配而不是空白
  • [abc] -匹配 a、b 或 c 中的任意一个
  • [**^**abc] - 匹配 a、b 或 c
  • [a**-**g] -在和& g 之间匹配一个字符

正则表达式使用反斜杠字符 ( '\')来表示特殊形式,或者允许使用特殊字符而不调用它们的特殊含义。这个与 Python 在字符串文字中出于相同目的使用相同字符的用法相冲突;例如,要匹配一个文字反斜杠,可能必须将'\\\\'写成模式字符串,因为正则表达式必须是\\,并且每个反斜杠必须在一个常规 Python 字符串文字中表示为\\****

解决方案是将 Python 的原始字符串符号用于正则表达式模式;以 **'r'**为前缀的字符串文字中的反斜杠没有任何特殊的处理方式。所以r"\n"是包含'\''n'的双字符字符串,而"\n"是包含换行符的单字符字符串。通常,模式将使用这种原始字符串符号在 Python 代码中表示。

来源:https://docs.python.org/3/library/re.html?highlight=regex

我们可以使用正则表达式将附加过滤应用到我们的文本中。例如,我们可以删除所有非单词字符。在许多情况下,我们不需要标点符号,用正则表达式很容易删除它们。

在 Python 中,**re**模块提供了类似于 Perl 中的正则表达式匹配操作。我们可以使用**re.sub**函数用替换字符串替换模式的匹配。让我们看一个用空格字符替换所有非单词的例子。

输出:

**'The development of snowboarding was inspired by skateboarding  sledding  surfing and skiing '**

正则表达式是一个强大的工具,我们可以创建更复杂的模式。如果你想了解更多关于 regex 的知识,我可以推荐你试试这两个 web 应用: regex r, regex101

词汇袋

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.iconfinder.com/icons/299088/bag_icon

机器学习算法不能直接处理原始文本,我们需要将文本转换成数字向量。这叫做 特征提取

词袋模型是一种流行的简单的 特征提取技术在我们处理文本时使用。它描述了文档中每个单词的出现。****

要使用该模型,我们需要:

  1. 设计一个已知单词的词汇表(也叫记号)
  2. 选择已知单词存在的度量

任何关于单词的顺序结构的信息都被丢弃。这就是为什么它被称为单词的。该模型试图理解一个已知单词是否出现在文档中,但不知道该单词在文档中的位置。

直觉是相似文档相似内容。同样,从一个内容中,我们可以了解一些关于文档的含义。

例子

我们来看看创建词袋模型有哪些步骤。在这个例子中,我们将用四个句子来看看这个模型是如何工作的。在现实世界的问题中,您将处理大量的数据。

1。加载数据

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.iconfinder.com/icons/315166/note_text_icon

假设这是我们的数据,我们想把它作为一个数组加载。

要做到这一点,我们可以简单地读取文件,并按行分割。

输出:

**["I like this movie, it's funny.", 'I hate this movie.', 'This was awesome! I like it.', 'Nice one. I love it.']**

2。 设计词汇

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.iconfinder.com/icons/2109153/book_contact_dairy_google_service_icon

让我们从四个加载的句子中获取所有独特的单词,忽略大小写、标点和单字符标记。这些单词将成为我们的词汇(已知单词)。

我们可以使用 sklearn 库中的 计数矢量器 类来设计我们的词汇表。我们也将在阅读下一步后看看如何使用它。

3。创建文档向量

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.iconfinder.com/icons/1574/binary_icon

接下来,我们需要对每个文档中的单词进行评分。这里的任务是将每个原始文本转换成一个数字向量。之后,我们可以使用这些向量作为机器学习模型的输入。最简单的评分方法是用 1 代表存在,0 代表不存在来标记单词的存在。

现在,让我们看看如何使用上面提到的 CountVectorizer 类创建一个单词袋模型。

输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

这是我们的句子。现在我们可以看到单词袋模型是如何工作的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

关于单词袋模型的补充说明

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Source: https://www.iconfinder.com/icons/1118207/clipboard_notes_pen_pencil_icon

单词袋模型的复杂性来自于决定如何设计已知单词(记号)的词汇表以及如何对已知单词的存在进行评分。

设计词汇
当词汇
大小增加
时,文档的向量表示也增加。在上面的例子中,文档向量的长度等于已知单词的数量。****

在某些情况下,我们可能有大量的数据,在这种情况下,表示文档的向量的长度可能是数千或数百万个元素。此外,每个文档可能只包含词汇表中的几个已知单词。

因此,矢量表示将有个零。这些有很多零的向量被称为稀疏向量。它们需要更多的内存和计算资源。

当使用单词袋模型来减少所需的内存和计算资源时,我们可以减少已知单词的数量。在创建我们的单词袋模型之前,我们可以使用我们已经在本文中看到的文本清理技术:

  • 忽略大小写的字样
  • 忽略标点符号
  • 从我们的文档中删除停用词****
  • 将单词简化为基本形式(文本词条化和词干化)
  • 修复拼错的单词

另一种更复杂的创建词汇表的方法是使用分组单词。这改变了词汇表的范围,并允许单词袋模型获得关于文档的更多细节。这种方法被称为 n-grams

一个 n-gram 是一个由若干(单词、字母、数字、数位等)组成的序列。).在 文本语料库 的上下文中,n-grams 一般是指一个单词序列。一个一元词是一个词,一个二元词是两个词的序列,一个三元词是三个词的序列,等等。“n-gram”中的“n”是指分组单词的数量。仅对语料库中出现的 n 元文法进行建模,而不是所有可能的 n 元文法。

例句
让我们看看下面这个句子的所有二元模型:
The office building is open today

所有的二元模型是:

  • 办公室
  • 办公楼
  • 建筑是
  • 已打开
  • 今天开门

****二元模型袋比词汇袋方法更强大。

给单词打分 一旦我们创建了已知单词的词汇表,我们就需要给这些单词在我们的数据中的出现次数打分。我们看到了一种非常简单的方法——二元方法(1 代表存在,0 代表不存在)。

一些额外的评分方法是:

  • 伯爵。计算每个单词在文档中出现的次数。
  • 频率。计算文档中所有单词中每个单词出现的频率。

TF-IDF

****评分词频的一个问题是,文档中最频繁出现的词开始有最高的分数。与一些更罕见和特定领域的单词相比,这些频繁出现的单词可能不包含太多的"信息增益"。解决这个问题的一个方法是惩罚在所有文档频繁出现的单词。这种方法被称为 TF-IDF。

TF-IDF,简称词频-逆文档频数是一种统计量**,用于评估一个词在集合或语料库中对一个文档的重要性。**

TF-IDF 得分值与单词在文档中出现的次数成比例地增加,但是它被语料库中包含该单词的文档的数量所抵消。

让我们看看用于计算文档 y 中给定术语 x 的 TF-IDF 得分的公式。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

TF-IDF Formula. Source: http://filotechnologia.blogspot.com/2014/01/a-simple-java-class-for-tfidf-scoring.html

现在,让我们把这个公式拆分一下,看看公式的不同部分是如何工作的。

  • 词频(TF) :该词在当前文档中出现频率的得分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Term Frequency Formula

  • 逆词频(ITF) :对单词在文档中的稀有程度进行评分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

Inverse Document Frequency Formula

  • 最后,我们可以使用前面的公式来计算给定术语的 TF-IDF 得分,如下所示:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

TF-IDF Formula

示例 在 Python 中,我们可以使用 sklearn 库中的tfidf 矢量器类来计算给定文档的 TF-IDF 分数。让我们使用和单词袋例子中相同的句子。

输出:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

同样,我将在这里添加句子,以便于比较和更好地理解这种方法是如何工作的。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

摘要

在这篇博文中,您将学习文本的 NLP 基础知识。更具体地说,您已经学习了以下概念以及其他详细信息:

  • NLP 用于将机器学习算法应用于文本语音
  • NLTK ( 自然语言工具包)是一个领先的平台**,用于构建 Python 程序来处理**人类语言数据****
  • ****句子标记化就是把书面语的一串分割成它的成分句子的问题
  • ****分词就是将书面语中的一串拆分成其成分单词的问题
  • 词干化词汇化的目的都是为了 屈折 形式以及有时将**单词的衍生相关形式缩减为**公共基础形式**。**
  • 停用词是在文本处理之前或之后过滤掉的词。他们通常指的是语言中最常见的单词
  • ****正则表达式是定义搜索模式的一系列字符。
  • 词袋模型是一种流行的简单的 特征提取技术在我们处理文本时使用。它描述了文档中每个单词的出现。
  • TF-IDF 是一个统计量,用于评估一个单词对集合中的一个文档或者语料库的重要性。

厉害!现在我们知道了如何从文本中提取特征的基本知识。然后,我们可以使用这些特征作为机器学习算法的输入。

要不要看所有用在的概念再来一个大例子**?

  • 给您!如果你在手机上阅读,请向下滚动到最后,点击“桌面版”链接。**

资源

互动版

这里的是在 Deepnote (云托管 Jupyter 笔记本平台)上传的这篇文章的交互版本**。请随意查看并使用示例。**

我的其他博客文章

你也可以看看我以前的博文。

时事通讯

如果你想在我发表新的博客文章时得到通知,你可以订阅我的最新时事通讯

商务化人际关系网

这是我在 LinkedIn 上的简介,如果你想和我联系的话。我将很高兴与你联系在一起。

最后的话

谢谢你的阅读。我希望你喜欢这篇文章。如果你喜欢,请按住拍手键,分享给你的朋友。我很高兴听到你的反馈。如果你有什么问题,尽管问。😉

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值