TowardsDataScience-博客中文翻译-2016-2018-二百零四-

41 阅读1小时+

TowardsDataScience 博客中文翻译 2016~2018(二百零四)

原文:TowardsDataScience Blog

协议:CC BY-NC-SA 4.0

使用 Scikit-Learn 进行多标签文本分类

原文:towardsdatascience.com/multi-label…

Photo credit: Pexels

多类分类指两个以上类的分类任务;每个标签都是互斥的。分类假设每个样本被分配给一个且仅一个标签。

另一方面,多标签分类给每个样本分配一组目标标签。这可以被认为是预测数据点的属性,这些属性并不相互排斥,例如 Tim Horton 经常被归类为面包店和咖啡店。多标签文本分类在现实世界中有很多应用,比如对 Yelp 上的企业进行分类,或者将电影分为一个或多个类型。

问题定式化

任何在网上成为辱骂或骚扰目标的人都会知道,当你注销或关掉手机时,这种情况不会消失。谷歌的研究人员正致力于研究在线有毒评论的工具。在这篇文章中,我们将建立一个多标签模型,能够检测不同类型的毒性,如严重中毒,威胁,淫秽,侮辱,等等。我们将使用监督分类器和文本表示。毒性评论可能是关于毒性、严重毒性、淫秽、威胁、侮辱或身份仇恨中的任何一种,也可能不是以上任何一种。数据集可以在卡格尔找到。

(来自数据源的免责声明:数据集包含可能被视为亵渎、粗俗或冒犯的文本。)

探索

%matplotlib inline
import re
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer
from sklearn.naive_bayes import MultinomialNB
from sklearn.metrics import accuracy_score
from sklearn.multiclass import OneVsRestClassifier
from nltk.corpus import stopwords
stop_words = set(stopwords.words('english'))
from sklearn.svm import LinearSVC
from sklearn.linear_model import LogisticRegression
from sklearn.pipeline import Pipeline
import seaborn as snsdf = pd.read_csv("train 2.csv", encoding = "ISO-8859-1")
df.head()

每个类别中的评论数量

df_toxic = df.drop(['id', 'comment_text'], axis=1)
counts = []
categories = list(df_toxic.columns.values)
for i in categories:
    counts.append((i, df_toxic[i].sum()))
df_stats = pd.DataFrame(counts, columns=['category', 'number_of_comments'])
df_stats

Figure 1

df_stats.plot(x='category', y='number_of_comments', kind='bar', legend=False, grid=True, figsize=(8, 5))
plt.title("Number of comments per category")
plt.ylabel('# of Occurrences', fontsize=12)
plt.xlabel('category', fontsize=12)

Figure 2

多标签

有多少评论有多重标签?

rowsums = df.iloc[:,2:].sum(axis=1)
x=rowsums.value_counts()#plot
plt.figure(figsize=(8,5))
ax = sns.barplot(x.index, x.values)
plt.title("Multiple categories per comment")
plt.ylabel('# of Occurrences', fontsize=12)
plt.xlabel('# of categories', fontsize=12)

Figure 3

绝大多数评论文字都没有标注。

print('Percentage of comments that are not labelled:')
print(len(df[(df['toxic']==0) & (df['severe_toxic']==0) & (df['obscene']==0) & (df['threat']== 0) & (df['insult']==0) & (df['identity_hate']==0)]) / len(df))

未标注评论的百分比: 0.8983211235124177

评论文本字数分布

lens = df.comment_text.str.len()
lens.hist(bins = np.arange(0,5000,50))

Figure 4

大多数评论文本长度在 500 个字符以内,有些异常值长达 5000 个字符。

注释文本列中没有缺失的注释。

print('Number of missing comments in comment text:')
df['comment_text'].isnull().sum()

注释文本中缺失的注释数:

0

先偷看一下第一条评论,文字需要清理。

df['comment_text'][0]

" 解释\ r 为什么在我的用户名 Hardcore Metallica Fan 下所做的编辑被恢复?他们不是故意破坏,只是我在纽约娃娃 FAC 投票后关闭了一些煤气。请不要把模板从对话页面上删除,因为我现在退休了。89.205.38.27

数据预处理

创建一个函数来清理文本

def clean_text(text):
    text = text.lower()
    text = re.sub(r"what's", "what is ", text)
    text = re.sub(r"\'s", " ", text)
    text = re.sub(r"\'ve", " have ", text)
    text = re.sub(r"can't", "can not ", text)
    text = re.sub(r"n't", " not ", text)
    text = re.sub(r"i'm", "i am ", text)
    text = re.sub(r"\'re", " are ", text)
    text = re.sub(r"\'d", " would ", text)
    text = re.sub(r"\'ll", " will ", text)
    text = re.sub(r"\'scuse", " excuse ", text)
    text = re.sub('\W', ' ', text)
    text = re.sub('\s+', ' ', text)
    text = text.strip(' ')
    return text

清理 comment_text 列:

df['comment_text'] = df['comment_text'].map(lambda com : clean_text(com))df['comment_text'][0]

解释为什么我的用户名 hardcore metallica fan 下所做的编辑被恢复,他们不是故意破坏,只是在我在纽约娃娃 fac 投票后关闭了一些气体,请不要从对话页面删除模板,因为我现在退休了 89 205 38 27

好多了!

将数据拆分为定型集和测试集:

categories = ['toxic', 'severe_toxic', 'obscene', 'threat', 'insult', 'identity_hate']train, test = train_test_split(df, random_state=42, test_size=0.33, shuffle=True)X_train = train.comment_text
X_test = test.comment_text
print(X_train.shape)
print(X_test.shape)

(106912,) (52659,)

分类器训练

管道

Scikit-learn 提供了一个管道实用程序来帮助自动化机器学习工作流。管道在机器学习系统中非常常见,因为有大量数据要操作,并且有许多数据转换要应用。因此,我们将利用流水线来训练每个分类器。

OneVsRest 多标签策略

多标签算法接受多个标签上的二进制掩码。每个预测的结果将是一个由 0 和 1 组成的数组,用于标记哪些类标签适用于每个行输入样本。

朴素贝叶斯

OneVsRest 策略可用于多标签学习,例如,使用分类器来预测多个标签。朴素贝叶斯支持多类,但我们处于多标签场景中,因此,我们将朴素贝叶斯包装在 OneVsRestClassifier 中。

# Define a pipeline combining a text feature extractor with multi lable classifier
NB_pipeline = Pipeline([
                ('tfidf', TfidfVectorizer(stop_words=stop_words)),
                ('clf', OneVsRestClassifier(MultinomialNB(
                    fit_prior=True, class_prior=None))),
            ])for category in categories:
    print('... Processing {}'.format(category))
    # train the model using X_dtm & y
    NB_pipeline.fit(X_train, train[category])
    # compute the testing accuracy
    prediction = NB_pipeline.predict(X_test)
    print('Test accuracy is {}'.format(accuracy_score(test[category], prediction)))

…处理有毒 测试精度为 0.9191401279933155 …处理严重 _ 有毒 测试精度为 0.9900112041626312 …处理淫秽 测试精度为 0.95148027877747584 …处理威胁 测试精度为 0.9971135033

线性 SVC

SVC_pipeline = Pipeline([
                ('tfidf', TfidfVectorizer(stop_words=stop_words)),
                ('clf', OneVsRestClassifier(LinearSVC(), n_jobs=1)),
            ])for category in categories:
    print('... Processing {}'.format(category))
    # train the model using X_dtm & y
    SVC_pipeline.fit(X_train, train[category])
    # compute the testing accuracy
    prediction = SVC_pipeline.predict(X_test)
    print('Test accuracy is {}'.format(accuracy_score(test[category], prediction)))

…处理有毒 测试精度为 0.9599498661197516 …处理严重 _ 有毒 测试精度为 0.9906948479842003 …处理淫秽 测试精度为 0.9789019920621356 …处理威胁 测试精度为 0.997417334

逻辑回归

LogReg_pipeline = Pipeline([
                ('tfidf', TfidfVectorizer(stop_words=stop_words)),
                ('clf', OneVsRestClassifier(LogisticRegression(solver='sag'), n_jobs=1)),
            ])for category in categories:
    print('... Processing {}'.format(category))
    # train the model using X_dtm & y
    LogReg_pipeline.fit(X_train, train[category])
    # compute the testing accuracy
    prediction = LogReg_pipeline.predict(X_test)
    print('Test accuracy is {}'.format(accuracy_score(test[category], prediction)))

…处理有毒的 测试精度为 0.9548415275641391 …处理严重 _ 有毒的 测试精度为 0.9910556600011394 …处理淫秽的 测试精度为 0.9761104464573956 …处理威胁的 测试精度为 0.999779395

三个分类器产生了相似的结果。我们已经为有毒评论多标签文本分类问题创建了一个强大的基线。

这篇文章的完整代码可以在 Github 上找到。我期待听到任何反馈或意见。

具有 Sigmoid 函数的多层神经网络——新手的深度学习(2)

原文:towardsdatascience.com/multi-layer…

第 1 章:介绍深度学习和神经网络

第二章:具有 Sigmoid 函数的多层神经网络

关注我的 推特 了解更多关于深度学习创业公司的生活。

大家好。欢迎回到我的第二篇系列文章菜鸟深度学习(DLFR) ,作者是你忠实的菜鸟;)如果你觉得难以理解的话,请随意参考我在这里的第一篇文章。或者在本页用备注高亮显示或者在下方留下评论!我们也非常感谢您的反馈。

这次我们将更深入地研究神经网络,这篇文章将比上一次更具技术性。但是不用担心,我会让你在没有 CS/数学背景的情况下,尽可能简单直观地学习基础知识。你很快就能吹嘘你的理解了;)

来自 DLFR 1 的评论

上次,我们介绍了深度学习领域,并检查了一个简单的神经网络——感知器……或恐龙……好吧,说真的,单层感知器。我们还研究了感知器网络如何处理我们输入的输入数据并返回输出。

关键概念:输入数据,权重,求和加偏,激活函数(具体是阶跃函数),然后输出。厌倦了吗?别担心:)我保证会有……更多的术语出现!但是你很快就会习惯的。我保证。

Graph 1: Procedures of a Single-layer Perceptron Network

回到 20 世纪 50 年代和 60 年代,人们没有单层感知器的有效学习算法来学习和识别非线性模式(还记得 XOR 门问题吗?).公众对感知器失去了兴趣。毕竟,现实世界中的大多数问题都是非线性的,作为个体人类,你和我都非常擅长线性或二元问题的决策,如 我是否应该研究深度学习 而不需要感知机。好吧,“好”在这里是一个棘手的词,因为我们的大脑真的不是那么理性。但我会把这个问题留给行为经济学家和心理学家。

突破:多层感知器

快进近 20 年,到 1986 年,Geoffrey Hinton、David Rumelhart 和 Ronald Williams 发表了一篇论文“通过反向传播错误学习表征”,其中介绍了:

  1. 反向传播的一个过程,反复调整权重以使实际输出和期望输出之间的差异最小化
  2. 隐藏层,是堆叠在输入和输出 之间的 神经元节点,允许神经网络学习更复杂的特性(如异或逻辑)

如果你对 DL 完全陌生,你应该还记得杰弗里·辛顿(Geoffrey Hinton),他在 DL 的发展过程中起着举足轻重的作用。这是一些重大新闻:我们 20 年来一直认为神经网络没有解决现实世界问题的前景。现在我们看到岸上灯塔发出的光了!让我们来看看这两个新的介绍。

嗯,第一个,反向传播,上一篇帖子提到过。还记得我们反复强调设计神经网络的重要性,以便网络可以从 期望输出 (事实是什么)和 实际输出 (网络返回什么)之间的差异中学习,然后向权重发回信号并要求权重进行自我调整吗?这将使网络的输出在下次运行时更接近于期望的输出。

第二个呢,隐藏层?什么是隐藏层?一个隐藏层就把单层感知器变成了多层感知器!计划是这样的,由于技术原因, 我将在这篇文章中重点讨论隐藏层,然后在下一篇文章 中讨论反向传播。

这里只是一个随机的有趣事实:我怀疑 Geoffrey Hinton 保持着谷歌:D 最年长实习生的记录。不管怎样,如果你已经熟悉机器学习,我相信他在 Coursera 上的课程会很适合你。

Geoffrey Hinton, one of the most important figures in Deep Learning. Source: thestar.com

具有隐藏层的神经网络

神经网络的隐藏层实际上就是在输入和输出层之间增加更多的神经元。

Graph 2: Left: Single-Layer Perceptron; Right: Perceptron with Hidden Layer

输入层中的数据用下标 1,2,3,…,m 标记为 x 。隐藏层中的神经元用下标 1,2,3,…,n 标记为 h 。注意隐藏层n 而不是 m ,因为隐藏层神经元的数量可能与输入数据中的数量不同。并且如下图所示,隐藏层神经元也标有上标 1 。这是为了当你有几个隐藏层时,你可以识别它是哪个隐藏层:第一个隐藏层有上标 1,第二个隐藏层有上标 2,以此类推,像在 图 3 中。输出用一个 帽子 标注为 y

Graph 3: We label input layer as x with subscripts 1, 2, …, m; hidden layer as h with subscripts 1, 2, …, n; output layer with a hat

为了使生活更容易,我们将使用一些术语来使事情变得清晰一些。我知道,术语可能很烦人但是你会习惯的:)首先,如果我们有 m 输入数据( x1,x2,…,xm ),我们称这个 m 特性 。特征只是我们认为对特定结果有影响的一个变量。就像我们关于 结果的例子如果你决定学不学 DL, 我们有 3 个特点:1。学了 DL,2 以后会赚更多的钱吗?数学/编程难吗,3。你需要一个 GPU 来开始吗?

其次,当我们将 m 个特征中的每一个乘以一个权重( w1,w2,…,wm )并将它们加在一起时,这就是一个点积:

Definition of a Dot Product

所以现在我们来看看几点:

  1. m 特性 在输入X 时,需要用m 权重来执行点积**
  2. n 隐层中的隐神经元,你需要 n 套权值( W1,W2,… Wn )来进行点积
  3. 有了 1 个隐藏层,你执行 n 点积得到隐藏输出h:(h1,h2,…,hn )
  4. **然后就像单层感知器一样,我们用隐藏输出 h: ( h1,h2,…,hn )作为具有 **n 个特征的输入数据,用 1 组权重( w1,w2,…,wn )执行点积,得到你的最终输出

输入值如何前向传播到隐含层,然后从隐含层到输出的过程与图 1** 相同。下面我提供了如何做到这一点的描述,在图 4 中使用了下面的神经网络。****

Graph 4: Example

********

Graph 5: Procedure to Hidden Layer Outputs

现在隐藏层的输出被计算出来了,我们用它们作为输入来计算最终的输出。

Graph 6: Procedure to Final Output

耶!现在你完全理解多层感知器是如何工作的了:)它就像一个单层感知器,除了在这个过程中你有更多的权重。当你在具有更多更多特征的大型数据集上训练神经网络时(比如自然语言处理中的 word2vec),这个过程会耗尽你计算机中的大量内存。这就是为什么深度学习直到过去几年才起飞的一个原因,当时我们开始生产更好的硬件,可以处理消耗内存的深度神经网络。

乙状结肠神经元:介绍

所以现在我们有了一个更复杂的带有隐藏层的神经网络。但是我们还没有用阶跃函数解决激活问题。

在上一篇文章中,我们谈到了阶跃函数线性的局限性。需要记住的一点是:如果激活函数是线性的,那么你可以在神经网络中任意堆叠多个隐层,最终输出的仍然是原始输入数据的一个 线性组合 。如果概念难以理解,请 务必阅读此链接 以获得的解释。这种线性意味着它不能真正掌握非线性问题的复杂性,如 XOR 逻辑或由曲线或圆分隔的模式。

同时,阶跃函数也没有有用的导数(它的导数在 x 轴上的 0 点处处处为 0 或未定义)。对于反向传播不起作用,这个我们在下一篇帖子里一定会讲到!

Graph 7: Step Function

好吧,这里有另一个问题:具有阶跃函数的感知器作为神经网络的“关系候选者”不是很“稳定”。想想看:这个女孩(或男孩)有严重的躁郁症!有一天(对于 z < 0 ),(s)他都是“安静”“下来”,给你零反应。然后又过了一天(对于 z ≥ 0 ),他突然“健谈”“活泼”,跟你说个不停。巨大的变化!她/他的心情是没有过渡的,你不知道什么时候是下降还是上升。是的…那是阶梯函数。

因此,基本上,我们感知机网络输入层中任何权重的微小变化都可能导致一个神经元突然从 0 翻转到 1,这可能再次影响隐藏层的行为,然后影响最终结果。就像我们已经说过的,我们想要一种学习算法,它可以通过逐渐改变权重来改善我们的神经网络,而不是通过平坦的无响应或突然的跳跃。如果我们不能使用阶跃函数来逐渐改变权重,那么它就不应该是选择。

Graph 8: We Want Gradual Change in Weights to Gradually Change Outputs

现在告别带阶跃函数的感知器。我们正在为我们的神经网络寻找一个新的合作伙伴, sigmoid 神经元,它具有 sigmoid 功能(duh)。但是不要担心:唯一会改变的是激活函数,到目前为止我们所了解的关于神经网络的一切仍然适用于这种新型神经元!

Sigmoid Function

Graph 9: Sigmoid Function using Matplotlib

如果函数对你来说看起来很抽象或者很奇怪,那么不要太在意像欧拉数 e 之类的细节或者最初是怎么有人想出这个疯狂的函数的。对于那些不精通数学的人来说,关于图 9 中的 sigmoid 函数,唯一重要的事情首先是它的曲线,其次是它的导数。以下是一些更多的细节:

  1. Sigmoid 函数产生与阶跃函数相似的结果,输出介于 0 和 1 之间。曲线在 z=0 处过 0.5,我们可以为激活函数设置规则,比如:如果乙状结肠神经元的输出大于等于 0.5,则输出 1;如果输出小于 0.5,则输出 0。
  2. Sigmoid 函数的曲线上没有加加速度。它是光滑的,它有一个非常好的简单的导数【σ(z)(1-σ(z)】,****,在曲线上处处可微。导数的微积分推导可以在栈溢出这里找到如果你想看的话。但是不一定要知道怎么推导。这里没有压力。*****
  3. 如果 z 非常负,那么输出大约为 0;如果 z 非常正,则输出约为 1;但在 z=0 左右,其中 z 既不太大也不太小(在图 9 中两条外侧垂直网格虚线之间),随着的变化,我们会有相对更多的偏差。******

现在,这似乎是我们神经网络的测年材料:)Sigmoid 函数,不同于阶跃函数,将非线性引入到我们的神经网络模型中。非线性只是指我们从神经元得到的输出,是一些输入 x (x1,x2,…,xm) 和权重 w (w1,w2,…,wm) 加偏置然后放入一个 sigmoid 函数的点积,不能用输入【x(x1,x2,…,XM)的一个线性组合来表示****

当被多层神经网络中的每个神经元使用时,该非线性激活函数产生原始数据的新的“表示,并且最终允许非线性判定边界,例如 XOR。因此,在 XOR 的情况下,如果我们在隐藏层中添加两个 sigmoid 神经元,我们可以在另一个空间中,将原始 2D 图重塑为类似下面图 10 左侧的 3D 图像。因此,该脊允许对异或门进行分类,它代表了图 10 右侧 2D 异或门的浅黄色区域。所以如果我们的输出值在山脊较高的区域上,那么应该是真或者 1(就像天气冷但不热,或者天气热但不冷);如果我们的输出值在两个角上较低的平坦区域,那么它为假或 0,因为说天气既热又冷或既不热也不冷是不对的(好吧,我想天气可能既不热也不冷…你明白我的意思吧…对吗?).

Graph 10. Representation of Neural Networks with Hidden Layers to Classify XOR Gate. Source: colinfahey.com/

我知道这些关于非线性的谈话可能会令人困惑,所以请在这里阅读更多关于线性和非线性的内容(Christopher Olah 的一个很棒的博客中的动画直观的帖子),在这里阅读(由 Vivek Yadav 带 ReLU 激活功能),在这里阅读(由 Sebastian Raschka)。希望你已经意识到为什么非线性激活函数是重要的,如果没有,放轻松,给自己一些时间来消化它。

问题解决了……暂时的;)我们将在不久的将来看到一些不同类型的激活函数,因为 sigmoid 函数也有自己的问题!比较流行的有 tanhReLU 。然而,这是另一篇文章。

多层神经网络:直观的方法

好吧。因此,我们在神经网络中引入了隐藏层,并用 sigmoid 神经元取代了感知器。我们还介绍了非线性激活函数允许对我们的数据中的非线性决策边界或模式进行分类的思想。你可以记住这些要点,因为它们是事实,但我鼓励你在互联网上搜索一下,看看你是否能更好地理解这个概念(我们自然需要一些时间来理解这些概念)。

现在,我们从未讨论过一个非常重要的问题:首先,我们究竟为什么要在神经网络中设置隐藏层?隐藏层如何神奇地帮助我们解决单层神经元无法解决的复杂问题?

从上面的 XOR 示例中,您已经看到了在 1 个隐藏层中添加两个隐藏神经元可以将我们的问题重新塑造到一个不同的空间中,这神奇地为我们创建了一种用脊对 XOR 进行分类的方法。因此,隐藏层以某种方式扭曲了问题,使神经网络很容易对问题或模式进行分类。现在,我们将使用一个经典的教科书示例:手写数字的识别,来帮助您直观地理解隐藏层的作用。

Graph 11. MNIST dataset of Hand-written Digits. Source: neuralnetworksanddeeplearning.com/

图 11 中的数字**属于一个名为 MNIST 的数据集。它包含了 70,000 个人手书写的数字的例子。这些数字中的每一个都是 28x28 像素的图片。所以一个数字的每个图像总共有 2828=784 个像素。每个像素取 0 到 255 之间的值(RGB 颜色代码)。0 表示颜色是白色,255 表示颜色是黑色。***

Graph 12. MNIST digit 5, which consist of 28x28 pixel values between 0 and 255. Source: neuralnetworksanddeeplearning.com/

现在,计算机无法像我们人类一样真正“看到”一个数字,但如果我们将图像分解为一个由 784 个数字组成的数组,如[0,0,180,16,230,…,4,77,0,0,0,0],那么我们可以将这个数组输入到我们的神经网络中。计算机不能通过“看”来理解图像,但它可以理解和分析代表图像的像素数量。

Graph 13: Multi-Layer Sigmoid Neural Network with 784 input neurons, 16 hidden neurons, and 10 output neurons

所以,让我们建立一个类似上面图 13 中的神经网络。它有 784 个 28×28 像素值的输入神经元。假设它有 16 个隐藏神经元和 10 个输出神经元。10 个输出神经元以数组的形式返回给我们,每个神经元负责对一个数字从 0 到 9 进行分类。所以如果神经网络认为手写数字是零,那么我们应该得到一个输出数组[1,0,0,0,0,0,0,0,0,0],这个数组中第一个感觉数字是零的输出被我们的神经网络“激发”为 1,其余的都是 0。如果神经网络认为手写数字是 5,那么我们应该得到[0,0,0,0,0,1,0,0,0,0,0,0]。负责分类 5 的第 6 个元素被触发,而其他元素没有被触发。如此等等。

还记得我们提到过,神经网络通过对数据进行重复训练来变得更好,这样它们就可以调整网络每一层的权重,以使最终结果/实际输出更接近所需输出吗?因此,当我们实际上用 MNIST 数据集中的所有训练样本训练这个神经网络时,我们不知道应该给每一层分配什么权重。所以我们只是随机要求计算机在每一层分配权重。(我们不希望所有的权重都是 0,如果空间允许,我会在下一篇文章中解释)。

这种随机初始化权重的概念很重要,因为每次训练深度学习神经网络时,你都在为权重初始化不同的数字。所以本质上,在网络被训练之前,你和我都不知道神经网络中发生了什么。一个经过训练的神经网络具有在特定值优化的权重,这些权重对我们的问题做出最佳预测或分类。从字面上看,这是一个黑匣子。并且每次经过训练的网络将具有不同的权重集。

为了便于论证,让我们想象一下图 14 中的以下情况,这是我从迈克尔·尼尔森的在线书籍中借来的:

Graph 14. An Intuitive Example to Understand Hidden Layers

在监督学习中用一轮又一轮的标记数据训练神经网络后,假设前 4 个隐藏神经元学会识别上面图 14 左侧的模式。然后,如果我们向神经网络输入一个手写数字 0 的数组,网络应该正确地触发隐藏层中的前 4 个隐藏神经元,而其他隐藏神经元保持沉默,然后再次触发第一个输出神经元,而其余的神经元保持沉默。

Graph 15. Neural Networks are Black Boxes. Each Time is Different.

如果你用一组新的随机权重来训练神经网络,它可能会产生下面的网络(比较图 15 和图 14 ),因为权重是随机的,我们永远不知道哪个会学习哪个或什么模式。但是,如果训练得当,网络仍然应该触发正确的隐藏神经元,然后产生正确的输出。

Our quote this week ;)

最后要提一点:在多层神经网络中,第一个隐藏层将能够学习一些非常简单的模式。每增加一层隐藏层,就能逐渐学习更复杂的模式。请看来自《科学美国人》的图 16 中的人脸识别示例:)

Graph 16: Each Hidden Layer Learns More Complex Features. Source: Scientific American

一些很棒的人制作了下面的网站,让你玩玩神经网络,看看隐藏层是如何工作的。试试看。真的很好玩!

**** [## 张量流-神经网络游乐场

这是一种构建从数据中学习的计算机程序的技术。它非常松散地基于我们如何思考…

playground.tensorflow.org](playground.tensorflow.org/)

Ophir Samson 写了一篇很好的文章,也解释了什么是神经网络,有很好的可视化效果,而且很简洁!

[## 深度学习周刊:什么是神经网络?

对于本周的文章,我想通过我收集的一个简单的例子来阐明什么是神经网络…

medium.com](medium.com/towards-dat…)

概述

在这篇文章中,我们回顾了感知器的局限性,介绍了具有新激活函数的 sigmoid 神经元,称为 sigmoid function。我们还讨论了多层神经网络如何工作,以及神经网络中隐藏层背后的直觉。

我们现在几乎完成了理解基本神经网络的全部课程;)呵呵,还没完呢!在下一篇文章中,我将会谈到一种叫做损失函数的东西,以及这种神秘的反向传播,我们只提到过,但从来没有访问过!如果你等得不耐烦,请查看以下链接:

[## 用于视觉识别的 CS231n 卷积神经网络

斯坦福 CS231n 课程材料和笔记:视觉识别的卷积神经网络。

cs231n.github.io](cs231n.github.io/optimizatio…) [## 一个逐步反向传播的例子

背景技术反向传播是训练神经网络的常用方法。网上不缺论文说…

mattmazur.com](mattmazur.com/2015/03/17/…)

敬请关注,最重要的是,享受学习:D 的乐趣

你喜欢这次阅读吗?别忘了关注我的 推特 ****

使用张量流的多层感知器

原文:towardsdatascience.com/multi-layer…

构建多层感知器和张量流的入门指南,用于构建数字识别系统。

在这篇博客中,我们将使用 TensorFlow 构建一个神经网络(多层感知器),并成功训练它识别图像中的数字。Tensorflow 是由发布的非常受欢迎的深度学习框架,本笔记本将指导使用该库构建神经网络。如果你想了解什么是多层感知器,你可以看看我之前的博客,在那里我用 Numpy 从头构建了一个多层感知器。

让我们从导入数据开始。作为 Keras,一个高级深度学习库已经将 MNIST 数据作为其默认数据的一部分,我们只是从那里导入数据集,并将其分为训练集和测试集。

*## Loading MNIST dataset from keras*
**import** **keras**
**from** **sklearn.preprocessing** **import** LabelBinarizer
**import** **matplotlib.pyplot** **as** **plt**
%matplotlib inline**def** load_dataset(flatten=**False**):
    (X_train, y_train), (X_test, y_test) = keras.datasets.mnist.load_data() *# normalize x*
    X_train = X_train.astype(float) / 255.
    X_test = X_test.astype(float) / 255. *# we reserve the last 10000 training examples for validation*
    X_train, X_val = X_train[:-10000], X_train[-10000:]
    y_train, y_val = y_train[:-10000], y_train[-10000:] **if** flatten:
        X_train = X_train.reshape([X_train.shape[0], -1])
        X_val = X_val.reshape([X_val.shape[0], -1])
        X_test = X_test.reshape([X_test.shape[0], -1]) **return** X_train, y_train, X_val, y_val, X_test, y_testX_train, y_train, X_val, y_val, X_test, y_test = load_dataset()
*## Printing dimensions*
print(X_train.shape, y_train.shape)
*## Visualizing the first digit*
plt.imshow(X_train[0], cmap="Greys");

正如我们所看到的,我们当前的数据的维数为 N 28* 28,我们将从展平 N*784 中的图像开始,并对我们的目标变量进行一次性编码。

*## Changing dimension of input images from N*28*28 to  N*784*
X_train = X_train.reshape((X_train.shape[0],X_train.shape[1]*X_train.shape[2]))
X_test = X_test.reshape((X_test.shape[0],X_test.shape[1]*X_test.shape[2]))print('Train dimension:');print(X_train.shape)
print('Test dimension:');print(X_test.shape)*## Changing labels to one-hot encoded vector*
lb = LabelBinarizer()
y_train = lb.fit_transform(y_train)
y_test = lb.transform(y_test)
print('Train labels dimension:');print(y_train.shape)
print('Test labels dimension:');print(y_test.shape)

现在我们已经处理了数据,让我们开始使用 tensorflow 构建我们的多层感知器。我们将从导入所需的库开始。

*## Importing required libraries*
**import** **numpy** **as** **np**
**import** **tensorflow** **as** **tf**
**from** **sklearn.metrics** **import** roc_auc_score, accuracy_score
s = tf.InteractiveSession()

tf。InteractiveSession() 是一种无论何时我们想要运行一个模型,都可以直接运行 tensorflow 模型而无需实例化一个图的方法。我们将建立 784(输入)-512(隐藏层 1)-256(隐藏层 2)-10(输出)神经网络模型。让我们从定义初始化变量开始我们的模型构建。

*## Defining various initialization parameters for 784-512-256-10 MLP model*
num_classes = y_train.shape[1]
num_features = X_train.shape[1]
num_output = y_train.shape[1]
num_layers_0 = 512
num_layers_1 = 256
starter_learning_rate = 0.001
regularizer_rate = 0.1

在 tensorflow 中,我们为输入变量和输出变量以及任何我们想要跟踪的变量定义了一个占位符。

*# Placeholders for the input data*
input_X = tf.placeholder('float32',shape =(**None**,num_features),name="input_X")
input_y = tf.placeholder('float32',shape = (**None**,num_classes),name='input_Y')
*## for dropout layer*
keep_prob = tf.placeholder(tf.float32)

因为密集图层需要权重和偏差,并且需要使用零均值和小方差(1/要素数量的平方根)的随机正态分布进行初始化。

*## Weights initialized by random normal function with std_dev = 1/sqrt(number of input features)*
weights_0 = tf.Variable(tf.random_normal([num_features,num_layers_0], stddev=(1/tf.sqrt(float(num_features)))))
bias_0 = tf.Variable(tf.random_normal([num_layers_0]))weights_1 = tf.Variable(tf.random_normal([num_layers_0,num_layers_1], stddev=(1/tf.sqrt(float(num_layers_0)))))
bias_1 = tf.Variable(tf.random_normal([num_layers_1]))weights_2 = tf.Variable(tf.random_normal([num_layers_1,num_output], stddev=(1/tf.sqrt(float(num_layers_1)))))
bias_2 = tf.Variable(tf.random_normal([num_output]))

现在我们将开始编写图形计算来开发我们的 784(输入)-512(隐藏层 1)-256(隐藏层 2)-10(输出)模型。我们将把每一层的输入乘以其各自的权重,并添加偏差项。在权重和偏差之后,我们需要添加一个激活;我们将对隐藏层使用 ReLU activation,对最终输出层使用 softmax 来获得类概率分数。也是为了防止过度拟合;让我们在每个隐藏层后添加一些 drop out。辍学是在我们的网络中产生冗余的一个基本概念,这导致了更好的泛化。

*## Initializing weigths and biases*
hidden_output_0 = tf.nn.relu(tf.matmul(input_X,weights_0)+bias_0)
hidden_output_0_0 = tf.nn.dropout(hidden_output_0, keep_prob)hidden_output_1 = tf.nn.relu(tf.matmul(hidden_output_0_0,weights_1)+bias_1)
hidden_output_1_1 = tf.nn.dropout(hidden_output_1, keep_prob)predicted_y = tf.sigmoid(tf.matmul(hidden_output_1_1,weights_2) + bias_2)

现在,我们需要定义一个损失函数来优化我们的权重和偏差,我们将使用 softmax 交叉熵和 logits 来预测和正确的标签。我们也将增加一些 L2 正则化到我们的网络。

*## Defining the loss function*
loss = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=predicted_y,labels=input_y)) \
        + regularizer_rate*(tf.reduce_sum(tf.square(bias_0)) + tf.reduce_sum(tf.square(bias_1)))

现在,我们需要为我们的网络定义一个优化器和学习率,以优化给定损失函数的权重和偏差。我们将每五个时期对我们的学习速率使用指数衰减,以减少 15%的学习。对于优化器,我们将使用 Adam 优化器。

*## Variable learning rate*
learning_rate = tf.train.exponential_decay(starter_learning_rate, 0, 5, 0.85, staircase=**True**)
*## Adam optimzer for finding the right weight*
optimizer = tf.train.AdamOptimizer(learning_rate).minimize(loss,var_list=[weights_0,weights_1,weights_2,
                                                                         bias_0,bias_1,bias_2])

我们已经完成了模型构建。让我们定义准确性度量来评估我们的模型性能,因为损失函数是非直观的。

*## Metrics definition*
correct_prediction = tf.equal(tf.argmax(y_train,1), tf.argmax(predicted_y,1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))

我们现在将开始在训练数据上训练我们的网络,同时在测试数据集上评估我们的网络。我们将使用大小为 128 的批处理优化,并训练它 14 个时期,以获得 98%以上的准确性。

*## Training parameters*
batch_size = 128
epochs=14
dropout_prob = 0.6training_accuracy = []
training_loss = []
testing_accuracy = []s.run(tf.global_variables_initializer())
**for** epoch **in** range(epochs):    
    arr = np.arange(X_train.shape[0])
    np.random.shuffle(arr)
    **for** index **in** range(0,X_train.shape[0],batch_size):
        s.run(optimizer, {input_X: X_train[arr[index:index+batch_size]],
                          input_y: y_train[arr[index:index+batch_size]],
                        keep_prob:dropout_prob})
    training_accuracy.append(s.run(accuracy, feed_dict= {input_X:X_train, 
                                                         input_y: y_train,keep_prob:1}))
    training_loss.append(s.run(loss, {input_X: X_train, 
                                      input_y: y_train,keep_prob:1}))

    *## Evaluation of model*
    testing_accuracy.append(accuracy_score(y_test.argmax(1), 
                            s.run(predicted_y, {input_X: X_test,keep_prob:1}).argmax(1)))
    print("Epoch:**{0}**, Train loss: **{1:.2f}** Train acc: **{2:.3f}**, Test acc:**{3:.3f}**".format(epoch,
                                                                    training_loss[epoch],
                                                                    training_accuracy[epoch],
                                                                   testing_accuracy[epoch]))

让我们可视化训练并测试作为历元数的函数的准确性。

*## Plotting chart of training and testing accuracy as a function of iterations*
iterations = list(range(epochs))
plt.plot(iterations, training_accuracy, label='Train')
plt.plot(iterations, testing_accuracy, label='Test')
plt.ylabel('Accuracy')
plt.xlabel('iterations')
plt.show()
print("Train Accuracy: **{0:.2f}**".format(training_accuracy[-1]))
print("Test Accuracy:**{0:.2f}**".format(testing_accuracy[-1]))

正如我们所看到的,我们已经成功训练了一个多层感知器,它是用 tensorflow 编写的,具有很高的验证准确性!

我希望你喜欢阅读,并随时使用我的代码(也可以在 jupyter 笔记本中找到)来为你的目的进行测试。此外,如果对代码或博客有任何反馈,请随时联系 aayushmnit@gmail.comLinkedIn 或给我发电子邮件。

分类特征的多态 LSTMs

原文:towardsdatascience.com/multi-state…

语境

神经网络现在在很多方面都有广泛的应用。从图像标题生成到乳房癌症预测,这种巨大的应用多样性是各种重要的神经架构 ( 前馈神经网络、卷积神经网络等)的自然结果。在所有这些架构中,长短期记忆(LSTM)——递归神经网络的一个特例——已经被证明在诸如机器翻译时间序列预测或任何数据为顺序的任务上非常成功。这主要是由于他们能够记忆相对的长期相关性,这是通过考虑先前的信息以进行进一步预测来实现的。

但是仅靠 LSTMs 是不够的。有时我们需要调整这些层,使它们适应手头的任务。

Kwyk ,我们提供在线数学练习。每次回答一个练习,我们都会收集一些数据,然后使用网站为每个学生量身定制作业。为了确定哪些练习最有可能让学生进步,我们需要知道他/她在任何给定的时间点上成功完成每个练习的可能性有多大。通过正确预测这些成功概率,我们可以选择最大化整体进度的作业。

这篇文章旨在介绍我们改进的 LSTM 单元“多态 LSTM ”,我们的模型就是基于它来尝试解决这个问题的。

快速数据概述

当一个练习被回答时,我们保存关于学生(或“用户”)和练习的信息,以及一个额外的分数值,该值是(0)还是(1)取决于用户的成功。我们收集的信息以分类特征的形式告诉我们:“是哪个练习?“,”是哪一章?是什么学生?他/她是哪个年级的?“…这会产生具有几十到几千种形态的特征,我们用它们来预测“得分”变量并获得成功概率

A sample of our data

基于 LSTM 的模型

选择 LSTM 模式背后有两个主要动机。

第一个原因是我们使用的所有特征都是绝对的。这就是我们想要学习的真正信息来源。通过手动烹饪特征,如之前得分的移动平均值,我们会因自己的主观选择而引入偏差。因此,我们选择依靠神经网络,直接反馈我们的数据,让特征自动形成****客观形成

第二个动机是在所有可用的架构中选择 LSTM。这仅仅是因为我们相信,对于每个学生来说,每次练习成功的概率取决于所有之前的时间结果**,因此是连续的。**

考虑到这一点,我们想到了一种架构,其中对于每个分类特征,共享的 LSTM 将保存每个模态的先前结果的历史。

让我们以“ user_id ”特性为例。在这种情况下,我们需要改编一个 LSTM 细胞来即时记忆每个学生过去如何成功的历史。这是通过在基本的 LSTM 单元中添加我们称之为“T42”的多状态“T43”来实现的:

Left : Basic LSTM cell / Right : Multi-state LSTM cell. Note : If you are not familiar with LSTMs you can refer to this great post by Christopher Olah.

每次一个学生的标签被馈送到多状态 LSTM 单元,它就开始查找相应的状态以前的分数**。然后,学生的状态被发送到更新一个共享 LSTM 单元。同时,先前的分数被馈送到这个 LSTM 单元,该单元产生一个输出。接下来,产生的状态返回到更新多状态中的学生数据。最后,一旦我们观察到实际的分数,这个值又被发送到更新学生在多状态中的先前分数。**

这个基本 LSTM 单元的修改版本工作方式类似,但有一个额外的优势:它现在可以直接接受一系列学生标签作为输入:

An unrolled Multi-state LSTM.

在前面的例子中,我们考虑了“user_id”分类特性,但这实际上可以应用于我们所有的分类特性。事实上,举例来说,在“ exercise_id ”功能上使用多状态 LSTM 将导致它学习每个练习的历史成功率**。从这里开始,我们使用的完整网络非常简单:**

The complete graph we used to solve our problem.

总而言之,这种架构试图学习每个分类特征的每个模态的单独历史,然后使用 LSTM 的输出来预测给定学生在给定练习中的成功概率。

结果

基线

为了评估我们基于 LSTM 的模型,我们需要一个基准。在尝试任何深度学习方法之前,我们曾经有一个 boosting 算法( 梯度 Boosting )使用了一些手工特征。从所有的分类特征中,我们为每个特征的每个模态编造了一些先前得分的快** 移动平均值 。然后,我们将这些特征输入到梯度推进分类器中,让奇迹发生。**

比较

两个分类器都有相同的方法。事实上,基线模型使用手工移动平均线作为特征,基于 LSTM 的方法自动学习这些历史来预测分数。果不其然,两种算法得到了相近的准确率分数(基线:74.61%,LSTM 基网络: 75.34% )。但预测的分布却大不相同:

We can see that the LSTM-based model is much better at segregating students.

事实上,基于 LSTM 的模型似乎将分成了 3 到 4 个不同的人群:

  • 一个给不应该能答对的学生(概率<10%)
  • One for those who have a moderate to good chance to succeed (50
  • One for those who have a very important chance of succeeding (probability> 90%)。

相反,基线只预测了总体平均成功率周围的偏斜正态分布,没有特别的歧视。

但是,为了进一步研究这两种模型之间的差异,我们需要更详细地了解 MSE。事实上,单从 MSE 来看,这两种模型具有相似的性能:

  • 基线:0.17
  • LSTM 网络: 0.16

但是正如我们在之前的帖子中所讨论的,当真正的随机性与目标相关联时(这里,预测人类行为),我们可以通过查看其可靠性度量(REL)** 来更好地评估分类器的性能。**

通过将数据分类到相似预测概率的箱中来计算可靠性。然后,我们针对箱中的平均目标计算每个箱的 MSE。最后,我们取一个总平均值来得到我们的 REL 值。

为每个模型获得的指标是:

  • 基线:3.86 e-3
  • LSTM 网络: 2.86 e-4

事实上,我们看到基于 LSTM 的网络比梯度推进基线精确 10 倍以上,这可以解释我们在比较两种分布时观察到的更好的分离。

结论

总而言之,我们已经在一个真实的例子上看到了 LSTM s 对于序列数据分类是如何有效的。但是我们也看到了我们的LSTM 的修改版本**—多态 LSTM如何能够在没有任何预处理或特征工程的情况下达到更好的性能。事实上,这种新的 LSTM 细胞可以直接接受一系列标签作为输入,这意味着它只能用于分类特征并且仍然产生良好的结果。**

为了进一步改进多状态 LSTM 的 T1,下一步将会考虑多个标签之间的 T2 相关性。事实上,当预测一个学生在给定的一对相似练习中的表现时,预测的概率应该非常相似。尝试确保这种行为的一种方法是将一个嵌入到网络中的的练习集成起来,让它学习依赖关系

作者:

多流 RNN,串联 RNN,内部 Conv RNN,在 Tensorflow 中落后 2 RNN

原文:towardsdatascience.com/multi-strea…

GIF from this website

在过去的两周里,我一直渴望实现不同种类的递归神经网络 (RNN),最终我有时间实现它们。以下是我想尝试的不同 RNN 案例列表。

案例 a:香草递归神经网络 案例 b:多流递归神经网络 案例 c:级联递归神经网络 案例 d:内部卷积递归神经网络 案例 e:滞后 2 递归神经网络

请注意,所有这些模型只是为了好玩和表达我的创意。还有,我要在这篇文章中使用的基础代码来自我的旧文章“OCR 的门控递归卷积 NN”。

香草递归神经网络

Image from this website

总共有 5 个不同的 RNN 案例我想执行。然而,为了完全理解所有的实现,最好对普通 RNN 有一个很好的理解(案例 a 是普通 RNN,所以如果你理解案例 a 的代码,你就可以开始了。)

如果有人想回顾简单的 RNN,请访问我的旧博客文章“ Only Numpy:香草递归神经网络通过时间实践推导反向传播 ”。

案例 a:普通递归神经网络(结果)

红框 → 3 卷积层 →橙色 →全局平均池化和 SoftMax 绿圈 →时间为 0 的隐藏单元 蓝圈 →输入 4 个时间戳 黑框 →带 4 个时间戳的递归神经网络

如上所述,基本网络是简单的 RNN 结合卷积神经网络用于分类。RNN 的时间戳为 4,这意味着我们将在每个时间戳向网络提供 4 种不同的输入。为此,我将在原始图像中添加一些噪声。

蓝线 →一段时间内的训练成本 橙线 →一段时间内的训练精度 绿线 →一段时间内的测试成本 红线 →一段时间内的测试精度

如上所述,我们的基础网络已经运行良好。现在的问题是其他方法表现如何,它是否能够比我们的基础网络更好地正规化。

案例 b:多流递归神经网络(想法/结果)

红框 → 3 卷积层 橙框 →全局平均池化和 SoftMax 绿框 →时间为 0 的隐藏单元 蓝框 →卷积输入流 黄框 →全连通网络流 黑框 →带 4 时间戳的递归神经网络

这种 RNN 背后的想法只是为 RNN 提供不同的数据表示。在我们的基本网络中,我们有原始图像或添加了一些噪声的图像。

红框 →增加四个 CNN/FNN 层来“处理”输入 蓝框 →在每个不同的时间戳创建输入

如下图所示,我们的 RNN 使用[batch_size,26,26,1]将宽度和高度减少了 2 倍。我希望数据的不同表示可以作为一种正则化。(类似于数据扩充)

蓝线 →一段时间内的训练成本 橙线 →一段时间内的训练精度 绿线 →一段时间内的测试成本 红线 →一段时间内的测试精度

正如上面所看到的,网络做得很好,在测试图像上比我们的基础网络高出 1%。

情况 c:级联递归神经网络(想法/结果)

红框 → 3 卷积层 →橙色 →全局平均池化和 SoftMax 绿圈 →时间为 0 的隐藏单元 蓝圈 →输入 4 个时间戳 →黑框 →带 4 个时间戳的递归神经网络 黑弯箭头 →级联输入每个时间戳

这种方法非常简单,其思想是在每个时间戳上提取不同的特征,随着时间的推移,网络具有更多的特征可能是有用的。(对于循环层。)

蓝线 →一段时间内的训练成本 橙线 →一段时间内的训练精度 绿线 →一段时间内的测试成本 红线 →一段时间内的测试精度

可悲的是,这是一个巨大的失败。我猜空的隐藏值对网络的良好运行没有任何帮助。

案例 d:内部卷积递归神经网络(想法/结果)

红框 → 3 卷积层 橙框 →全局平均池和 SoftMax 绿圈 →时间为 0 的隐藏单元 蓝圈 →输入 4 个时间戳 黑框 →带 4 个时间戳的递归神经网络 灰色箭头 →在传递到下一个时间戳之前执行内部卷积

如上所述,这个网络与我们的基础网络接收完全相同的输入。然而,这次我们将在数据的内部表示中执行额外的卷积运算。

右图 →声明 3 个新的卷积层 左图(红框) →如果当前内层不为无,我们将进行额外的卷积操作。

我实际上并没有在这个实现背后的理论原因,我只是想看看它是否工作 LOL。

蓝线 →一段时间内的训练成本 橙线 →一段时间内的训练精度 绿线 →一段时间内的测试成本 红线 →一段时间内的测试精度

如上所述,网络在融合方面做得很好,但是它无法超越我们的基础网络。(可悲)。

情况 e:滞后 2 递归神经网络(想法/结果)

红框 → 3 卷积层 →橙框 →全局平均池化和 SoftMax 绿圈 →时间为 0(或滞后 1)的隐藏单元 →蓝圈 →输入 4 个时间戳 黑框 →带有 4 个时间戳的递归神经网络 紫圈 →隐藏状态滞后 2

在传统的 RNN 设置中,我们仅依靠最早的值来确定当前值。有一段时间我在想,我们没有理由把回看时间(或滞后)限制为 1。我们可以将这个想法扩展到滞后 3 或滞后 4 等。(为了简单起见,我采用了滞后 2)

蓝线 →一段时间内的训练成本 橙线 →一段时间内的训练精度 绿线 →一段时间内的测试成本 红线 →一段时间内的测试精度

谢天谢地,这个网络比基础网络做得更好。(但是具有非常小的余量),然而这种类型的网络将最适合于时间序列数据。

交互式代码/透明度

对于 Google Colab,你需要一个 Google 帐户来查看代码,而且你不能在 Google Colab 中运行只读脚本,所以在你的操场上复制一份。最后,我永远不会请求允许访问你在 Google Drive 上的文件,仅供参考。编码快乐!同样为了透明,我在 github 上上传了所有的训练日志。

要访问案例的代码,请点击这里,要查看日志,请点击这里。 点击此处查看案例 b 的代码,点击此处查看日志。 要访问案例 c 的代码,请点击此处,要查看日志,请点击此处。 要访问案例 c 的代码,请点击此处,要查看日志,请点击此处。 点击此处查看案例 c 的代码,点击此处查看日志。

最后的话

我想回顾 RNN 已经很久了,现在我终于可以这样做了。

如果发现任何错误,请发电子邮件到 jae.duk.seo@gmail.com 给我,如果你想看我所有的写作清单,请在这里查看我的网站。

同时,在我的 twitter 上关注我这里,访问我的网站,或者我的 Youtube 频道了解更多内容。我还实现了广残网,请点击这里查看博文 t。

参考

  1. 【NIPS 2017/Part 1】用于 OCR 的带交互码的门控递归卷积 NN【手动反推…(2018).走向数据科学。检索于 2018 年 6 月 6 日,来自https://towards data science . com/nips-2017-tensor flow-gated-recurrent-convolution-neural-network-for-ocr-part-1-with-47 bb 2 A8 a7 ab 3
  2. 带 Tensorflow 的软签激活功能【带 TF 的手动背道具】。(2018).走向数据科学。检索于 2018 年 6 月 6 日,来自https://towards data science . com/soft-sign-activation-function-with-tensor flow-manual-back-prop-with-TF-5a 04 F3 c8 e9 c 1
  3. 东格斯,V. (2018)。递归神经网络。machinelearning-blog.com。检索于 2018 年 6 月 6 日,来自https://machine learning-blog . com/2018/02/21/recurrent-neural-networks/
  4. 唯一 Numpy:香草递归神经网络通过时间实践推导反向传播-部分…(2017).中等。检索于 2018 年 6 月 6 日,来自https://medium . com/@ SeoJaeDuk/only-numpy-vanilla-recurrent-neural-network-back-propagation-practice-math-956 fbea 32704
  5. 递归神经网络。(2018).En.wikipedia.org。检索于 2018 年 6 月 6 日,来自en.wikipedia.org/wiki/Recurr…

多模态深度学习

原文:towardsdatascience.com/multimodal-…

使用深度学习的多模态融合

由于对深度学习的研究充满热情,我一直在寻找该领域未被探索的领域(尽管很难找到)。我之前做过 数学应用题 等许多类似的题目。

使用深度神经网络作为黑盒的挑战激起了我的兴趣。我决定更深入地研究“多模态深度学习中的可解释性”这个话题。以下是一些结果。

多模态数据

我们对世界的体验是多模态的——我们看到物体,听到声音,感受纹理,闻到气味,品尝味道。模态是指事情发生或经历的方式,当一个研究问题包括多个这样的模态时,它就被称为多模态。为了让人工智能在理解我们周围的世界方面取得进展,它需要能够一起解释这种多模态信号。

比如 图片通常会关联标签和文字说明;文本包含图像,以更清楚地表达文章的主要思想。 不同的模态以非常不同的统计特性为特征。

多模态深度学习

虽然组合不同模态或类型的信息以提高性能看起来是直观上吸引人的任务,但是在实践中,组合不同水平的噪声和模态之间的冲突是具有挑战性的。此外,模态对预测输出具有不同的定量影响。实践中最常见的方法是将不同输入的高级嵌入连接起来,然后应用 softmax。

Example of Multimodal deep learning where different types of NN are used to extract features

这种方法的问题在于,它会对所有子网络/模态给予同等的重视,这在现实生活中是极不可能的。

All Modalities have an equal contribution towards prediction

网络的加权组合

我们采用子网络的加权组合,使得每个输入模态可以对输出预测具有学习贡献(θ)。

我们的优化问题变成了-

Loss Function after Theta weight is given to each sub-network.

The output is predicted after attaching weights to the subnetworks.

但是这一切的用处!!

言归正传,我开始吹嘘成果了。

准确性和可解释性

我们在两个真实的多模态数据集上取得了最先进的结果

多模态情感强度语料库(MOSI)数据集— 每毫秒视频注释音频特征的注释数据集 417。总共有 2199 个带注释的数据点,其中情绪强度被定义为从强负到强正,线性标度从 3 到+3。

模式是-

  1. 文本

2.声音的

3.演讲

Amount of contribution of each modality on sentiment prediction

转录起始位点预测(TSS)数据集— 转录是基因表达的第一步,其中 DNA 的特定片段被复制成 RNA (mRNA)。转录起始位点是转录开始的位置。DNA 片段的不同部分具有影响其存在的不同特性。我们把 TSS 分成三部分-

  1. 上游 DNA
  2. 下游 DNA
  3. TSS 区域

我们取得了前所未有的 3%的进步,超过了之前的最高水平。具有 TATA 盒的下游 DNA 区域对该过程影响最大。

我们还对合成生成的数据进行了实验,以验证我们的理论。

现在,我们正在起草一篇论文,准备提交给一本 ML 期刊。

如果你有兴趣了解多模态学习的数学细节或范围,一般来说,在 purvanshi.mehta11@gmail.com 上 ping 我。欢迎对作品提出意见。

多模态图像到图像翻译

原文:towardsdatascience.com/multimodal-…

在这篇博客中,我将解释图像到图像的翻译,这就是通常所说的bicle gan。图像到图像转换的任务可以被认为是每个像素的回归或分类。但是可以用来解决这个问题的更有趣的方法是生成对抗网络。通过使用 GANs 获得的结果更健壮并且在感知上更真实。

在论文“走向多模态图像到图像翻译”中,目的是在给定输入图像的情况下生成输出图像的分布。基本上,它是使用条件生成对抗网络的图像到图像翻译模型的扩展。在 pix2pix 之前,许多人试图使用 GAN 无条件地解决这个问题,并且使用 L2 回归以输入为条件输出。除了变分自动编码器之外,我已经在我以前的博客中解释了条件 GAN。

在模型的第一部分,我们使用了一个条件变分自动编码器 GAN。想法是使用编码器网络学习目标图像的低维潜在表示,即,已经生成所有目标图像的概率分布,并且我们尝试该分布接近正态分布,以便在推断时间期间容易采样。接下来,我们使用一个生成器,使用编码表示 z 将输入图像映射到输出图像。

在图像的第二部分,我们使用了条件隐回归子 GAN。在这种情况下,从正态分布 N(z)中采样 z,除了输入图像 A 之外,该正态分布 N(z)还被馈送到生成器以获得输出图像。这个输出图像然后被馈送到编码器网络以输出 z ’,我们试图使它接近 N(z)。经过这两步,我们计算损失函数。最终损失函数如下所示:

其中 G、D 和 E 代表发生器、鉴别器和编码器。

在该模型中,从潜在向量(z)到输出图像以及输出图像到潜在向量的映射是双射的。整体架构由两个循环组成,B-> z-> B’和 z-> B’--> z’,因此得名 BicycleGAN。该图清楚地总结了该架构。

要点:-

  • 我们有 3 个不同的网络:a)鉴别器,b)编码器,和 c)发生器。
  • cVAE-GAN(条件变分自动编码器-生成对抗网络)被用于将地面真实输出图像 B 编码为潜在向量 z,然后潜在向量 z 被用于重构输出图像 B’,即,B-> z-> B’。
  • 对于逆映射(z-> B’--> z’),我们使用 LR-GAN(潜在回归生成对抗网络),其中使用生成器从输入图像 A 和 z 生成 B’
  • 结合这两个模型,我们得到了自行车根。
  • 发生器的架构与 U-net 相同,其中存在具有对称跳跃连接的编码器和解码器网络。
  • 对于编码器,我们使用几个残差块对输入图像进行有效编码。
  • 使用批次大小为 1 的批次规范化,使用 Adam optimizer 来训练该模型。
  • 泄漏 ReLU 激活功能用于所有类型的网络。

履行

我在 TensorFlow 中实现了 BicycleGAN,你可以在我的 GitHub 个人资料中找到它。

[## prakashpendey 9/自行车

NIPS 论文“多模态图像到图像翻译”的 BicycleGAN - Tensorflow 实现

github.com](github.com/prakashpand…)

参考

arxiv.org/pdf/1711.11…

用于文本分析的多项式朴素贝叶斯分类器

原文:towardsdatascience.com/multinomial…

机器学习最流行的应用之一是分类数据的分析,特别是文本数据。问题是,有很多关于数字数据的教程,但是关于文本的很少。考虑到我过去关于机器学习的大多数博客都是基于 Scikit-Learn 的,我决定通过自己实现整个事情来玩玩这个。

在这篇博客中,我将介绍如何为 20 个新闻组数据集实现多项式朴素贝叶斯分类器。20 个新闻组数据集包含大约 18000 个关于 20 个主题的新闻组帖子,分为两个子集:一个用于培训(或开发),另一个用于测试(或性能评估)。训练集和测试集之间的划分基于在特定日期之前和之后发布的消息。

图书馆

首先,让我们导入编写实现所需的库:

**import** **numpy** **as** **np**
**import** **pandas** **as** **pd**
**import** **matplotlib.pyplot** **as** **plt**
**import** **operator**

阶级分布

首先,我们计算每个类中文档的比例:

*#Training label*
train_label = open('20news-bydate/matlab/train.label')

*#pi is the fraction of each class*
pi = {}

*#Set a class index for each document as key*
**for** i **in** range(1,21):
    pi[i] = 0

*#Extract values from training labels*
lines = train_label.readlines()

*#Get total number of documents*
total = len(lines)

*#Count the occurence of each class*
**for** line **in** lines:
    val = int(line.split()[0])
    pi[val] += 1

*#Divide the count of each class by total documents* 
**for** key **in** pi:
    pi[key] /= total

print("Probability of each class:")
print("**\n**".join("**{}**: **{}**".format(k, v) **for** k, v **in** pi.items()))

词汇的概率分布

让我们首先创建熊猫数据框架

*#Training data*
train_data = open('20news-bydate/matlab/train.data')
df = pd.read_csv(train_data, delimiter=' ', names=['docIdx', 'wordIdx', 'count'])

*#Training label*
label = []
train_label = open('/home/sadat/Downloads/HW2_210/20news-bydate/matlab/train.label')
lines = train_label.readlines()
**for** line **in** lines:
    label.append(int(line.split()[0]))

*#Increase label length to match docIdx*
docIdx = df['docIdx'].values
i = 0
new_label = []
**for** index **in** range(len(docIdx)-1):
    new_label.append(label[i])
    **if** docIdx[index] != docIdx[index+1]:
        i += 1
new_label.append(label[i]) *#for-loop ignores last value*

*#Add label column*
df['classIdx'] = new_label

df.head()

每类每个单词的概率

为了计算我们的概率,我们将找到给定类别中每个单词的平均值。

对于 j 类和单词 I,平均值由下式给出:

但是,由于一些单词的计数为 0,我们将使用 low 执行拉普拉斯平滑:

其中 V 是词汇表中所有单词的数组

*#Alpha value for smoothing*
a = 0.001

*#Calculate probability of each word based on class*
pb_ij = df.groupby(['classIdx','wordIdx'])
pb_j = df.groupby(['classIdx'])
Pr =  (pb_ij['count'].sum() + a) / (pb_j['count'].sum() + 16689)    

*#Unstack series*
Pr = Pr.unstack()

*#Replace NaN or columns with 0 as word count with a/(count+|V|+1)*
**for** c **in** range(1,21):
    Pr.loc[c,:] = Pr.loc[c,:].fillna(a/(pb_j['count'].sum()[c] + 16689))

*#Convert to dictionary for greater speed*
Pr_dict = Pr.to_dict()

Pr

停止言语

停用词是在每个文档中出现很多的词(例如介词和代词)。

*#Common stop words from online*
stop_words = [
"a", "about", "above", "across", "after", "afterwards", 
"again", "all", "almost", "alone", "along", "already", "also",    
"although", "always", "am", "among", "amongst", "amoungst", "amount", "an", "and", "another", "any", "anyhow", "anyone", "anything", "anyway", "anywhere", "are", "as", "at", "be", "became", "because", "become","becomes", "becoming", "been", "before", "behind", "being", "beside", "besides", "between", "beyond", "both", "but", "by","can", "cannot", "cant", "could", "couldnt", "de", "describe", "do", "done", "each", "eg", "either", "else", "enough", "etc", "even", "ever", "every", "everyone", "everything", "everywhere", "except", "few", "find","for","found", "four", "from", "further", "get", "give", "go", "had", "has", "hasnt", "have", "he", "hence", "her", "here", "hereafter", "hereby", "herein", "hereupon", "hers", "herself", "him", "himself", "his", "how", "however", "i", "ie", "if", "in", "indeed", "is", "it", "its", "itself", "keep", "least", "less", "ltd", "made", "many", "may", "me", "meanwhile", "might", "mine", "more", "moreover", "most", "mostly", "much", "must", "my", "myself", "name", "namely", "neither", "never", "nevertheless", "next","no", "nobody", "none", "noone", "nor", "not", "nothing", "now", "nowhere", "of", "off", "often", "on", "once", "one", "only", "onto", "or", "other", "others", "otherwise", "our", "ours", "ourselves", "out", "over", "own", "part","perhaps", "please", "put", "rather", "re", "same", "see", "seem", "seemed", "seeming", "seems", "she", "should","since", "sincere","so", "some", "somehow", "someone", "something", "sometime", "sometimes", "somewhere", "still", "such", "take","than", "that", "the", "their", "them", "themselves", "then", "thence", "there", "thereafter", "thereby", "therefore", "therein", "thereupon", "these", "they",
"this", "those", "though", "through", "throughout",
"thru", "thus", "to", "together", "too", "toward", "towards",
"under", "until", "up", "upon", "us",
"very", "was", "we", "well", "were", "what", "whatever", "when",
"whence", "whenever", "where", "whereafter", "whereas", "whereby",
"wherein", "whereupon", "wherever", "whether", "which", "while", 
"who", "whoever", "whom", "whose", "why", "will", "with",
"within", "without", "would", "yet", "you", "your", "yours", "yourself", "yourselves"
]

现在,让我们创建词汇数据框架

vocab = open('vocabulary.txt') 
vocab_df = pd.read_csv(vocab, names = ['word']) 
vocab_df = vocab_df.reset_index() 
vocab_df['index'] = vocab_df['index'].apply(**lambda** x: x+1) vocab_df.head()

获取词汇表中每个单词的计数并将停用词设置为 0:

*#Index of all words*
tot_list = set(vocab_df['index'])

*#Index of good words*
vocab_df = vocab_df[~vocab_df['word'].isin(stop_words)]
good_list = vocab_df['index'].tolist()
good_list = set(good_list)

*#Index of stop words*
bad_list = tot_list - good_list

*#Set all stop words to 0*
**for** bad **in** bad_list:
    **for** j **in** range(1,21):
        Pr_dict[j][bad] = a/(pb_j['count'].sum()[j] + 16689)

多项式朴素贝叶斯分类器

将 P 的概率分布与属于每个类别的文档的分数相结合。

对于类 j ,字频为 f 的字 i :

为了避免下溢,我们将使用对数总和:

一个问题是,如果一个词再次出现,它再次出现的概率会上升。为了平滑这一点,我们取频率的对数:

此外,为了将停用词考虑在内,我们将为每个词添加逆文档频率(IDF)权重:

尽管对于这个特定的用例,停用词已经被设置为 0,但还是添加了 IDF 实现来一般化该函数。

*#Calculate IDF* 
tot = len(df['docIdx'].unique()) 
pb_ij = df.groupby(['wordIdx']) 
IDF = np.log(tot/pb_ij['docIdx'].count()) 
IDF_dict = IDF.to_dict()**def** MNB(df, smooth = **False**, IDF = **False**):
    *'''*
 *Multinomial Naive Bayes classifier*
 *:param df [Pandas Dataframe]: Dataframe of data*
 *:param smooth [bool]: Apply Smoothing if True*
 *:param IDF [bool]: Apply Inverse Document Frequency if True*
 *:return predict [list]: Predicted class ID*
 *'''*
    *#Using dictionaries for greater speed*
    df_dict = df.to_dict()
    new_dict = {}
    prediction = []

    *#new_dict = {docIdx : {wordIdx: count},....}*
    **for** idx **in** range(len(df_dict['docIdx'])):
        docIdx = df_dict['docIdx'][idx]
        wordIdx = df_dict['wordIdx'][idx]
        count = df_dict['count'][idx]
        **try**: 
            new_dict[docIdx][wordIdx] = count 
        **except**:
            new_dict[df_dict['docIdx'][idx]] = {}
            new_dict[docIdx][wordIdx] = count

    *#Calculating the scores for each doc*
    **for** docIdx **in** range(1, len(new_dict)+1):
        score_dict = {}
        *#Creating a probability row for each class*
        **for** classIdx **in** range(1,21):
            score_dict[classIdx] = 1
            *#For each word:*
            **for** wordIdx **in** new_dict[docIdx]:
                *#Check for frequency smoothing*
                *#log(1+f)*log(Pr(i|j))*
                **if** smooth: 
                    **try**:
                        probability=Pr_dict[wordIdx][classIdx]         
                        power = np.log(1+ new_dict[docIdx][wordIdx])     
                        *#Check for IDF*
                        **if** IDF:
                            score_dict[classIdx]+=(
                               power*np.log(
                               probability*IDF_dict[wordIdx]))
                        **else**:
                            score_dict[classIdx]+=power*np.log(
                                                   probability)
                    **except**:
                        *#Missing V will have log(1+0)*log(a/16689)=0* 
                        score_dict[classIdx] += 0                        
                *#f*log(Pr(i|j))*
                **else**: 
                    **try**:
                        probability = Pr_dict[wordIdx][classIdx]        
                        power = new_dict[docIdx][wordIdx]               
                        score_dict[classIdx]+=power*np.log(
                                           probability) 
                        *#Check for IDF*
                        **if** IDF:
                            score_dict[classIdx]+= power*np.log(
                                   probability*IDF_dict[wordIdx]) 
                    **except**:
                        *#Missing V will have 0*log(a/16689) = 0*
                        score_dict[classIdx] += 0      
            *#Multiply final with pi* 
            score_dict[classIdx] +=  np.log(pi[classIdx])                          

        *#Get class with max probabilty for the given docIdx* 
        max_score = max(score_dict, key=score_dict.get)
        prediction.append(max_score)

    **return** prediction

比较平滑和 IDF 的效果:

regular_predict = MNB(df, smooth=**False**, IDF=**False**)
smooth_predict  = MNB(df, smooth=**True**, IDF=**False**)
tfidf_predict   = MNB(df, smooth=**False**, IDF=**True**)
all_predict     = MNB(df, smooth=**True**, IDF=**True**)*#Get list of labels*
train_label = pd.read_csv('20news-bydate/matlab/train.label',
                          names=['t'])
train_label= train_label['t'].tolist()total = len(train_label) 
models = [regular_predict, smooth_predict, 
          tfidf_predict, all_predict] 
strings = ['Regular', 'Smooth', 'IDF', 'Both'] 

**for** m,s **in** zip(models,strings):
    val = 0
    **for** i,j **in** zip(m, train_label):
        **if** i != j:
            val +=1
        **else**:
            **pass**   
    print(s,"Error:**\t\t**",val/total * 100, "%")

正如我们所看到的,IDF 几乎没有影响,因为我们删除了停用词。 然而,平滑使模型更加精确。

因此,我们的最佳模型是:

测试数据

现在我们有了模型,让我们用它来预测我们的测试数据。

*#Get test data*
test_data = open('20news-bydate/matlab/test.data')
df = pd.read_csv(test_data, delimiter=' ', names=['docIdx', 'wordIdx', 'count'])

*#Get list of labels*
test_label = pd.read_csv('/home/sadat/Downloads/HW2_210/20news-bydate/matlab/test.label', names=['t'])
test_label= test_label['t'].tolist()

*#MNB Calculation*
predict = MNB(df, smooth = **True**, IDF = **False**)

total = len(test_label)
val = 0
**for** i,j **in** zip(predict, test_label):
    **if** i == j:
        val +=1
    **else**:
        **pass**print("Error:**\t**",(1-(val/total)) * 100, "%")

使用 Clustal Omega 和 T-Coffee 的多序列比对

原文:towardsdatascience.com/multiple-se…

3 个或更多生物序列的序列比对

你想知道科学家如何识别三个或更多生物序列中的相似区域吗?正如我在上一篇文章中所描述的,序列比对是一种排列 DNA、RNA 或蛋白质序列以识别相似区域的方法。在我最近一篇关于生物信息学的文章中,我已经讨论了关于 两两序列比对 。一定要检查他们。多序列比对与成对序列比对非常相似,但它使用三个或更多个序列,而不是只有两个序列。

在本文中,我将带您完成多重序列比对。此外,我们将使用 Clustal OmegaT-Coffee 测试一些示例,这些示例将使用 Biopython 测试一些编码示例。

Figure 1: Results from T-Coffee

什么是多序列比对?

多序列比对(MSA) 中,我们试图比对 三个或三个以上相关序列 ,以达到它们之间的最大匹配。MSA 的目标是排列一组序列,使每个序列中尽可能多的字符根据某种评分函数进行匹配。

Figure 2: Image Source: openi.nlm.nih.gov/detailedres…

得分

MSA 的评分过程是根据某个评分矩阵,基于多重比对中所有可能的序列对的得分之和。你可以参考我的上一篇文章来了解不同的评分矩阵以及如何匹配。

多重比对得分= ∑得分(A,B)

其中 score(A,B)= A,B 的成对比对分数。

例子

Sequence 1:    **G   K   N**
Sequence 2:    **T   R   N**
Sequence 3:    **S   H   E**
Sum of pairs: **-1 + 1 + 6 = 6**

第二列的和= score (K,R) + score (R,H) + score (K,H) = 2+0+-1 = 1

MSA 的目标是达到的最大和。

多序列比对的类型

比对三个或更多个序列可能很困难,手动比对几乎总是很耗时。因此,使用计算算法来产生和分析这些比对。大多数 MSA 算法采用动态规划启发式方法。

下面给出了使用启发式方法的 MSA 技术。

  1. 渐进式排列结构
  2. 迭代比对构建
  3. 基于块的对齐

这些方法可以在所有可能的解决方案中找到解决方案,但它们不能保证找到最佳解决方案。因此它们被认为是近似值,但是我们可以很容易地在短时间内找到接近实际值的解。

渐进式线形施工

这种方法也被称为分层树形方法,是由 Paulien HogewegBen Hesper 于 1984 年开发的。它通过组合从最相似的配对开始并前进到最远相关的配对的成对比对来构建最终的 MSA

目前使用的两种流行的渐进对准方法是,

  1. Clustal Omega
  2. T-Coffee

迭代线形施工

该方法由一组产生MSA的方法组成,同时减少了渐进方法中固有的误差。它们的工作方式类似于渐进式方法,但会反复重新排列初始序列,并向不断增长的 MSA 添加新序列。

软件包 PRRN/PRRP 基于爬山算法优化其 MSA 比对分数。

基于块的对齐

这种方法将序列分成块,并试图识别许多序列共有的无缺口比对的块。

DIALIGN2 是一种流行的基于块的比对方法。

练习时间到了

你期待的时刻到了。是时候尝试一些工具和例子了。我将用 Clustal OmegaT-Coffee 向大家展示几个 MSA 的例子。你可以在网上试用这些工具。

Clustal 欧米茄

转到www.ebi.ac.uk/Tools/msa/c…

Figure 3: Clustal Omega

您将看到一个页面,选择数据类型(蛋白质、DNA 或 RNA),输入序列(或上传支持格式的文件)并设置输出格式。

我将用下面的 10 个棘冠海星**(俗称 棘冠海星 )的基因组序列(DNA)来做这个演示。你可以从 这里 下载一个生物体的完整基因组。fsa 格式。**

一个 FSA 文件(。fsa) 是由 DNA 测序仪和分析仪创建的片段分析数据文件。

10 sequences from the genome of Acanthaster planci (commonly known as Crown-of-thorns starfish)

输入序列并选择参数后,您可以提交任务。可以按如下方式查看作业的结果。您可以从 点击 查看该示例的结果。

Figure 4: Results of the job on Clustal Omega

您可以使用下载结果作为校准文件。aln 扩展名通过点击下载对齐文件按钮。

t-咖啡

tcoffee.crg.cat/apps/tcoffe…

Figure 5: T-Coffee

在本次演示中,我选择了 DNA 部分下的联合收割机常用对齐器(M-Coffee) 。然后你会看到一个页面来输入序列(或者上传一个支持格式的文件)。

Figure 6: M-Coffee input page

我将使用我用来演示 Clustal Omega 的同一个文件。输入序列后,您可以提交作业。可以按如下方式查看作业的结果。你可以从 这里 查看这个例子的结果。

Figure 7: Results for the job on T-Coffee

Clustal Omega 和 T-Coffee 的 Biopython 包装

Biopython ,我曾在我的上一篇文章中介绍过,它由用于 Clustal OmegaT-Coffee 和许多其他工具的命令行包装器组成,如 ClustalWdiaign**。您可以在这里 查看 中的所有包装器和示例代码。在下一个例子中,我将展示如何使用 Clustal Omega 包装器。**

要运行 Clustal Omega 包装器,首先您应该下载它的预编译二进制文件。你可以从 这里 下载。将下载一个二进制文件。您可以使用下面给出的命令使其成为可执行文件。根据您下载的二进制文件版本,二进制文件的名称可能会有所不同。在我的机器上,它被下载为clus tal-omega-1 . 2 . 3-ma cosx**。**

**chmod 777 clustal-omega-1.2.3-macosx**

我将使用相同的。以前使用的 fsa** 文件,对于这个例子也是如此。**

以下代码使用 Clustal Omega 包装器为给定输入开发 MSA 。fsa 文件。如果你有这种能力,那就容易了。fsa 文件,。py 文件和可执行二进制文件放在同一个位置。

运行完这段 python 代码后,您将得到一个命令作为输出。路径可能会根据您放置文件的位置而变化。

**clustalo -i /Users/vijinimallawaarachchi/Documents/Python/Acanthaster_planci_Gnomon.fsa -o aligned.fasta — auto -v**

Figure 8: Output command

现在用如下所示的命令执行下载的二进制文件。确保用替换离合器。/clus tal-omega-1 . 2 . 3-ma cosx****

**./clustal-omega-1.2.3-macosx -i /Users/vijinimallawaarachchi/Documents/Python/Acanthaster_planci_Gnomon.fsa -o aligned.fasta --auto -v**

您将会得到以下结果,表明已经进行了渐进式比对。

Figure 9: Final result

现在你可以看到一个名为 aligned.fasta 的文件已经在与你的文件相同的位置形成。一旦你打开它,你可以看到 FASTA 格式的排列。

****FASTA 格式是一种基于文本的格式,用于表示核苷酸序列或肽序列,其中核苷酸或氨基酸用单字母代码表示。该格式还允许序列名称和注释位于序列之前。该格式起源于 FASTA 软件包,但现在已经成为生物信息学领域的标准。

Figure 10: Output file in FASTA format

希望你喜欢读这篇文章,并学到一些有用和有趣的东西。

因为我对这个领域还很陌生,所以我想听听你的建议。😇

感谢阅读…😃

多任务学习:教你的人工智能更多,使之更好

原文:towardsdatascience.com/multitask-l…

bitesizebio.com/27766/multi…

大家好!今天,我想告诉你关于机器学习的话题,一方面,这是非常面向研究的,应该把机器学习算法带到更像人类的推理中,另一方面,这是我们从机器学习的基础中非常熟悉的,但很少被解释为我今天想要展示的。这被称为多任务学习,它(几乎)与上图中的多任务无关。在这篇文章中,我将展示什么是人类和算法的多任务学习,今天的研究人员如何应用这一概念,你如何用它来解决你的任何问题以提高你的模型的性能。最重要的是,我将为您提供源代码和 4 个用例的解释(从照片中识别情感,用加速度计数据识别运动,暹罗网络助推和解决数字挑战:全部使用多任务学习!),你可以用它作为你自己项目的模板(我希望是灵感)!

这篇文章的灵感来自于 Sebastian Ruder 和丰富的卡鲁阿纳资料。

如果想直接跳转到 Keras 中的代码,这里的就是对应的 GitHub repo。我也在数据科学 UA 会议上做了一个关于这个话题的演讲,幻灯片也即将上传。

我们的多任务处理

“一心多用”这个词本身通常意味着一些负面的东西——一个人试图做很多事情,但没有一件成功就是最好的例子。但在这里我想谈谈有点不同的“多任务处理”。我想想象一下,我们生物大脑的所有功能都是某种深度神经网络,它也经过反向传播训练,并给出一些标签作为输出。如果我这样想我的视觉系统,当我看东西时,它会输出什么?我不仅能识别物体,分割它们,还能理解场景。我还可以估计街上人们的情绪,他们的穿着,根据他们的穿着判断天气,我可以估计这是哪个国家甚至是哪个城市,以及许多其他重要的细节,这些都让我从视觉渠道获得了非常丰富的理解。

好吧,那呢?如果我听到任何人的声音,我会立即理解一个人的性别、音调,我理解单词、整个句子和意思,我知道语言,我理解所有的实体,甚至能够回答我听到的。

我可以用我的任何感觉系统做同样的练习——我总是从一个单一的“测试”例子中感受到很多东西,不管它是什么——一张图片、一个声音、一段文字甚至一种感觉。

机器的多任务处理

另一方面,现代神经网络(和其他机器学习算法)通常从单个例子中解决单个问题——它可以是分类、回归、结构化预测、异常检测甚至是对象生成,但通常,我们期望最终是单个事情。在这篇博客中,我想谈谈并展示我们如何让我们的模型学习更多的东西,我将从一个我们已经知道多年的多任务学习的例子开始:

Well-known L2 regularization for a loss function

你说得对,我们都知道这个著名的 L2 正则化公式。为什么我说是多任务学习的例子?因为我们同时解决了两个优化问题:损失函数最小化和使我们的参数 w 的范数更小。我们通常不会深入思考这个问题,但选择这个特定的第二优化函数背后有很多理论:

Different explanations of a regularization effect

例如,安德烈 吉洪诺夫主要对解决逆不适定问题感兴趣,通过参数范数添加正则化帮助他实现问题的平滑和良好调节。波兰数学家 Zaremba 将它引入统计学习理论,因为模型的复杂性非常小,因此我们将其最小化。从 Bayes 的的观点来看,这样我们就把我们的权重设定为某种特定的分布——这些是我们对参数的先验。当然,我们大多数人在一些课程中学习过它,我们并不真正担心它,但我们知道它可以防止我们的模型过度拟合:)

如你所见,在这些解释中,我们只考虑模型本身的参数。但是从我的直觉角度(以及我大脑中的神经网络)我想从推理的角度更具体地解释它。我可以添加一些考虑到问题的“真实的”、“类似人类的”背景的“正则化”吗?如果我想从照片中识别情绪,我应该限制权重以“知道”鼻子和嘴唇的运动吗?很可能是的。如果我想翻译一篇文章,知道给定单词的词性能对我的参数有帮助吗?我想会的。如果我正在处理信号处理问题,我是否希望我的模型能够对给定时间序列的过去和未来有一些直觉?可能会很有帮助!

ruder.io/multi-task/

所有这些“知道”,“调节”我可以作为一个额外的输入纳入机器学习算法,但自从我在这里开始谈论多任务学习…你现在明白我在领导什么了。如果算法参数的正则化这样的额外损失有助于更好的性能,为什么我们不尝试从人类逻辑的角度来看应该有助于性能的额外损失?然后,我们的算法将看起来像上面的图片:一个单一的输入,几个层(在神经网络的情况下)和许多输出,可以发挥一些超参数λ的正则化作用,或一个独立的目标,也希望优化和解决。

是的,除了多任务学习的“正规化”动机之外,我们只能承认,学习一个神经网络来同时解决 X 个问题,而不是拥有 X 个独立的神经网络,从简单的工程角度来看,这要酷得多。更好的性能、规范化和通用化是额外的收获。

动机用例

在开始深入细节之前,我想展示一些激励人心的例子。第一个是计算机视觉方面的惊人研究,他们不仅展示了单个神经网络如何同时解决 20 多项任务,而且还自动建立了 2D 和 3D 空间中不同任务的层次结构(这就是为什么它被称为 Taskonomy ),并显示了与将一项任务的学习转移到另一项任务相比,性能有所提高。这项工作是一个惊人的灵感,关于如何把一个单一图像的复杂理解纳入一个单一的算法。

[## 斯坦福大学

Taskonomy:解开任务迁移学习,CVPR 2018(最佳论文)。斯坦福大学伯克利分校。我们提议完全…

taskonomy.stanford.edu](taskonomy.stanford.edu/)

第二个很好的例子是自然语言处理:为什么我们不使用一个神经网络来解决情感分析、语义解析、翻译、回答问题、翻译单个句子呢?Salesforce 的研究人员也这么认为,并开发了他们自己的创造性解决方案。

[## decaNLP

深度学习显著提高了自然语言处理(NLP)任务的最新性能,但…

decanlp.com](decanlp.com)

在我负责机器学习的 Mawi Solutions 中,我们还将多任务学习的概念应用于实时心电图分析。在测量 ECG 期间,我们需要标记其形态结构以供进一步分析,估计信号质量,并在每秒相同的时间解决异常检测任务。我们可以在一部手机上同时运行三种不同的算法(不一定是机器学习算法),但我们成功地用一个单一的神经网络解决了它们,与不同方法的组合相比,这个神经网络明显更快、更准确。

Multitask learning for live ECG analysis in Mawi Solutions

作为“类人”行为的一个重要概念,多任务学习对于强化学习也非常重要。一个很好的例子可以是 DeepMind 的工作发狂:我们建议共享一个“提炼”的策略,捕捉跨任务的共同行为,而不是共享不同损失之间的参数。

Distral: Robust Multitask Reinforcement Learning

工作的理由

好吧,这一切都很酷,但仍然不太清楚它为什么工作。为什么添加不同的,甚至相近的任务可以帮助学习主要任务,或者为什么他们可以一起学习?

  1. **正则化:**附加损失原则上与不同研究者从正则化中得到的结果是一样的:它平滑了损失函数,最小化了模型的复杂性,并为模型提供了非常有用的先验信息。
  2. **表示偏差:**当你在几个任务的交集上训练你的模型时,你推动你的学习算法在交集上的较小表示区域而不是单个任务的较大区域上寻找解决方案。它导致更快更好的收敛。
  3. **特性选择仔细检查:**如果一个特性对于不止一个任务是重要的,那么很可能这个特性对于您的数据来说确实是非常重要和有代表性的
  4. **迁移学习:**机器学习已经从学习几项任务中受益,但顺序使用迁移学习:在一项任务的大型数据集上预先训练一个模型,然后使用获得的模型在其上训练另一项任务。经验结果表明,联合学习这些任务会更有益处,而且肯定会更快。
  5. **不能成为输入的输出:**这一刻对我个人来说是最有趣的。有一些特殊类型的数据,由于它们的顺序性质,受到过去观察的制约,通常我们需要处理它们:句子中的单词(必须预测下一个单词、帧和视频,必须预测下一帧,等等)。我们希望这些过去时刻的表示能够模拟未来的时刻——在这里,辅助任务如此自然地出现——过去的帧必须预测下一帧,而我们不能将这些帧用作输入!其他很好的例子是那些在测试/生产阶段很难或者很长而无法计算的特性,但是我们可以使用它们作为辅助损失函数来规范我们的模型,以便“了解”它们。

Predicting next frame in a video cant be a very informative prior: coxlab.github.io/prednet/

每个人的辅助任务

好吧,也许现在你或多或少地相信多任务学习很酷,对研究人员有用,背后有一些理论和经验动机。但是你可能会回答我,在你的项目中你并不真的需要它,因为你不需要同时解决几个任务,或者你只是没有数据集的额外标签,或者没有可能得到它们。在这一部分,我想展示一些辅助损失的例子,你们中的每一个人都可以在任何项目中使用,作为一个额外的正则项,这将提高你们的绩效。

  1. 自然语言处理您可以预测句子中的下一个单词,作为您希望模型拥有的先验知识。
    • NLTK:词性、句子树、NER——你确定你的深度学习不会从它们那里受益?如前所述,尝试来自 NLTKspacy 的基本 NLP 功能。 -de clalp:清晰的灵感:)
  2. 计算机视觉你在 OpenCVscikit-image 或者 dlib 里都有。
  3. 信号处理
  4. 一般建议 -自动编码器/生成式建模,因为模型推动任何表示尽可能最有用和最具描述性 -提示(预测重要特征,如计算机视觉中的 HOG、NLP 中的 NER 和 DSP 中的熵)

关于可重复性研究的一个注记

在展示如何实现多任务学习之前,我想展示我必须做些什么来使我在 Keras 中的代码至少在某种程度上可以在另一台计算机上重现(但这仍然不够,正如我在基辅的工作室所展示的那样)。首先,我必须修复所有随机种子:

random.seed(42)
np.random.seed(42)
tf.set_random_seed(42)

修复神经网络层的初始化器并运行会话:

my_init = initializers.glorot_uniform(seed=42)session_conf = tf.ConfigProto(intra_op_parallelism_threads=1,
                              inter_op_parallelism_threads=1)
sess = tf.Session(graph=tf.get_default_graph(), config=session_conf)
K.set_session(sess)

并在创建数据集时修复随机种子:

train_test_split(X, Y1, Y2, Y3, random_state = 42)

甚至在训练一个模型时设置“shuffle = False”。此外,我将模型和训练条件的所有超参数固定为时期数、优化器和批量大小。但是这还不够。在某些电脑上(我在 MacBook Air 上运行我的代码),结果与我的略有不同。我只能这样解释(感谢听觉的提示):不同的硬件导致不同的浮点数错误,从而导致不同 CPU 上的优化过程略有不同。我想知道是否有办法克服这一点(我正在考虑在每个训练过程之前重新初始化随机种子),并非常感谢任何提示。

练习 1:情绪识别

正如我所承诺的,本文将有几个代码示例,因此您可以尝试自己进行多任务学习(主要集中在使用附加任务作为正则项)。第一个例子与计算机视觉有关,特别是与数据集有关(数据集不是免费分发的,但您可以出于研究目的请求访问):

[## 匹兹堡的情感分析小组

编辑描述

www.pitt.edu](www.pitt.edu/~emotion/ck…)

我的完整代码在这里:

[## 拉赫诺格/教育

我的讲座和机器学习自学材料- Rachnog/education

github.com](github.com/Rachnog/edu…)

该数据集由不同人的图像和相应的标签组成:

  • 他们脸上表达的情感
  • 面部动作单元(后来的 FAU,见更多信息这里
  • 面部关键点

我们将使用一个非常简单的神经网络(与最先进的网络相比)作为主要任务的情感识别,并将尝试调整 FAU 和关键点检测作为正则化。这是一个我们将尝试用多任务学习来增强的神经网络。如你所见,2018 深度学习时代我们很容易称之为“浅”:

visible = Input(shape=input_shape)
x = Conv2D(10, kernel_size=3, activation='elu', padding='same', kernel_initializer=my_init)(visible)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(20, kernel_size=3, activation='elu', padding='same', kernel_initializer=my_init)(x)
x = MaxPooling2D(pool_size=(2, 2))(x)
x = Conv2D(30, kernel_size=3, activation='elu', padding='same', kernel_initializer=my_init)(x)
x = GlobalMaxPooling2D()(x)
output = Dense(Y_train.shape[1], activation='softmax', kernel_initializer=my_init)(x)
model = Model(inputs=visible, outputs=output)

它显示了以下结果(当然这并不令人满意):

precision    recall  f1-score   support

          0       0.39      0.56      0.46       149
          1       0.00      0.00      0.00        10
          2       0.00      0.00      0.00        71
          3       0.32      0.11      0.16        74
          4       0.47      0.64      0.54       163
          5       0.44      0.11      0.17        64
          6       0.38      0.54      0.44       130

avg / total       0.36      0.41      0.36       661

接下来,我为一个必须预测面部动作单元和情绪的模型添加了第二个输出:

output2 = Dense(Y_train2.shape[1], activation='sigmoid', name = 'facs', kernel_initializer=my_init)(x)

而且成绩变得稍微好一点!

precision    recall  f1-score   support

          0       0.58      0.36      0.44       149
          1       0.00      0.00      0.00        10
          2       0.47      0.27      0.34        71
          3       0.36      0.65      0.46        74
          4       0.56      0.83      0.67       163
          5       0.56      0.08      0.14        64
          6       0.62      0.68      0.65       130

avg / total       0.53      0.53      0.49       661

好吧,如果这个辅助损失有帮助,也许预测关键点也可以很好?至少它的表现也比基线要好:

precision    recall  f1-score   support

          0       0.69      0.34      0.45       149
          1       0.00      0.00      0.00        10
          2       0.71      0.07      0.13        71
          3       0.38      0.65      0.48        74
          4       0.52      0.88      0.65       163
          5       0.50      0.05      0.09        64
          6       0.53      0.72      0.61       130

avg / total       0.56      0.52      0.46       661

好的,看起来现在我有两个辅助损失,它们都很好地规范了我的基线解,所以我想把它们结合起来,我希望得到更好的结果。我会用一种“聪明”的方式来做这件事。我知道,当我(作为一个人)分解我自己的情绪识别时,我首先看到关键点,在我将它们组合成行动单元之后,只有在最后,我才能从这个特征层次中理解情绪。就神经网络而言,这可能意味着我应该将 FAU 损失附加到第一卷积层,将关键点损失附加到第二卷积层,并将主要损失留在最后:

visible = Input(shape=input_shape)
x1 = Conv2D(10, kernel_size=3, activation='elu', padding='same', kernel_initializer=my_init)(visible)
x1 = MaxPooling2D(pool_size=(2, 2))(x1)
x2 = Conv2D(20, kernel_size=3, activation='elu', padding='same', kernel_initializer=my_init)(x1)
x2 = MaxPooling2D(pool_size=(2, 2))(x2)
x3 = Conv2D(30, kernel_size=3, activation='elu', padding='same', kernel_initializer=my_init)(x2)
x = GlobalMaxPooling2D()(x3)output = Dense(Y_train.shape[1], activation='softmax', name = 'emotion', kernel_initializer=my_init)(x)
output2 = Dense(Y_train2.shape[1], activation='sigmoid', kernel_initializer=my_init)(GlobalMaxPooling2D()(x2))
output3 = Dense(Y_train3.shape[1], activation='linear', kernel_initializer=my_init)(GlobalMaxPooling2D()(x1))model = Model(inputs=visible, outputs=[output, output2, output3])

为了避免“杀死”较低层主损失函数的梯度,我为第二层和第一层的损失 0.1 添加了λs:

model.compile(loss=['categorical_crossentropy', 'binary_crossentropy', 'mse'],
              optimizer=Adam(clipnorm = 1.), metrics = {'emotion': 'accuracy'}, loss_weights = [1, 1e-1, 1e-1])

我们为同样的 10 个纪元训练…然后…瞧!

precision    recall  f1-score   support

          0       0.75      0.56      0.64       149
          1       0.00      0.00      0.00        10
          2       0.79      0.27      0.40        71
          3       0.45      0.80      0.58        74
          4       0.67      0.88      0.76       163
          5       0.64      0.14      0.23        64
          6       0.61      0.78      0.68       130

avg / total       0.65      0.63      0.60       661

我们可以将我们的结果从 0.36 F1 分提高到 0.60 F1 分,只需以一种巧妙的方式使用额外的损失函数。同样的简单 convnet,同样的初始化器,同样的数据,同样的训练过程。看起来像魔术?那么让我们检查下一个例子。

练习 2:加速度计运动分析

你可以告诉我,通常情况下,除了主要损失之外,你没有像面部动作单位这样好的附加功能。没关系,现在我给你看一个任务的例子,你可以自己创造这些损失。该数据集是关于通过腕戴式加速度计对活动进行分类的:

https://archive . ics . UCI . edu/ml/datasets/Dataset+for+ADL+Recognition+with+腕式+加速度计

这是我解决这个问题的完整代码:

[## 拉赫诺格/教育

我的讲座和机器学习自学材料- Rachnog/education

github.com](github.com/Rachnog/edu…)

我的输入是加速度计的三个轴的多元时间序列,输出是 21 个活动类之一。没有附加额外的损失。我现在该怎么办?当然,创造一些!我选择了我认为合理的损失:

  • 给定时间序列的标准偏差
  • 时间序列的绝对变化之和
  • 傅立叶系数。

我有一个假设,如果我的神经网络知道这些特征中的一个,它会比没有表现得更好。我首先用一个简单的 1D 卷积神经网络检查基线解决方案:

inn = Input(shape = (X_train.shape[1], X_train.shape[2], ))

x = Conv1D(16, 5, activation='relu', kernel_initializer=my_init)(inn)
x = MaxPooling1D(5)(x)
x = Conv1D(32, 5, activation='relu', kernel_initializer=my_init)(x)
x = MaxPooling1D(5)(x)
x = Conv1D(64, 5, activation='relu', kernel_initializer=my_init)(x)
x = GlobalMaxPooling1D()(x)
out = Dense(Y_test.shape[1], activation = 'softmax', kernel_initializer=my_init)(x)

model = Model(inputs=[inn], outputs=[out])

model.compile(loss='categorical_crossentropy',
              metrics = ['accuracy'], optimizer = Adam(clipnorm = 1.))

并得到如下精确回忆 F1:

avg / total       0.61      0.57      0.54       245

加上标准差损失怎么样?

avg / total       0.61      0.60      0.57       245

又用了一个的变化总和

avg / total       0.57      0.60      0.57       245

好吧,他们都没多大帮助,但是傅立叶肯定是一个强有力的镜头…

avg / total       0.60      0.62      0.59       245

似乎我们可以将基线提高 5% ,但这也是一个不错的结果!我们经常使用不同的巧妙方法来争取这 5%的份额,所以现在你又多了一个

练习 3:加强暹罗网络

暹罗神经网络是一类特殊的模型,旨在在一个新的嵌入空间中比较对象:相似的对象必须彼此靠近(距离小)并且不同——远离(距离大)。为两幅 64x64 的图像计算欧几里德距离(在 MNIST 数据集的情况下)并不是一个明智的想法,但是我们可以将这些图像嵌入到一些向量空间中,这样做是有意义的。这一系列模型的主要特点是具有两个输入和在这些输入之间共享的层权重,以允许交换性(因为我们基本上计算两个对象之间的距离)。在本例中,我将展示向这些图层“袖子”中的每一个添加额外损失将如何提高 MNIST 数据集的性能。完整代码在这里:

[## 拉赫诺格/教育

我的讲座和机器学习自学材料- Rachnog/education

github.com](github.com/Rachnog/edu…)

首先,我们为每个输入设置了一个编码器,如下所示:

input = Input(shape=input_shape)
x = Flatten()(input)
x = Dense(64, activation='relu')(x)
x = Dropout(0.1)(x)
m = Model(input, x)

如您所见,我们将输入图像嵌入某个 64 维空间,在那里我们可以比较它们,损失旨在最小化相同数量图像之间的距离,最大化不同数量图像之间的距离:

def contrastive_loss(y_true, y_pred):
    margin = 1
    sqaure_pred = K.square(y_pred)
    margin_square = K.square(K.maximum(margin - y_pred, 0))
    return K.mean(y_true * sqaure_pred + (1 - y_true) * margin_square)

我有一个假设,在这个 64 维嵌入空间中,我不仅可以比较图像,还可以对它们进行分类。**所以我的第二个损失将被简单分类成 10 位数的类别。**训练基线暹罗网络并将其作为分类器进行测试,结果如下:

* Accuracy on training set: 85.47%
* Accuracy on test set: 85.61%

伴随着一个附加损失:

* Accuracy on training set: 88.49%
* Accuracy on test set: 88.54%

就是这样。:)

练习 4:数字财务预测

我觉得这个博客已经太长了,但是不加上最后一个和财务预测有关的例子太有诱惑力了。numeri是一项关于加密金融数据的数据科学挑战,你已经为自己准备好了一切,剩下的就是——预测五个独立变量的 0 或 1,并且不要过度拟合训练数据。因为这里有几个目标是从数据中自然产生的(我知道多任务学习可以防止过度适应),所以我决定尝试一下多任务。你可以在这里查看全部代码:

[## 拉赫诺格/教育

我的讲座和机器学习自学材料- Rachnog/education

github.com](github.com/Rachnog/edu…)

在这种情况下,我的额外损失不是辅助的,但它们都是重要的。所以,我像下面这样建立我的神经网络:

inputs = Input(shape=(50,))
c = Dense(100, activation='relu')(inputs)
c = Dropout(0.1)(c) predictions_target_bernie = Dense(1, activation='sigmoid', name = 'target_bernie')(c)
predictions_target_charles = Dense(1, activation='sigmoid', name = 'target_charles')(c)
predictions_target_elizabeth = Dense(1, activation='sigmoid', name = 'target_elizabeth')(c)
predictions_target_jordan = Dense(1, activation='sigmoid', name = 'target_jordan')(c)
predictions_target_ken = Dense(1, activation='sigmoid', name = 'target_ken')(c)

用相等的λs:

model.compile(loss='binary_crossentropy',               optimizer=Adam(lr = 0.0001), 
loss_weights = [0.2, 0.2, 0.2, 0.2, 0.2])

这种模型允许在实时财务数据上超过基准15 次,并且仍在计算。我认为这是一个不错的结果,我很高兴与你们分享。

9/15 on Numerai with multitask learning

结论

我知道所有这些材料可能有点让人不知所措,但别担心。我试图展示的一切可以被压缩成三个主要结论:

  1. 多任务学习对人类来说是正常的
  2. 多任务学习对于机器学习来说是正常的,而且,我们已经做了几十年了
  3. 下次你看到你过度拟合或没有从你的机器学习模型中获得最大收益,是时候思考了——也许你不需要更多的数据,但你需要更多的损失?

此外,我们回顾了一些关于多任务学习的实际用例,并学习了如何在 Keras 中对其进行编码,如何使用辅助损失并为其选择权重(至少在某些情况下)。我希望这篇博文对你有用,并且你会使用多任务学习的概念在你当前的项目中获得更好的结果!

附言 如果你觉得这个内容很有用,很有观点,你可以在 Bitclout 上支持我。关注我还可以在脸书上看到太短的人工智能文章,在 Instagram 上看到个人资料,在 Linkedin 上看到!

基于 ipyvolume 的 Jupyter 多体绘制:跨语言三维可视化

原文:towardsdatascience.com/multivolume…

Jupyter 笔记本正在成为许多领域中数据科学的标准环境,随之而来的是可视化的需求。二维可视化可以说是最重要的,并且有丰富的库可供选择。其中许多都建立在 Python 世界中可视化的主力工具之上:Matplotlib。其他一些,如 plotly散景bqplot 通过提供完全交互式的情节更好地利用浏览器,能够以高帧率和平滑过渡进行缩放、平移和选择。

尽管 3D 可视化不经常使用,但有时理解内在的 3D 数据集(例如,脑部扫描)或 2D 投影难以理解的复杂结构是必不可少的。

Transparency in 2d, not a problem. Here showing a million points in bqplot (an open PR).

然而,三维可视化是困难的。虽然 2D 的透明度微不足道;它只需要混合操作,几乎不可能以可接受的帧率在 3D 中正确完成。事实上,这是一个活跃的研究领域。

对于 2D 的大型数据集,绘制每个单独的点没有意义。相反,使用数据的统计更有意义。datashader 和 vaex 采用的方法是将数据简化为 2d 直方图(或任何其他统计数据),并将其可视化为热图。

Showing 150 million taxi pickup locations in NYC by showing a heat map instead of individual points, using vaex with bqplot

体绘制

同样的技术可以用在 3D 中,除了 3D 立方体的渲染技术更加困难:它使用体积渲染,更具体地说是 v 体积光线投射。使用这种技术,光线会针对场景中的每个像素投射到场景中,并累积 3d 体积立方体中每个像素的 RGB 和 alpha 值,然后将它们混合在一起。

(left) Big data: exploring 100+ million rows by volume rendering a 3d histogram. (middle) Astronomical data cube: Radio observations. (right): Medical data cube: Scan of a male head.

一些数据集本质上是体积立方体。在射电天文学中,两个轴是天空坐标,第三个轴是频率轴,形成(通常)发射的 3d 强度立方体。在医学成像中,三个轴通常只是空间维度。

多体绘制

有时,需要在同一个场景中渲染多个大型数据集或多个数据立方体。它们可以重叠、完全重叠、部分重叠或完全不重叠。让事情变得更加复杂的是,一种称为最大强度投影的不同体绘制技术以不同的方式工作,这使得在同一场景中组合它们变得不同。事实上,我认为这使得多体积渲染至少和 3D 透明技术一样困难。

Glue-Jupyter uses ipyvolume for 3D rendering and also provides a richer UI and higher level data bookkeeping.

胶水对胶水-Jupyter

Glue 是一个用于多维链接数据探索的桌面应用程序,并在其 3D 可视化中使用多体积渲染,例如,可视化 3D 选择(如上面的截屏所示)。 Glue-jupyter (我正在进行的一个项目)旨在将 glue 引入 jupyter 笔记本。因此,它需要一个在 Jupyter 笔记本中进行多体积渲染的解决方案。Glue-jupyter 仍处于早期开发阶段,但已经提供了一种简单的现代方法来交互式地探索(多个)数据集,同时提供了从笔记本进行编程访问的功能。

Ipyvolume

Ipyvolume 是 Jupyter 笔记本最好的 3D 可视化软件包(免责声明:我是主要作者;).使用 ipyvolume,您可以在一个场景中进行散点图、颤动图和多体积渲染,只需几行代码,这并不容易!

Simple example showing volshow, scatter and quiver.

此外,ipyvolume 构建在 ipywidgets (前端部分的 Jupyter 小部件)之上,为您提供它开箱即用的所有功能。示例渲染 live 在文档中,绘图很容易嵌入到静态 HTML 文件中,能够在前端(浏览器)或内核端(Python 进程)轻松地将属性链接在一起,并监听属性的任何更改(双向通信的副产品)。此外,ipyvolume 重用了pytreejs,免费公开了大部分的 threejs API!使用 ipywebrtc ,我们可以录制电影,将它们传输到远程计算机或拍摄快照。

Multivolume rendering: male head scan and dark matter particle simulation in one scene.

从版本 0.5 开始, ipyvolume 支持多体积渲染,允许您可视化两个相互叠加的数据集。在左边的例子中,我们展示了一个人头部的扫描,同时展示了暗物质模拟中粒子的 3D 直方图。任意数量的数据立方体可以放在同一个场景中,这是 Jupyter 生态系统中可视化的一大壮举!据我所知,它是第一个为 Jupyter 做多体渲染的包。

大型数据立方体呢?

如果您正在使用远程 Jupyter 笔记本,可能使用 Jupyter Hub ,您将拥有两个世界的优势:您的代码接近数据,可视化在您的笔记本电脑/台式机上是本地的。然而,这意味着数据需要传输到客户机/浏览器,对于大型数据立方体来说,这可能相当大(是的,任何 3 次方的东西通常都很大)。为了解决这个问题,ipyvolume 将在默认情况下向浏览器发送低分辨率数据立方体。如果放大,会检测到边界框坐标的变化(yay ipywidgets!),并且放大的更高分辨率剪切版本将被发送到浏览器。

After zooming in, a new high-resolution cutout will be sent to the browser.

跨语言

乐趣还不止于此,因为 ipyvolume 的大部分代码都是在浏览器中运行的前端代码(JavaScript ),所以我们可以将它用于其他语言。两个适马的 BeakerX 团队已经展示了它可以在所有 JVM 语言中使用(Java,Clojure,Groovy,Scala 等等)。

现在和 QuantStack 团队一起,我们正在构建 xvolume ,一个绑定到 ipyvolume 前端代码的 C++程序(是的,我应该把它重命名为 jupyter-volume,对吗?).

这意味着,通过一个单一的代码库(加上一些每种语言的胶水),我们可以在 Jupyter 笔记本上为许多语言提供一个严肃的 3D 可视化包( ipyvolume )。

TL;灾难恢复版本/结论

从 ipyvolume 0.5 开始,我们为 Jupyter 生态系统提供了一个严肃的 3D 可视化包,它甚至可以使用混合渲染技术进行多体渲染,结合常规网格、散点和颤动图。重用前端代码,作为一个 Jupyter 小部件,我们可以在所有 JVM 语言和 C++中重用这个库。

特别感谢Casper van leeuw en以及所有其他为此 0.5 版本做出贡献的人!

一个可怕的数据故事的成分是什么?

原文:towardsdatascience.com/murdering-a…

Photo by Caleb Woods on Unsplash

忽视图形的语法甚至会破坏传说中的数据可视化

“狮子是属于猫科的哺乳动物”“吃是摄取食物为一个有机体提供能量”“长颈鹿是现存最高的动物”。

上面这句话有什么意义吗?写狮子的饮食习惯时,我强迫自己使用短语或句子,而不是传统的方式。同一个句子自然会变成:

“狮子吃长颈鹿”

这很简洁,也更有意义。我们对任何语言的这种造句方式都习以为常,以至于在日常交流中,我们认为这是理所当然的。但是,为什么数据消费应该有所不同呢?

为什么我们要人为地使用单片图表来限制交流呢?在展示分析见解时,数据科学从业者会想到模板化的仪表盘和现成的图表。销售趋势变成顶部的*‘KPI 部分’*中的条形图,而产品组合是下面的饼图,以此类推。

这就像使用预设的句子,而不是将正确的单词串在一起,来传达一个优雅的信息。不幸的是,这种做法在今天太普遍了。每次出现这种情况,一个信息设计师的心都在滴血。

还不信服?

以防你还在疑惑,让我们来做一个有趣的实验。我们将选择一个优雅的视觉,被广泛认为是有史以来最好的。然后我们会发现如果我们使用模板化的方法来呈现完全相同的数据会发生什么。

让我们以查尔斯·密纳德创作的《T2 拿破仑的俄罗斯战役》来做这个测试。这是一个经典的,永恒的可视化,被爱德华·塔夫特认为是有史以来最好的可视化。这张 1869 年手绘的图是通过自由地让数据讲述自己的故事,以正确的方式组成的。有了这次审判,我希望密纳德在九泉之下也不会翻身!

我首先选择了下面提供的数据。这是利兰·威尔金森从视觉上重新创造的,并发表在他的中。下面有三个数据集:第一个显示了拿破仑军队走过的城市,以及它们的纬度。

第二组显示了引用日期的经度和温度。这突出了军队撤退期间的严冬。第三个数据集显示了每个纬度上的士兵数量,他们行进的方向(前进或后退),以及这是主要的队伍,还是分散的队伍。

现在,让我们假设这些数据是从竞选前线用电子邮件发给我们的。然后,我们的经理给我们布置了一项任务,要求我们连夜创建一个可视化效果。一个直接的冲动是将它输入公司的仪表板装配线。数据从传送带的一端传入,机器人手臂使用预设的仪表盘布局模型和现成的图表来强制调整它们。从另一端出来一个闪亮的,互动的,彩色的垃圾。嗯,差不多了。

我试着用一种类似上面的粗糙的模板化方法来处理“*拿破仑的进行曲”。*让我们看看同样的数据是如何失去所有的优雅,并以使用预建图表的企业风格的仪表板结束的。以下是最终结果:

How we killed Charles Minard’s storytelling using the modern dashboarding assembly line

我们已经成功地摧毁了叙事,传奇的数据故事已经沦为一个琐碎的,无效的仪表板。我使用 Tableau public 将这些放在一起,但作为一个强烈的免责声明,问题不在于工具。Tableau 是一个很好的工具,市场上的许多其他工具也是如此。问题总是在于采用的方法和创作者缺乏想象力的处理。

图形的语法?

是的,图形确实有语法。选择合适的底层元素来构成优雅的视觉效果是可能的。我们不需要摸索僵化的、预先构建的图表。当我们拥抱这些信息设计的关键实体时,它赋予我们构建任何视觉的能力。

依靠 Leland Wilkinson 在他的书《图形的语法》中建立的优秀基础,我们将理解优雅图形的流体结构。通过一个简单的例子,我们将看到如何用数据元素一层一层地构建一个优秀的视觉效果。我们还将证明并非所有图表都需要标准名称。

语法使语言富有表现力。一种只有单词而没有语法的语言只能表达和单词一样多的思想。—利兰·威尔金森

英语语法什么管用?

为了快速了解上下文,让我们看看我们是如何在英语中直观地构造句子的。约翰在操场上的动作是通过引入不同的词类并把它们串在一起来传达的。

任何简单的措辞都会完全改变结构。例如,如果我们把最后两个单词和第一个互换,这个句子就变成了*“球击中了约翰”*。一个化妆品的变化,但结果是不太一样了!

介绍图形的语法

为了使图形或视觉表现具有表现力,我们必须理解它们的基本语法结构。《图形语法》提供了一套标准的指导方针,用于将数据转换成讲述其故事的有效可视化形式。

让我们假设我们有下面的数据要呈现。它显示了美国 6 个城市的销售业绩。

图形语法中有 7 种语法成分。让我们从底层开始逐一查看,并向上移动。这个概念最好用例子来说明。我们将使用 ggplot2 ,这是 R 上的一个高级图表包,也是受同一本书的启发。

如果你不懂代码,不用担心。下面显示的代码片段仅用于说明目的。一个人不需要知道编程就能跟上。只要扫一眼标签,就可以看到当每个单词被递增添加时,视觉效果是如何变化的。这只需要简单的英语理解。

组件 1–2–3:数据-美学-几何

数据是基础组件,带有要绘制的元素。美学为数据提供轴和编码元素,而几何保存可用于表示数据的形状。

下面是一个简单的命令,使用上面显示的 3 个组件绘制每个城市的销售额和价格。注意每一个是如何被显式调用的, 数据 被映射到输入数据帧, 美学 将列关联到 x-y 轴,而 几何 要求将形状显示为点。

ggplot( 数据AES(x =价格,y =销售额))+ geom _point()

不,这不是创建散点图的语法。我们将看到如何通过编码更多的元素来处理这 3 个组件。现在让我们根据城市所属的区域给点着色(左图)。然后,我们通过将销售量显示为点的大小来区分城市(右图)。请注意,该命令只添加了两项内容,如下所述。

ggplot(data,AES(x =价格,y =销售额,color =地区size =体积)+geom _ point()

构成部分 4:方面

我们现在添加第四个组件,称为“刻面”。顾名思义,这是用来通过创建支线剧情将刻面出来的。有时,并排拆分和比较图是有帮助的,以便更清楚地突出差异。

对于上面的同一条命令,我们要求根据*‘区域’*拆分视觉效果,而不是在单个图表中显示所有内容。这需要一个简单的加法,如下所示:

ggplot(data,aes(x=Price,y=Sales,color=Region,size = Volume))+geom _ point()+facet _ wrap(~ Region)

构成部分 5:统计

第五个组成部分是“统计”,它提供了一种引入统计模型和汇总的方法,如均值、中值、分布。显示基本的统计数据通常很有用。

假设我们想要计算每个价格点的平均销售额。我们可以通过在命令中再添加一个参数来动态地添加这一点。这导致具有相同价格点的城市被聚合。

ggplot(data,AES(x =价格,y =销售额))+stat _ summary _ bin(fun . y =" mean ",geom = "bar ")

构成部分 6:坐标

我们可能需要改变绘图的坐标系统。可以修改上面显示的默认笛卡尔坐标或 x-y 坐标图。我们可以将其转换为极坐标,这是(不)流行的饼图或圆环图的基础。

一个带有直观命名的命令的一个单独的添加就转换了整个视觉,而不必修改任何基本组件。尽管这种视觉效果不太适合我们的数据,但它展示了如何做到这一点。下图是*“蜘蛛或雷达图”“圆形图上的气泡”*的变体吗?我们已经在发明表象了!

ggplot(data,aes(x=Price,y=Sales,color=Region,size = Volume))+geom _ point()+facet _ wrap(~ Region)+coord _ polar()

构成部分 7:主题

语法中的最后一个组件是“主题”,它可用于任何非数据墨迹。示例包括图表或轴标题标签背景颜色方案等。在这一层,可以通过混合非数据墨水和数据墨水来对故事进行注释。

与其他组件一样,在下面添加一个参数*‘theme _ bw’*会将前景-背景从之前的默认灰度转换为白底黑字主题。添加标题、标签、页边距或线条也有同样简单的方法。

ggplot(data,AES(x =价格,y =销售额,color =地区,size =体积))+geom _ point()+theme _ bw()

因此,我们已经看到了图形语法如何帮助无缝地将数据组合到最合适的元素上。这些组件一起形成一个层,一个地块可能有多个层交织在一起。

如果意图是比较两个产品的销售,将它们绘制为条形 几何长度 美观 。如果你想看看这些产品的增长如何变化,把这个作为宽度 美观 带进来。不,请不要想条形图!相反,想象一下你如何能让数据发光。

想看看这些产品的利润吗?将它们编码为**。想比较不同公司的产品吗? Facet 剧情将视图并排拆分,轻松对比两家公司。在与用户共享之前,使用 主题 组件添加必要的文本。**

思考图表的问题是,随着需求的增加,思考过程总是停滞不前。一个只用僵硬的图表工作的头脑很快就会耗尽多才多艺的表现。

摘要

Grammar of Graphics: A layered approach to elegant visuals

我们已经了解了灵活表示数据的基本构件。这个概念的真正力量在于将数据从单一图表的局限中解放出来。给他们自由,让他们讲述自己富有表现力的故事。

尽管今天的许多可视化工具没有完全采用图形方法的语法,但这似乎是前进的方向。与此同时,人们有机会开始将此付诸实践。这一点非常重要,必须成为所有数据工作者的必修课,无论是数据翻译、分析师、设计师、数据科学家还是记者。

你使用一套固定图表的经验是什么?

如果你觉得这很有趣,你会喜欢我写的这些相关文章

对数据科学充满热情?随意在LinkedIn上加我,订阅我的 简讯

文章参考:

  1. 利兰·威尔金森的《图形语法》
  2. Jacques Bertin 的书名为“图形符号学:图表、网络、地图
  3. ggplot2 上的 Wilke 实验室课程:讲座 3-2017 年春季
  4. 用于 R 中交互图形的 GGPlot2
  5. Bret Victor 在斯坦福大学举办的名为“绘制动态可视化的人机交互研讨会,讨论了如何设计一个使用数据驱动可视化的系统。

通过人类选择的音乐

原文:towardsdatascience.com/music-by-me…

深度学习遇上交互式进化计算

One of the examples from the paper discussed (shoe photos on this post are from the UT Zappos50K dataset)

深度生成模型的一个更有趣的问题是,模型如何在生成过程中考虑用户偏好?控制一个模型的输出可以通过输入一个条件来完成,但是样本本身目前并没有通过考虑用户的主观偏好并产生用户特别喜欢的样本而在任何有意义的意义上有机地“进化”。

能够做到这一点的模型将在广泛的创造性应用中非常有用,从产品设计和资产生成到绘画和音乐。一月份发布的一篇论文“深度互动进化”很好地解决了这个问题,这也是这篇文章将要讨论的内容。

遗传算法

我们理想中想要的系统,是一个从一批完全随机的样本开始,并要求用户 选择 他们喜欢的样本,一个带有他们最终想要的输出的一些属性的样本。基于所选样本,该模型生成更多样本,这些样本具有与所选样本相似的特征。重复该过程,直到产生具有所有期望属性的样本。

很明显,我们正在执行一个优化过程,在每个时间步生成更新、更好的样本。有趣的是,奖励/适应度函数(衡量一个样本有多“好”的函数)不是一个可微的数学函数。是你。您选择的选项可以简单地表示为 1 和 0 的向量,分别代表好的和坏的样本。

这种适合度函数的公式非常有用,因为它使我们不必定义(难以处理的)适合度函数来预测用户喜欢哪些样本。我们只是直接把控制权交给用户。然而,由于输出离散数字向量的函数显然是不可微的,所以我们不能在这里使用反向传播。

一类自然适用的优化方法是 遗传算法【2】。目前,我们需要知道的是,它们的工作原理是将最佳样本的特征相结合,以产生更好的样本(交叉),同时向特征添加一点随机噪声,以探索特征的变化(突变)。

样本不断“进化”以具有更好的特征,直到找到一个具有所有期望特征的样本。这种使用遗传优化来响应用户输入的方法被称为交互式进化计算(IEC)【3】

什么是特色?

所以我们现在有一种方法可以进化我们的样本,但我们仍然有一个问题:什么是特征?我们可以简单地将照片中的每一个像素定义为独一无二的特征。现在,我们要做的就是运行遗传算法,我们应该会得到很好的结果,对吗?

正如您所看到的,这种幼稚的方法几乎马上就会遇到问题。随机选取像素而不是不仅不能给我们想要的真实图像,而且也不能给我们真实图像。

优化潜在向量

遗传算法的一个基本要求是用来表示信息的特征是独立的,或者至多是弱相关的。这使得特征可以被独立地组合和变异,并且仍然有希望获得离原始数据分布不太远的输出,也就是说,不太不切实际。

然而,对于大多数数据类型来说,不管领域(图像、文本、声音), raw 特征往往彼此之间有很强的相关性。你不能随意优化一个特征,因为它是否真实强烈地依赖于它的邻居。

例如,拍摄一张树叶的照片,并从中选取任意三个相邻的像素。几乎可以肯定,三个像素的颜色都非常接近。毕竟,如果周围的像素都是绿色的,你不会期望只是随机看到一个红色的像素。事实上,如果您随机选取许多这样的像素三元组,并绘制其绿色通道的强度,您会发现几乎所有的三元组都位于整个 3D 空间的一个非常小的子集上,位于从 x,y,z = 0 到 x,y,z = 1 的对角线上,其中 x,y,z 是三个像素的绿色通道强度。这是因为,对于任何三重态,绿色强度彼此强烈相关。任何不在线上的三联体都不太可能是任何真实图像的一部分。

虽然上面的例子只使用了三个像素,但图像位于真实空间的一个小子集的核心思想适用于任何大小的图像。对于更大的空间,关系变得非线性,但是事实仍然是许多特征彼此高度相关。这个想法也适用于文本和音乐,句子中的单词显然依赖于它们的邻居,大多数随机产生的音乐听起来很糟糕,一点也不和谐。不考虑领域,大多数数据位于总空间的一个小的子空间中,用于表示数据,我们称之为流形*。只有在这个流形上,数据才代表了人们认为现实的东西。*

遗传算法本质上是随机优化算法,随机地探索搜索空间。在流形上,它们的收敛很慢,因为它们生成的大多数样本一开始就不现实。你让碰运气通过时不时地生成一些像样的样本,沿着正确的方向缓慢前进,从而取得缓慢的进展。人类没有在真实的样本中给打分,他们被迫给样本是否真实打分。这种方法几乎肯定不会在任何合理的时间内收敛。

因此,通常还有其他的表现形式,比如 picbreeder.com 所使用的不断变化的函数组合,或者用几何形状来近似图像,等等。虽然这些方法确实极大地减少了搜索空间,其中局部结构保持了颜色的相似性,即没有随机噪声,但是从全局来看,大多数结构组合可能仍然没有意义或者不够真实。

While the pixel triplets here are realistic, the image at large is not (source: picbreeder.com)

搜索空间仍然太大,收敛太慢,因为即使在 picbreeder 上,你也需要数千次迭代才能生成一幅图像。

这个想法

这就是这篇论文的发现所在,它真的可以总结为一句话:让我们优化生成模型的潜在向量而不是原始数据,以快速找到用户喜欢的样本。

这是一个非常通用的解决方案,无缝融合了 IEC 方法和深度生成模型。许多生成模型通过使用潜在向量并将其传递通过解码器/生成器网络来创建真实样本。最重要的是,潜在向量通常是从 N (0 ,I )分布中采样的,也就是说,每个分量是从随机正态分布中采样的,这些分量彼此独立(或者在 VAEs 的情况下,一个分量被迫非常接近它)。

解码器然后学习将潜在空间的特定区域与特定种类的输出相关联。由于空间在较低维度的潜在空间中非常珍贵,解码器仅将潜在空间的区域“分配”给接近流形的相当真实的样本。简而言之,创建这些潜在向量是为了让生成真实的样本。在训练过程中,潜在向量的分量相互独立,解码器/生成器必须学会通过将所有这些向量与实际输出相关联来克服这一点。

Sampling in latent vector space vs in input space (image on left from Fig 6. Karras et. al. (2017))

通过随机采样并将潜在向量传递给生成器网络,您可以得到看起来稍微“不像”的样本,但它们仍然比真实输入空间上的随机采样更有可能接近真实,其中大部分只是纯粹的噪声。

由于潜在向量的分量在训练期间基本上彼此独立,现在人们可以自由地重新组合特征,同时在任何方向上随机添加噪声,并且仍然得到生成器“熟悉”的向量,从而产生真实的图像。

这确保了更快的收敛速度,因为我们可以更有效地探索低维空间的子集,而不是随机探索高维空间。换句话说,我们不是探索每一个可能的像素组合,而是探索产生真实图像的像素组合。

该算法

最终的遗传算法适用于任何潜在向量生成模型。它假设您首先训练了一个创成式模型,然后继续执行以下操作:

A.样本:样本 n (为了便于说明,n=8) 与潜在变量的先验分布相同的随机向量(通常为(0*,I** ))***

8 randomly generated latent vectors

***B *。生成:不断重复下面的步骤,直到用户找到一个拥有他想要的所有属性的样本,然后,终止这个过程。

  1. 选择:要求用户选择样品,样品具有他们想要的一些属性。这些拟合样本的潜在向量被保留,而所有其余的被丢弃。

2。交叉:对于每批允许的 n 个总样本,除了分配给所选的和预定义数量的外来样本外,剩余部分用交叉样本填充。每个交叉潜在向量是通过选择任意两个所选潜在向量,并组合它们的向量分量而生成的,其中每个分量有 50%的机会来自任一父项。

****3。突变:所有被选择和交叉的潜在向量现在都经历突变。每个潜在向量有 50%的机会经历突变,如果发生突变,向量的每个分量还有 50%的机会添加随机正态噪声,用户在每个时间步长设置标准偏差(σ) ϵ [0,1],即突变的“强度”。σ = 0 对应于完全没有突变,而σ = 1 对应于矢量分量本身数量级的噪声。

****4。外来向量:可能会出现没有一个样本具有用户想要的属性的情况。这可以通过突变慢慢收敛,但如果它是一个相当不同的属性,引入随机向量(与潜在变量先验分布相同)会更快,从而引入遗传多样性。用户可以将这些新样本与以前的样本进行交叉,以更接近所需的属性。

在一次优化的最后,我们得到一批这样的向量:

向量的总数在每次迭代中都保持不变(在我们的例子中是 8),并且这批新的向量作为输入被传递回遗传优化过程的下一步,直到用户停止它。

这就是整个算法。收敛性要好得多,因为在论文中,当生成简单的图像时,用户通常只需 10 个生成步骤就可以获得他们喜欢的图像。

音乐一代

完成所有这些后,现在我们剩下要做的就是在音乐数据上训练一个生成模型,并执行上述进化过程。出于我们的目的,我们使用来自谷歌 Magenta 项目的预训练 VAE,music vae【4】2 小节旋律模型,并在其上测试潜在向量优化过程。

这个模型是一个 VAE,其中编码器是一个双向 LSTM,中间是一个采样层,末端是一个基于 LSTM 的解码器,产生单独的第 16 个音符事件。

Structure of the 2-bar MusicVAE, linear layers omitted, modified from original paper

我们从 512 维的分布 N (0, I )中采样一些潜在向量,将其通过解码器,并对潜在向量不断执行遗传优化过程,直到我们得到我们所期望的结果。

我们从随机采样和解码潜在向量开始:

然后我们优化它。经过 8 代优化后,我们得到了这个:

没有人会认为这是一个突破,但仍然非常迷人。更重要的一点是,即使是音乐作品(尽管最初的领域是图像)的核心思想。对于更健壮的模型,仍然可以应用相同的方法来获得更好的结果。

另外,出于好奇,还有一本合作笔记本可供选择。

结论

我发现论文中概述的方法非常有趣,因为它最终似乎弥合了考虑人类偏好和深度生成模型之间的差距。深度学习不太可能完全取代人类在艺术领域的创造力,相反,它可能成为增强人类创造力的有力工具。关于插值已经取得了巨大的进步,本文也为探索方法提供了一种简洁的方法。随着每天都有更好的生成模型被发现,它必然会改进。

如果你在这篇文章中发现任何重大错误,请告诉我们,我会立即改正。如果你喜欢这篇文章,你可以在 Twitter 这里 找到我。

参考

1.深度互动进化

2.遗传算法简介

3.交互式进化计算

4.分级变分音乐自动编码器

用 Python 进行音乐流派分类

原文:towardsdatascience.com/music-genre…

Python 中的音频/音乐信号分析指南

Photo by Jean on Unsplash

音乐就像一面镜子,它告诉人们你是谁,你关心什么,不管你喜欢与否。我们喜欢说“你就是你流的东西”:Spotify

拥有260 亿美元净资产的 Spotify ,如今统治着音乐流媒体平台。目前,它的数据库中有数百万首歌曲,并声称拥有适合每个人的音乐配乐。Spotify 的 Discover Weekly 服务在千禧一代中大受欢迎。不用说,Spotify 在研究方面投入了大量资金,以改善用户查找和收听音乐的方式。机器学习是他们研究的核心。从 NLP 到协同过滤再到深度学习,Spotify 都用上了。歌曲基于它们的数字签名被分析一些因素,包括速度、声学、能量、可跳舞性等。来回答第一次约会时那个不可能回答的问题:你喜欢哪种音乐?

目标

公司如今使用音乐分类,要么是为了能够向他们的客户进行推荐(如 Spotify、Soundcloud),要么只是作为一种产品(如 Shazam)。确定音乐流派是朝着这个方向迈出的第一步。机器学习技术已被证明在从大型数据池中提取趋势和模式方面相当成功。同样的原理也适用于音乐分析。

在本文中,我们将学习如何用 Python 分析音频/音乐信号。然后,我们将利用学到的技能 将音乐片段分类成不同的流派。

使用 Python 进行音频处理

声音以一种音频信号的形式呈现,该信号具有诸如频率、带宽、分贝等参数。典型的音频信号可以表示为幅度和时间的函数。

source

这些声音有多种格式,使得计算机能够读取和分析它们。一些例子是:

  • mp3 格式
  • WMA (Windows Media Audio)格式
  • wav(波形音频文件)格式

音频库

Python 有一些很棒的用于音频处理,比如 Librosa 和 PyAudio。还有一些基本音频功能的内置模块。

我们将主要使用两个库进行音频采集和回放:

1.利布罗萨

这是一个 Python 模块,用于分析一般的音频信号,但更适合音乐。它包括建立一个 MIR(音乐信息检索)系统的具体细节。它已经被很好地记录了,还有很多例子和教程。

关于描述包装设计原理的更高级介绍,请参考 librosa 论文atSciPy 2015

安装

pip install librosa
or
conda install -c conda-forge librosa

为了提供更多的音频解码能力,你可以安装许多音频解码器附带的 FFmpeg、

2.IPython.display .音频

[**IPython.display.Audio**](https://ipython.org/ipython-doc/stable/api/generated/IPython.display.html#IPython.display.Audio)让您直接在 jupyter 笔记本上播放音频。

载入音频文件

import librosaaudio_path = '../[T08-violin](https://github.com/parulnith/Data-Science-Articles/blob/main/Music-Genre-Classification-with-Python-master/T08-violin.wav).wav'
x , sr = librosa.load(audio_path)print(type(x), type(sr))
<class 'numpy.ndarray'> <class 'int'>print(x.shape, sr)
(396688,) 22050

这会以 numpy 数组的形式返回音频时间序列,默认采样速率(sr)为 22KHZ 单声道。我们可以这样改变这种行为:

librosa.load(audio_path, sr=44100)

以 44.1KHz 的频率重新采样,或者

librosa.load(audio_path, sr=None)

禁用重采样。

采样率是每秒传送的音频样本数,以赫兹或千赫兹为单位。

播放音频

使用,**IPython.display.Audio**来播放音频

import IPython.display as ipd
ipd.Audio(audio_path)

这将在 jupyter 笔记本中返回一个音频小部件,如下所示:

screenshot of the Ipython audio widget

这个小工具在这里不能用,但是可以用在你的笔记本上。我已经把它上传到了 SoundCloud,这样我们就可以听了。

对于音频示例,您甚至可以使用 mp3 或 WMA 格式。

可视化音频

波形

我们可以使用[**librosa.display.waveplot**](https://librosa.github.io/librosa/generated/librosa.display.waveplot.html#librosa.display.waveplot)来绘制音频数组:

%matplotlib inline
import matplotlib.pyplot as plt
import librosa.displayplt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

这是波形的幅度包络图。

光谱图

声谱图声音或其他信号的频率频谱随时间变化的直观表示。声谱图有时被称为声谱图声纹声谱图。当数据以 3D 图表示时,它们可以被称为瀑布。在二维数组中,第一个轴是频率,而第二个轴是时间。

我们可以用。[**librosa.display.specshow**](https://librosa.github.io/librosa/generated/librosa.display.specshow.html)**.**

X = librosa.stft(x)
Xdb = librosa.amplitude_to_db(abs(X))
plt.figure(figsize=(14, 5))
librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='hz')
plt.colorbar()

纵轴显示频率(从 0 到 10kHz),横轴显示剪辑的时间。因为所有的行为都发生在光谱的底部,我们可以把频率轴转换成对数轴。

librosa.display.specshow(Xdb, sr=sr, x_axis='time', y_axis='log')
plt.colorbar()

编写音频

[**librosa.output.write_wav**](https://librosa.github.io/librosa/generated/librosa.output.write_wav.html#librosa.output.write_wav)将 NumPy 数组保存到 WAV 文件。

librosa.output.write_wav('example.wav', x, sr)

创建音频信号

现在让我们创建一个 220 赫兹的音频信号。一个音频信号是一个 numpy 数组,所以我们应该创建一个并把它传递给 audio 函数。

import numpy as np
sr = 22050 *# sample rate*
T = 5.0    *# seconds*
t = np.linspace(0, T, int(T*sr), endpoint=**False**) *# time variable*
x = 0.5*np.sin(2*np.pi*220*t)*# pure sine wave at 220 Hz***Playing the audio**
ipd.Audio(x, rate=sr) *# load a NumPy array***Saving the audio**
librosa.output.write_wav('tone_220.wav', x, sr)

这是你创造的第一个声音信号。🙌

特征抽出

每个音频信号都包含许多特征。然而,我们必须提取与我们试图解决的问题相关的特征。提取特征以用于分析的过程称为特征提取。让我们详细研究几个特征。

  • 过零率

过零率是信号随符号变化的速率,即信号从正变到负或反变的速率。这个功能在语音识别音乐信息检索中都被大量使用。它通常具有较高的值,适用于像金属和摇滚这样的高敲击声。

让我们计算示例音频剪辑的过零率

# Load the signal
x, sr = librosa.load('../T08-violin.wav')#Plot the signal:
plt.figure(figsize=(14, 5))
librosa.display.waveplot(x, sr=sr)

# Zooming in
n0 = 9000
n1 = 9100
plt.figure(figsize=(14, 5))
plt.plot(x[n0:n1])
plt.grid()

似乎有 6 个过零点。让我们向 librosa 核实一下。

zero_crossings = librosa.zero_crossings(x[n0:n1], pad=False)
print(sum(zero_crossings))**6**

它表示声音的“质量中心”所在的位置,计算方法是声音中频率的加权平均值。考虑两首歌曲,一首来自蓝调流派,另一首属于金属。现在,与布鲁斯流派歌曲相比,它的长度是一样的,金属歌曲在结尾有更多的频率。因此蓝调歌曲的频谱质心将位于其频谱的中间附近,而金属歌曲的频谱质心将接近其末端。

[**librosa.feature.spectral_centroid**](https://librosa.github.io/librosa/generated/librosa.feature.spectral_centroid.html#librosa.feature.spectral_centroid)计算信号中每一帧的频谱质心:

spectral_centroids = librosa.feature.spectral_centroid(x, sr=sr)[0]
spectral_centroids.shape
(775,)# Computing the time variable for visualization
frames = range(len(spectral_centroids))
t = librosa.frames_to_time(frames)# Normalising the spectral centroid for visualisation
def normalize(x, axis=0):
    return sklearn.preprocessing.minmax_scale(x, axis=axis)#Plotting the Spectral Centroid along the waveform
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_centroids), color='r')

光谱质心在接近末端时上升。

  • 光谱衰减

它是信号形状的度量。它表示总频谱能量的特定百分比(例如 85%)低于的频率。

[**librosa.feature.spectral_rolloff**](https://librosa.github.io/librosa/generated/librosa.feature.spectral_rolloff.html#librosa.feature.spectral_rolloff)计算信号中每一帧的滚降频率:

spectral_rolloff = librosa.feature.spectral_rolloff(x+0.01, sr=sr)[0]
librosa.display.waveplot(x, sr=sr, alpha=0.4)
plt.plot(t, normalize(spectral_rolloff), color='r')

信号的 Mel 频率倒谱系数(MFCCs)是一小组特征(通常约为 10–20),它们简明地描述了频谱包络的整体形状。它模拟了人类声音的特征。

这次让我们用一个简单循环波来工作。

x, fs = librosa.load('../simple_loop.wav')
librosa.display.waveplot(x, sr=sr)

[**librosa.feature.mfcc**](https://bmcfee.github.io/librosa/generated/librosa.feature.mfcc.html#librosa.feature.mfcc)计算音频信号的 MFCCs:

mfccs = librosa.feature.mfcc(x, sr=fs)
**print** mfccs.shape
(20, 97)#Displaying  the MFCCs:
librosa.display.specshow(mfccs, sr=sr, x_axis='time')

这里 mfcc 计算了 97 帧中的 20 个 MFCC。

我们还可以执行特征缩放,使得每个系数维度具有零均值和单位方差:

import sklearn
mfccs = sklearn.preprocessing.scale(mfccs, axis=1)
print(mfccs.mean(axis=1))
print(mfccs.var(axis=1))librosa.display.specshow(mfccs, sr=sr, x_axis='time')

色度特征是音乐音频的一种有趣而强大的表示,其中整个频谱被投影到表示音乐八度音阶的 12 个不同半音(或色度)的 12 个箱上。

[librosa.feature.chroma_stft](https://librosa.github.io/librosa/generated/librosa.feature.chroma_stft.html#librosa.feature.chroma_stft) 用于计算

# Loadign the file
x, sr = librosa.load('../simple_piano.wav')hop_length = 512
chromagram = librosa.feature.chroma_stft(x, sr=sr, hop_length=hop_length)
plt.figure(figsize=(15, 5))
librosa.display.specshow(chromagram, x_axis='time', y_axis='chroma', hop_length=hop_length, cmap='coolwarm')

案例分析:将歌曲分为不同的类型。

在概述了声音信号、其特征及其特征提取过程之后,是时候利用我们新开发的技能来解决机器学习问题了。

目标

在他的章节中,我们将尝试建立一个分类器来将歌曲分类成不同的流派。让我们假设一个场景,由于某种原因,我们在硬盘上发现了一堆随机命名的 MP3 文件,这些文件被认为包含音乐。我们的任务是根据音乐类型将它们分类到不同的文件夹中,如爵士、古典、乡村、流行、摇滚和金属。

资料组

我们将使用著名的 GITZAN 数据集进行案例研究。该数据集用于 G. Tzanetakis 和 P. Cook 在 2002 年 IEEE 音频和语音处理汇刊中的著名论文“音频信号的流派分类”音乐流派分类

该数据集由 1000 首音轨组成,每首音轨时长 30 秒。它包含十种风格:布鲁斯、古典、乡村、迪斯科、嘻哈、爵士、雷鬼、摇滚、金属和流行。每种体裁由 100 个声音片段组成。

预处理数据

在训练分类模型之前,我们必须将来自音频样本的原始数据转换成更有意义的表示。音频剪辑需要从。au 格式到。wav 格式,使其与 python 的 wave 模块兼容,用于读取音频文件。我使用开源的 SoX 模块进行转换。这里有一个方便的关于 SoX 转换的备忘单

sox input.au output.wav

分类

  • 特征提取

然后,我们需要从音频文件中提取有意义的特征。我们将选择五个特征来分类我们的音频剪辑,即梅尔频率倒谱系数、频谱质心、过零率、色度频率、频谱滚降。然后将所有特征追加到一个. csv 文件中,以便可以使用分类算法。

  • 分类

一旦提取了特征,我们可以使用现有的分类算法将歌曲分类成不同的流派。您可以直接使用光谱图图像进行分类,也可以提取特征并对其使用分类模型。

后续步骤

音乐流派分类是音乐信息检索的众多分支之一。从这里,您可以对音乐数据执行其他任务,如节拍跟踪、音乐生成、推荐系统、音轨分离和乐器识别等。音乐分析是一个多样化的领域,也是一个有趣的领域。音乐会话在某种程度上代表了用户的某个时刻。在数据科学领域,找到并描述这些时刻是一个有趣的挑战。