原文:TowardsDataScience Blog
协议:CC BY-NC-SA 4.0
利用机器学习生成鞋子设计
原文:https://towardsdatascience.com/generating-shoe-designs-with-deep-learning-5dde432a23b8?source=collection_archive---------13-----------------------
鞋子。 *等什么?我以为这是关于机器学习的!*是的。如果你去亚马逊,你会找到多少双鞋?可能很多吧?但是它们的种类多吗?至少就运动鞋而言,很多看起来都很相似。是时候来点新鲜的设计了。我们需要 进化——如果我们可以用机器生成我们自己的鞋子设计会怎么样…
These shoes were generated by a neural network.
数据。大型零售商有大量的鞋子出售——Zappos 和亚马逊都在他们的网站上有成千上万的鞋子照片。所以我从网上搜集了这些照片,并把它们储存在我的电脑上,主要是针对亚马逊上出售的耐克跑鞋。我写了一些代码来抓取这些图像。幸运的是,它们已经被裁剪为 224 像素乘 224 像素(这是将它们输入模型所需的大小)。但是什么样的机器学习架构是生成东西而不是寻找模式呢?你问题的答案很吸引人…
生成性对抗网络。深度学习领域相对较新的创新是生成对抗网络(GAN)。GANs 使用两个不同的网络,一个生成它认为是鞋的图像(这被称为生成器),另一个试图从数据集中区分假鞋和真鞋(这被称为鉴别器)。你可以把它想象成这些网络之间的冷战,只不过它们试图智胜对方,而不是在武器上胜过对方。一旦鉴别器基本分辨不出生成图像和真实图像的区别,模型就已经收敛了。
A Generative Adversarial Network.
深度学习模型。我创建的神经网络在很大程度上基于 Siraj Raval 的口袋妖怪 GAN 项目,他用 GAN 生成了新的口袋妖怪。我修改了代码以处理我的鞋子数据,并在亚马逊网络服务的 GPU 上训练了 500 个时代的模型。结果很酷…
Check out these fresh kicks!
结果。我让模型输出它在每个时期生成的图像,以查看它在整个训练过程中的进展。它最初主要是噪声,随机的彩色像素充满了屏幕,但逐渐形成了鞋子的形状,并获得了不同的颜色,以更好地类似鞋子。我发现有趣的是,一些鞋子有耐克标志,这可能反映了数据集中的大多数训练图像是耐克跑鞋。
那么这意味着什么呢?这个项目展示了机器学习除了在一堆数据中寻找模式之外还可以如何使用。它生成新图像的能力为大型行业(如时装、制药等)的应用提供了机会。).通过一些改进和更多的训练,这些模型可以非常强大,也许能够为现实世界的应用创造鞋的设计;时尚公司也许可以用 GANs 来创造出很酷的新潮设计。
未来时装设计师的工作可能会被机器抢走……
你可以在我的 GitHub 库这里找到我的代码。
一些有趣的附加资源:
- Siraj Raval 的口袋妖怪 GAN 视频
- 原甘论文
用 LSTM 网络生成新加坡英语文本消息
原文:https://towardsdatascience.com/generating-singlish-text-messages-with-a-lstm-network-7d0fdc4593b6?source=collection_archive---------16-----------------------
在 Medium 上发表了我的第一篇文章后,我意识到从构思一个想法到分享我的发现和学习经验的整个过程是多么令人愉快。我意识到大多数与数据相关的项目和解决方案都源于这两件事——1)我们试图解决的问题 2)我们拥有的数据带来的机遇。由于我之前的帖子是关于解决社交媒体竞赛中手工工作的问题,我想这次我应该先寻找数据。
谷歌数据集搜索
谷歌最近发布了谷歌数据集搜索,这是一个数据集的谷歌学术,这对我的起步很有帮助。我偶然发现了一个非常有趣的数据集,来自我的学校,新加坡国立大学短信语料库。这是一个超过 50,000 条新加坡英语短信的语料库,它是计算机科学系的研究工作的一部分。这些信息主要来自这项研究的志愿者,他们是在大学就读的新加坡人。
理解我们语言的机会
我认为这是一个非常好的机会来学习这些课文的语言,特别是因为我自己是新加坡国立大学的学生,我一直用新加坡英语说话和发短信。对于门外汉来说,新加坡式英语似乎是一种蹩脚的英语,甚至是一种非常粗俗的俚语。尽管看起来缺乏连贯性和语义,但它在新加坡实际上非常普遍。事实上,它经常可以用来立即与新加坡人建立联系和信任。
You can come from all walks of life and despite your race and mother tongue, as long as you’re Singaporean, you will totally get this.
当一个单词可以改变整个信息的意思时,新加坡式英语也很难理解,这也是为什么它是一种非常有效的语言的原因之一。
The nuances of Singlish.
短信里的新加坡式英语是另一个层面。除了缺少完整的句子之外,短信和网络语言进一步缩短了句子。
虽然我不是语言学专家,但我认为通过在语料库上训练神经网络来生成类似的文本信息可能有助于理解这一点。我想理解并演示为我们的文本生成选择模型的最终表示的原因。
如果不想理解 NNs、RNNs 和 LSTMs,请向下滚动到 Code。
前馈神经网络
人工神经网络模拟我们的大脑,并用节点表示神经。该网络具有接收信息的输入层、处理信息(操作、计算、特征提取)的隐藏层以及基于通常用于进行预测的信息产生期望输出的最终输出层。
A simplistic representation of a neural net.
预测输出和实际输出可能会有很大差异,这可以通过我们希望最小化的成本函数来衡量。
- 神经网络就像一个婴儿,他想学习如何正确地说话(模型输出 Yhat)
- 通过做一套特定的动作,比如说说,…,喊随机的东西(X_1 到 X_n),
- 一些比另一些更频繁(W_1 到 W_n)。
- 他试图通过在脑海中反复尝试不同的行动场景来说出什么是正确的(更新权重)。
- 他在那个时间点选择的最后一组行动尽可能接近他父母告诉他的是正确的(最小化成本函数 C)。
这就是为什么它是一种监督学习的形式。他头脑中的这种更新/理解过程也被称为反向传播。
前馈神经网络是设计的第一种也是最简单的人工神经网络,它只允许信号从输入传输到输出。它没有时间因素。当谈到文本生成时,我们试图预测给定单词序列的下一个单词,我们需要一个代表记忆的模型。
递归神经网络
RNN is a type of ANN that has a recurring connection to itself.
这种循环连接有助于 RNN 学习先前输入 X_t-1(向量)以及当前输入 X_t(向量)的效果,同时预测时间 Yhat_t 时的输出。这给了 RNN 时间感。这可以让宝宝从过去被责骂的场景中学习,避免犯同样的错误。
让我们想象一个多层香草 RNN
Recurrent Neural Network with L layers. In each layer, the input (a vector) is unrolled into t different states.
Activation function in each state
状态(蓝色)的每个输出(h)是前一状态(h_t-1)的输出和当前输入向量(X_t)的激活函数。第一层的这些输出 h_1 到 h_t 然后将作为输入馈送到下一层,因为它深入到 RNN 中。
这将允许我们根据句子的上下文来预测下一个单词。
Based on the context of the sentence, we can find the right word “meh” to use after “can”.
然而,当句子所需的上下文变得非常大时,记住诸如“so”之类的单词可能就不那么重要了。不幸的是,随着这种差距的增长,传统的 rnn 变得无法学习连接信息,因为它无法忽略或忘记所有不必要的信息。
长短期记忆(LSTM)
LSTM 模型能够表示接受信息(输入门),给出预测值(输出门),遗漏不重要信息(遗忘门)的行为。LSTM 在文本生成等序列建模任务中非常流行。与前面的 RNN 图类似,LSTM 网络将使用 LSTM 单代替节点。
让我们设想一个由 LSTM 单态组成的单层
t LSTM cells (blue) in a single layer with num_units of cell units (yellow is 1 cell unit). Each cell unit has 1 Cell State Belt and 3 Gates.
LSTM 结构和香草 RNN 结构在外表上非常相似,但主要区别是在单个细胞内。这将有助于我们及时模拟不同的状态,在这些状态下,我们能够输入、输出和忘记信息。
The Cell State Belt allows information to flow from one state to the other.
每个门都有一个 sigmoid 函数,它将返回 0–1 的输出,表示通过门的信息比例。每个门将具有权重函数 W 和 U 以及偏置项 b。
𝞂 (WXt + Uht-1 + b) = [0,1]
The Forget Gate (in purple) allows the current state to only retain a proportion of information from the previous state.
The Input Gate (in green) allows us to decide the proportion of information that should be updated in the current state.
Having both the Forget Gate and Input Gate allows us to both retain past information and update current information in this state.
The Output Gate (in red) allows us to decide how much information in the state should finally “release”, giving us the output h_t for that state.
有了对 LSTMs 的一些了解,我们最终可以探索语料库并建立我们的模型。
密码
我将使用 Python 3.6 和 Keras 来完成这项任务。首先,我们将解析数据并标记每个文本。
Number of Users: 343 Number of Texts: 55835 Sequence Length: 5
创造词汇
仅取前 1000 条消息后,文本的模态长度为 5,我们将使用它作为序列长度。基本上我们会用一个句子中过去的 4 个单词来预测下一个单词。
['just', 'now', 'i', 'heard', 'thunder', 'but', 'e', 'sky', 'still', 'looks', 'ok', 'hee', 'if', 'really', 'rain', 'den', 'i', 'no', 'need', 'to', 'run', 'liao', 'i', 'also', 'lazy', 'but', 'no', 'choice', 'have', 'to', 'force', 'myself', 'to', 'run']
上面是一个标记化文本消息的例子。我的模型的缺点是我排除了标点符号,但它也可以以其他方式建模。
We can get the vocabulary of all the texts (unique words).
Vocab Size: 1490 Total words 10419 Vocab / Total words ratio: 0.143
Next we must encode the words with numbers so that they can be fed into the neural network.
用数字表示单词
tokenizer.word_index
返回一个将单词映射到索引的字典,而tokenizer.index_word
返回相反的结果。每个单词都用一个索引进行编码,这个索引实际上是在各自的独热向量数组中启动的位置。
这有助于神经网络理解现在由一个热点向量表示的词汇。然而,这导致一个非常大且稀疏的矩阵,其当前占据了相当于 5×6 个单的空间,但是当词汇表的大小增加时,它会增长很多。
我们可以使用单词嵌入层将表示映射到指定数量的维度中。实践中推荐的大小(我在网上找到的)是 vocab_size0.25,但是在下面的例子中,我将使用嵌入大小 3。
Size is reduced when word embeddings are used. The similarity between words will also be represented based on the distance in the vector space.
模型架构
我们可以用一个简单的架构和一个顺序模型—
- 嵌入层
- 双向 LSTM 层(学习一个句子的前一个和后一个上下文,这里不赘述)
- 脱落层(防止过度拟合)
- 将输出大小映射回 vocab_size 的密集层
- 使用 Softmax 在词汇表中找到最有可能使用的类别(单词)的激活
准备培训数据
随着我们的模型建立和文本编码,下一步是准备序列数据进行训练。
这种多词对多词的上下文帮助我们训练模型,告诉他们哪个单词序列(我们的预测器 X)导致最终的单词(我们的标签 Y)。
Using the green words as X and red word as Y
最后,我们将编译并拟合我们的模型,使用—
- Adam Optimizer(深度学习流行,易于配置)
- 稀疏分类交叉熵(多类分类的成本/损失函数,其中目标输出是整数索引而不是一位热编码)
- 每次精确度提高时,保存最佳权重的模型检查点
- 当验证准确率连续 4 次没有提高时,提前停止训练。
我们还将把所有对象保存在一个 Pickle 文件中,以便在生成文本时可以重新加载它们。
培训过程看起来会像这样
Epoch 39/100 loss: 4.2459 - sparse_categorical_accuracy: 0.2050 - val_loss: 6.4890 - val_sparse_categorical_accuracy: 0.0924 Epoch 00039: sparse_categorical_accuracy improved from 0.20413 to 0.20503, saving model to best_weights.hdf5Epoch 40/100 loss: 4.2390 - sparse_categorical_accuracy: 0.2051 - val_loss: 6.4887 - val_sparse_categorical_accuracy: 0.0935 Epoch 00040: sparse_categorical_accuracy improved from 0.20503 to 0.20513, saving model to best_weights.hdf5
最后,我们可以创建一个 generate_text 函数,它接受一个种子句子“i will be ”,将其填充到正确的 sequence_length,并使用它来迭代预测下一个单词。
工作中的文本生成
这听起来确实像短信里的新加坡英语!该模型已经设法学习语法,即使拼写不完整,即使文本被迫具有 5 个单词的长度,它也是相当容易理解的。
现状核实
出于时间和金钱的考虑,我没有在整个语料库上对网络进行充分的训练。事实上,我只在 1000 条文本上使用它来测试整个流程。验证的准确性非常低,模型当然是过度拟合的。我也没有使用最佳网络结构进行测试,也没有调整任何参数。我也用了 https://www.floydhub.com,但是他们的 GPU 只有 2 个小时空闲。我目前正在等待我的 AWS 学生帐户得到验证,以便我可以在整个语料库上训练模型。然而,我的期末考试快到了,我不能再等了。
然而,这是一个非常有趣的问题,也是一次很好的学习经历。期待回来的时候多学习,多探索,多分享!
链接到项目的回购
请通过 LinkedIn 或 与我在进一步讨论!
参考
[ 如何用 Keras 在 Python 中开发基于单词的神经语言模型
语言建模包括在已知单词序列的情况下,预测序列中的下一个单词。一个…
machinelearningmastery.com](https://machinelearningmastery.com/develop-word-based-neural-language-models-python-keras/) [ LSTM(长短期记忆)的嵌入层是什么?
回答(第 1 题,共 2 题):如果你考虑如何提供一个单词作为 LSTM 的输入,它基本上是一个网络/模型…
www.quora.com](https://www.quora.com/What-is-the-embedding-layer-in-LSTM-long-short-term-memory) [ 使用双向 LSTM 和 Doc2Vec 模型 1/3 生成文本
本文的目的是讨论文本生成,使用机器学习的方法,特别是…
medium.com](https://medium.com/@david.campion/text-generation-using-bidirectional-lstm-and-doc2vec-models-1-3-8979eb65cb3a) [ 深度学习精要:长短期记忆导论
引言序列预测问题由来已久。他们被认为是最难的…
www.analyticsvidhya.com](https://www.analyticsvidhya.com/blog/2017/12/fundamentals-of-deep-learning-introduction-to-lstm/) [ 深度学习-安,RNN,LSTM 网络
长短期记忆(LSTM)模型是一种有监督的深度神经网络,非常适合处理时间序列问题
vishnuviswanath.com](https://vishnuviswanath.com/ann_rnn_lstm.html)
使用递归神经网络生成文本
原文:https://towardsdatascience.com/generating-text-using-a-recurrent-neural-network-1c3bfee27a5e?source=collection_archive---------5-----------------------
Figure 1: person writing on paper by rawpixel on Unsplash
如何使用 Keras 创建亚瑟·柯南·道尔风格的文本
深度学习可以用于许多有趣的事情,但通常它可能会觉得只有最聪明的工程师才能创建这样的应用程序。但这根本不是真的。
通过 Keras 和其他高级深度学习库,每个人都可以创建和使用深度学习模型,无论他对理论和算法内部工作的理解如何。
在本文中,我们将看看如何使用递归神经网络来创建亚瑟·柯南·道尔爵士风格的新文本,使用他的书“夏洛克·福尔摩斯的冒险”作为我们的数据集。
我们可以从古腾堡网站获得数据。我们只需要将其保存为文本(。txt)文件并删除文本中嵌入的 Gutenberg 页眉和页脚。如果你不想自己做这些,你可以从我的 Github 获得本文的文本和所有代码。
递归神经网络
Figure 2: Unfold RNN by François Deloche
递归神经网络(RNN)是用于顺序数据的最先进的算法。这是因为它们可以通过内部记忆记住以前的输入。
在本文中,我不会深入探讨递归神经网络是如何工作的,但如果你感兴趣,你可以查看我的视频解释 RNN 是如何工作的,或者你可以查看Suvro baner JEE的这篇伟大文章。
创建我们的数据集
像往常一样,我们将开始创建我们的数据集。为了能够在 RNN 中使用文本数据,我们需要将其转换为数值。然后,我们将创建一个字符序列作为我们的 X 数据,并使用下面的字符作为我们的 Y 值。最后,我们将把数据转换成一个布尔数组。
首先,我们将加载数据,并创建从字符到整数和整数到字符的映射:
with open('sherlock_homes.txt', 'r') as file: text = file.read().lower() print('text length', len(text))chars = sorted(list(set(text))) # getting all unique chars print('total chars: ', len(chars))char_indices = dict((c, i) for i, c in enumerate(chars)) indices_char = dict((i, c) for i, c in enumerate(chars))
为了获得有价值的数据,我们可以用它来训练我们的模型,我们将把我们的数据分成长度为 40 个字符的子序列。然后我们将把数据转换成一个布尔数组。
maxlen = 40 step = 3 sentences = [] next_chars = [] for i in range(0, len(text) - maxlen, step): sentences.append(text[i: i + maxlen]) next_chars.append(text[i + maxlen])x = np.zeros((len(sentences), maxlen, len(chars)), dtype=np.bool) y = np.zeros((len(sentences), len(chars)), dtype=np.bool) for i, sentence in enumerate(sentences): for t, char in enumerate(sentence): x[i, t, char_indices[char]] = 1 y[i, char_indices[next_chars[i]]] = 1
递归神经网络模型
虽然创建一个 RNN 听起来很复杂,但是使用 Keras 实现起来非常容易。我们将创建一个简单的 RNN,其结构如下:
- LSTM 层:将学习序列
- 密集(全连接)层:每个独特字符一个输出神经
- Softmax 激活:将输出转换为概率值
我们将使用 RMSprop 优化器和分类交叉熵损失函数。
from keras.models import Sequential from keras.layers import Dense, Activation from keras.layers import LSTM from keras.optimizers import RMSpropmodel = Sequential() model.add(LSTM(128, input_shape=(maxlen, len(chars)))) model.add(Dense(len(chars))) model.add(Activation('softmax'))optimizer = RMSprop(lr=0.01) model.compile(loss='categorical_crossentropy', optimizer=optimizer)
助手功能
为了看到我们的模型在训练时的改进,我们将创建两个辅助函数。这两个函数来自 Keras 团队的官方 LSTM 文本生成示例。
第一个辅助函数将从输出(概率数组)中抽取一个索引。它有一个名为 temperature 的参数,这个参数定义了函数在创建文本时的自由度。第二个将在每个时期结束时生成具有四个不同温度的文本,以便我们可以看到我们的模型做得如何。
def sample(preds, temperature=1.0): # helper function to sample an index from a probability array preds = np.asarray(preds).astype('float64') preds = np.log(preds) / temperature exp_preds = np.exp(preds) preds = exp_preds / np.sum(exp_preds) probas = np.random.multinomial(1, preds, 1) return np.argmax(probas)def on_epoch_end(epoch, logs): # Function invoked at end of each epoch. Prints generated text. print() print('----- Generating text after Epoch: %d' % epoch) start_index = random.randint(0, len(text) - maxlen - 1) for diversity in [0.2, 0.5, 1.0, 1.2]: print('----- diversity:', diversity) generated = '' sentence = text[start_index: start_index + maxlen] generated += sentence print('----- Generating with seed: "' + sentence + '"') sys.stdout.write(generated) for i in range(400): x_pred = np.zeros((1, maxlen, len(chars))) for t, char in enumerate(sentence): x_pred[0, t, char_indices[char]] = 1. preds = model.predict(x_pred, verbose=0)[0] next_index = sample(preds, diversity) next_char = indices_char[next_index] generated += next_char sentence = sentence[1:] + next_char sys.stdout.write(next_char) sys.stdout.flush() print() print_callback = LambdaCallback(on_epoch_end=on_epoch_end)
我们还将定义另外两个回调函数。第一个名为 ModelCheckpoint。这将节省我们的模型每一个时代的损失减少。
from keras.callbacks import ModelCheckpoint filepath = "weights.hdf5" checkpoint = ModelCheckpoint(filepath, monitor='loss', verbose=1, save_best_only=True, mode='min')
另一个回调会在每次学习停滞时降低学习速度。
rom keras.callbacks import ReduceLROnPlateau reduce_lr = ReduceLROnPlateau(monitor='loss', factor=0.2, patience=1, min_lr=0.001)callbacks = [print_callback, checkpoint, reduce_lr]
训练模型并生成新文本
对于训练,我们需要选择一个 batch_size 和我们想要训练的时期数。对于 batch_size,我选择 128,这只是一个任意的数字。我只训练了 5 个时期的模型,所以我不需要等这么久,但如果你想你可以训练它更多。
model.fit(x, y, batch_size=128, epochs=5, callbacks=callbacks)
培训产出:
Epoch 1/5 / [==============================] - 225s 1ms/step - loss: 1.9731----- Generating text after Epoch: 0 ----- diversity: 0.2 ----- Generating with seed: "lge on the right side of his top-hat to " lge on the right side of his top-hat to he wise as the bore with the stor and string that i was a bile that i was a contion with the man with the hadd and the striet with the striet in the stries in the struttle and the striet with the strange with the man with the struttle with the stratter with the striet with the street with the striet which when she with the strunt of the stright of my stright of the string that i shall had been whi ----- diversity: 0.5 ----- Generating with seed: "lge on the right side of his top-hat to " lge on the right side of his top-hat to he had putting the stratce, and that is street in the striet man would not the stepe which we had been of the strude in our in my step withinst in some with the hudied that in had a had become and the corted to a give with his right with a comon was and confice my could to my sule i was and shugher. i little which a sitter and the site my dippene with a chair drive to be but the some his site with
为了自己生成文本,我们将创建一个类似于 on_epoch_end 函数的函数。它将采用一个随机的起始索引,从文本中取出接下来的 40 个字符,然后用它们来进行预测。作为参数,我们将传递给它我们想要生成的文本的长度和生成的文本的多样性。
def generate_text(length, diversity): # Get random starting text start_index = random.randint(0, len(text) - maxlen - 1) generated = '' sentence = text[start_index: start_index + maxlen] generated += sentence for i in range(length): x_pred = np.zeros((1, maxlen, len(chars))) for t, char in enumerate(sentence): x_pred[0, t, char_indices[char]] = 1. preds = model.predict(x_pred, verbose=0)[0] next_index = sample(preds, diversity) next_char = indices_char[next_index] generated += next_char sentence = sentence[1:] + next_char return generated
现在我们可以通过调用 generate_text 函数来创建文本:
print(generate_text(500, 0.2)
生成的文本:
of something akin to fear had begun to be a sount of his door and a man in the man of the compants and the commins of the compants of the street. i could he could he married him to be a man which i had a sound of the compant and a street in the compants of the companion, and the country of the little to come and the companion and looked at the street. i have a man which i shall be a man of the comminstance to a some of the man which i could he said to the house of the commins and the man of street in the country and a sound and the c
结论
递归神经网络是一种处理顺序数据的技术,因为它们可以通过内部存储器记住最后的输入。它们在几乎每一个顺序问题上都达到了最先进的性能,并被大多数大公司所采用。RNN 可用于以特定作者的风格生成文本。
创建文本生成 RNN 的步骤如下:
- 创建或收集数据集
- 建立 RNN 模式
- 以一个随机的句子为起点创建新的文本
这个项目的细节可以在这里找到。我鼓励任何人试验一下代码,也许可以改变数据集和预处理步骤,看看会发生什么。
为了获得更好的输出,您还可以对模型进行许多改进。其中一些是:
- 使用更复杂的网络结构(更多 LSTM 层、密集层)
- 为更多时代而训练
- 摆弄批处理大小
如果你喜欢这篇文章,可以考虑订阅我的 Youtube 频道,在社交媒体上关注我。
如果你有任何问题或批评,可以通过推特或评论区联系我。
用神经网络生成文本
原文:https://towardsdatascience.com/generating-text-with-lstms-b0cdb6fc7bca?source=collection_archive---------2-----------------------
Can Neural Networks learn to Write?
有许多文章因声称“用 lstm 写另一部哈利波特”或“用 lstm 写说唱歌词”而获得了人气。LSTMs 属于一类更广泛的神经网络模型,称为递归神经网络。“循环”部分来自模型按顺序处理数据的能力,以及将以前的输入值作为最新输入值的输出因素。
序列处理是一个非常有趣的问题,可以应用于价格建模、视频处理,以及我们将在本文中讨论的文本处理。
Letters vs. Words, what is the foundation for language in Neural Networks?
当将 RNNs 用于文本、字符和单词级模型时,有两种主要的二分法。这是指将文本编码成整数以便模型处理的方式。在 char 级模型中,我们将每个字母标记为字母语料库中的一个 hot 向量。在单词级模型中,我们将每个单词标记为单词语料库中的一个热点向量。
尽管对每个单独的字符进行编码可能看起来更加繁琐,但这里要避免的瓶颈是结果向量的稀疏性。在文本的训练数据集中通常只使用大约 60 个字符,在同一个数据集中很容易使用 1000 个独特的单词。有很多方法可以使用单词嵌入来尝试和减少单词级编码的维数,但是到目前为止,字符级编码对于简单的推理来说会产生更好的结果,即编码的向量具有更密集的信息。
字符级网络中的一键矢量编码示例 ( 如果你已经熟悉这个请跳过):
语料库:[‘a ‘,’ b ‘,’ c ‘,’ d,’ e ‘,’ f ‘,g ‘,’ h ‘,’ i’] — len(语料库)= 9
单词:[‘坏’] → [‘b ‘,’ a ‘,’ d’]
b → [0,1,0,0,0,0,0,0,0],a → [1,0,0,0,0,0,0,0,0,0],d → [0,0,0,0,1,0,0,0,0]
一些采用这种策略的人选择不使用一键向量编码方法,而是用 ASCII 码对每个字符进行编码,比如 a = 65。以这种方式编码字符的问题是,整数暗示了字母之间的某种顺序,例如:a < b < d。在实际语言中,字母之间的这种组织是不存在的。
当处理神经网络,尤其是具有许多层的深度神经网络时,我们希望尽量避免这样的事情,因为很难确切地说出网络在训练后学到了什么。一个著名的例子是在森林中探测坦克的军事实验。包含坦克/不包含坦克的数据集仅在晴天拍摄了坦克,在阴天拍摄了不包含坦克的田地。因此,深层 CNN 模型学会了对天气进行分类,而不是对坦克的存在进行分类。
一旦将文本编码成向量,就该使用 LSTM 来训练模型了。在这个代码示例中,我们将使用构建在 Tensorflow 之上的 Keras 库来大大简化这项任务。
from keras.models import Sequential from keras.layers import Dense, LSTMmodel = Sequential() model.add(LSTM(75, input_shape=(X.shape[1], X.shape[2]) model.add(Dense(vocab_size, activation='softmax'))model.compile(loss = 'categorical_crossentropy' optimizer = 'adam', metrics = ['accuracy'])model.fit(X, y, epochs = 100, verbose = 2)
正如我们在上面看到的,建立神经网络并不太困难。与生成文本相关的大部分工作(像许多 ML 项目一样),是对文本进行预处理,对文本进行标记并将其转换成向量,然后将其输入模型。
我用 JCole 歌词做了一个实验,看看这个模型是否能继续这个序列。该模型在训练中报告了 80%的准确率,但当我给出这些例子时,结果并不令人印象深刻。我们确实注意到该模型不能很好地概括,即使两个输出都不令人满意,但是当训练数据中包含起始种子时,该模型表现得更好。
示例 1:(训练集中包含的起始种子)
“没有角色模型,我是她”,20 #歌词包含在训练集中,20 个参数指示模型再生成 20 个角色
模型输出→没有榜样,而我在这里是因为他们没有
(至少在某种程度上这是英语)
示例 2:(起始种子不包含在训练集中)
跳入水中,20 #歌词不包含在训练集中
输出→跳入水中,furby 调用 som
这些结果如此糟糕的主要原因是因为我只给模型输入了 500 行 JCole 歌词,如果你有兴趣自己尝试这个实验,我建议使用 kaggle 的 55,000 首歌曲歌词数据集。你应该预料到训练这个模型也需要一些时间,除非你有 GPU 机器或者计划在云上训练你的模型。
如果一个字符或单词级别的递归网络可以生成类似电视节目中的对话或书籍节选的内容,我会感到惊讶。我也对如何使用生成对立网络来生成文本非常感兴趣。有许多流行的论文使用文本生成方法,标题如:“神经网络撰写研究论文标题”。训练这些网络需要大量的数据、计算能力和深度模型,所以如果在本地计算机上运行,请做好准备。
感谢您的阅读,希望这篇文章能帮助您理解 RNN/LSTM 序列网络的文本生成!如果你想用 Python 和 Keras 详细浏览你的第一个角色级 RNN,下面是一篇很好的文章:
https://machine learning mastery . com/develop-character-based-neural-language-model-keras/
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对数据科学、深度学习和软件工程感兴趣。主要用 Python,JavaScript,C++编码。请关注更多关于这些主题的文章。
生成 Twitter 自我网络&发现社区
原文:https://towardsdatascience.com/generating-twitter-ego-networks-detecting-ego-communities-d255?source=collection_archive---------2-----------------------
一种基于图的 Twitter 网络社区发现方法
我们的心甚至还没有参与——就此而言,我们的耳朵也没有!我们更像是一个神不守舍、全神贯注的人,他的耳朵里刚刚响起了正午 12 点的钟声(一个 twitter 通知把你叫醒了),他突然醒来,问自己“那个钟到底敲了多少下?” (他/她刚才到底转发了什么,是在说我想的那个吗…?) (这真的是刚刚发生的吗?) 还有更多:“我们到底是谁?” (我为什么要跟着他/她?) 然后,正如我已经提到的,我们数一数——事后——我们经历的时钟的所有十二次颤抖的敲击 (我们浏览他们所有的推文) 、我们的生活 (我们的推文) 、我们的存在 (我们的追随者)——唉!在这个过程中,我们不断失去计数。因此,我们对自己仍然是陌生人,我们不了解自己,我们必须让自己困惑 (我们察觉到它们) 。对我们来说,这条定律永远适用:“每个人都离自己最远。就我们自己而言,我们不是“有知识的人”。”—弗里德里希·尼采
我很确定尼采预言了推特。以这样的方式开始我的数据科学相关帖子(引用这样的话)可能看起来很奇怪,但这确实是我们任务背后的动机——试图成为*‘有知识的人’,*通过理解我们身边的人(虚拟地)来拉近我们自己。
推特是…至少可以说很奇怪。我跟踪的很多人都不止一次抱怨过 Twitter 的无用和对它的沉迷…在推特上。我不知道当一个平台被用来抱怨自己时,它会说些什么,但我知道的是,它会把你拉回来。Twitter 就像柏拉图的洞穴,在那里我们看到影子在跳舞,除非我们有意识地面对它,并且技术上可以“自由”转身离开,但通常不会。这并不那么可怕和令人沮丧,我们必须承认,Twitter 允许我们拥有一个微型互联网,在我们作为进出连接的枢纽时,可以自由定义自己的定制规则。随着这个中心的成长——随着我们被越来越多的用户关注和追随——它塑造和修补成一些个人的东西,包含了解释我们的兴趣甚至我们个性的某些部分的潜在属性的组合。作为一个中枢,我们娱乐并被我们随着时间的推移创造的网络所娱乐:一个以我们为焦点的自我网络(一个来自社会学的术语),延伸我们的虚拟肢体去触摸和感受其他自我和他们自己的自我网络的素。
不管你对 Twitter 的看法如何,它可以是一个丰富的数据集,这个项目旨在使用这些数据来建模和分析一个 Twitter 自我网络。为了能够进行更深入的分析,我们必须完成一些预备步骤。因此,在这篇文章中,我将只讨论这种分析的第一阶段:通过社区检测技术对网络建模并执行一些高级软分析。
未来阶段将尝试使用自然语言处理技术进行更深入的研究和语言素分析。
概述
1.数据挖掘
2.网络建模
3.社区检测
4.观察和分析
这篇文章是为普通读者写的,旨在展示一些工作是如何完成的,我将避免过于技术性的谈话——希望让它成为每个人相关和有趣的经历。然而,我将为有一些基本编码经验的读者提供足够的技术参考,以便他们能够了解可以使用什么工具来执行任何类似的分析。(我也可以根据要求展示代码)
技术说明
所有编程,数据挖掘,算法应用等。是在 Jupyter 笔记本(Python)中从一个基本的 Docker 模板中完成的。
#Libraries Used: tweepy i-graph networkx tqdm pandas numpy matplotlib seaborn pickle json
Gephi 用于输出两者的网络可视化。巴新和。svg 格式。 i-graph 和 networkx 库都可以输出中的图形。来自 Python 对象的 gml 格式,可以使用 Gephi 读取并组织、着色、分区等等。
数据挖掘— 让我们获取数据
这个项目的数据是使用 Twitter 的 API 从 Twitter 中提取的。不幸的是,鉴于 Twitter 的费率限制,在给定的时间窗口内只允许一定数量的呼叫,挖掘起来并不迅速。为了建立我们的网络,我们需要:
- 账号/验证 _ 凭证 — 获取 root 用户的【又名我的】信息
- 好友/列表 —返回每个用户的信息 root 用户是“关注者”,我们称他们为“好友”[~ 300/15 分钟]
- friends/ids — 返回 root 用户的朋友的 id 为“following”,如 get“朋友的朋友”)[~75,000ids/15min 或 15users/15min]
- 状态/user_timeline — 获取任何给定用户的多达 3,200 条最新推文[~36,000 条推文/15 分钟]
使用一个名为 Tweepy 的 python 库,它自动等待考虑速率限制,我们可以获得 Twitter 的 API 响应并将它们存储到 JSON 文件中。然后,可以读取这些文件,并将其放入数据结构(字典或 Pandas DataFrame)中,供我们的其余流程使用。
网络建模——我们如何量化我们所看到的?
任何数据科学分析最重要的步骤之一是花时间思考如何量化问题。通常,当我们用来量化现实的基础数据和手段薄弱时,我们往往会转向模型和算法。
我们将建立一个社会学中所谓的一步邻居——在某种意义上,我们将只深入到两层朋友,但条件是我们将删除不是根用户朋友的朋友的朋友。所以,我们会查看 look 用户(我的)的朋友以及他们之间的任何联系。(用户的*‘朋友’是 twitter 的官方术语,用来描述用户‘关注’的人)。由于要建立我们的网络,我们更感兴趣的是根用户“看到”了什么,而不是他们如何被“看到”,我们将关注他们的朋友,而不是他们的追随者。该网络将是一个基于有向图的网络 (图 1) ,意味着我们主要处理节点和有向边。基本设置:*
- 节点将被定义为用户。
- 边基于某种关系将两个用户(节点)连接在一起。从这个意义上说,如果用户 A 跟随用户 B,一条边将从节点 A 出去,进入节点 B。
Figure 1: Basic Directed Graph
虽然这是网络的基础,但我们可以直观地看到,每个“我在关注你”的关系不可能有相同的“权重”——你的叔叔住在几英里外,4 年前跟踪你,作为一种“时髦”的手段,他在你的网络中的角色与你的共同分享者非常不同,他们总是转发你所做的一切。因此,我们通过建模权重(针对边和节点)在我们的网络中引入一些复杂性。本项目中的假设是权重由*【活动】*量化(这也将在我们稍后选择的社区检测类型中发挥作用)。
- 边缘权重将是任何给定用户之间的各种连接的函数,即你最近历史中的转发、回复和引用状态的数量。我们还将量化“我追随你”的联系,假设 A) 如果用户的追随者与追随者比率较低,那么他们追随某人会变得更加“重要”,而 B) 拥有更多追随者的用户追随拥有较少追随者的用户会变得更加“重要”。这就引出了一个等式:
EdgeWeight between a & b = (w1 * RT_ab) + (w2 * Qtd_ab) + (w3 * Rep_ab) + ( w4 * (Rff_a * (FC_a - FC_b) / (FC_a + FC_b) )Rt_ab = # of A Retweets B Qtd_ab = # of A Quoted B Rep_ab = # of A Replies to B Rff_a = Follower to Following Ration of a FC_a = Follower Count of a FC_b = Follower Count of bw1,w2,w3,w4 = (manually assigned) weights of each connection w4 > w3 > w2 > w1
w1、w2、w3、w4 这些术语是根据直觉选择的,以便对每个术语的意义进行排序(根据我与 Twitter 的互动方式)——关注比回复更有价值,引用比转发更有价值…
- 我们还可以根据用户活动为节点本身分配权重。可以理解的是,不管有什么联系,如果我(和我的朋友)更频繁地见到一个用户,他通常是我的网络中更强大的一部分。
NodeWeight of a = ~ Avg # of tweets day based on recent historyTweets include RTs, Quoted Statuses, & Replies.
可以使用 python 库 i-graph 或 networkx 对图形进行建模。 Networkx 很好,因为它允许从 Pandas Dataframe 直接导入,但是在 i-graph 上有更多的社区检测算法选项。就我个人而言,我在两个 i-graph 中对他们建模,以获得社区分配,然后使用 networkx 进行一些初步可视化(因为它与 matplotlib 一起工作,不像 i-graph
网络统计:节点和边属性的分布
在解释下面的图表时,请注意大多数轴都是对数 10 标度的,以便更清楚地看到数值的分布(例如,x 轴上的 2 表示 100 单位,3 = 1000 单位,4 = 1000 单位,等等)。).另请注意,节点统计的 y 轴值是密度而不是计数(例如曲线下的面积等于 1)。不管怎样,我们对查看一般分布感兴趣——哪个值出现得最多或最少。
Node Stats (all x-axis are log-scaled)
在我们的网络中,似乎大多数用户有 1000-10,000 条推文和 100-1000 个好友(如下)。followersCount 分布似乎没有达到峰值,所以分布更加均匀。最后,我们的大多数节点都有很小的权重,有些用户比这个网络中的普通用户活跃近 10 倍。
Edge Stats
就优势而言,正如预期的那样,大多数用户并不经常联系,而那些联系上的用户之间最近的活动水平(5-100 次转发和回复)差异很大。
最终网络:汇集一切
现在,我们的网络由大约 400 个加权节点和大约 10,000 条边组成(很小,但关系复杂)。下面是过滤掉一些孤立节点后的样子:(注意,节点的大小描述了节点权重)
Figure 2: Social Network — Directed Graph with Weighted Nodes and Edges
嗯……酷?(有可能)。但实际上,我们很快就会意识到我们无法从中获得一大堆信息。目前,这是非常平淡无奇的(从字面上看,这只是黑与白),这实际上是我们在处理复杂网络时面临的挑战之一——你不能只是从它们那里“观察”见解。这就是为什么在我们作为人类分析师真正进行任何有意义的分析之前,我们需要看到“聚集”的信息。从算法上来说,对数据进行聚类也将有助于我们今后的语言分析,并且也经常用于减少计算时间。有助于应对这一挑战的技术是社区检测— 一个强大的过程*(图 3)* ,其中我们将一个复杂的网络分割成个社区,这些社区在结构上对图进行分类,并描述一些隐藏在你在图 2 中看到的网状混乱中的高阶属性。
Figure 3: Example of Community Detection
社区检测
现在是有趣的部分(再次,字面上),我们如何在我们的网络中找到隐藏的社区?我只有大约 400 个朋友,所以如果有人建议花一天时间浏览他们,他们并没有“错误”…然而,如果我们想摆脱人类的“偏见”,更“科学地”找到社区呢?如果我们开始手动地将用户分类到社区中,我们会确切地知道该做什么,但是在更真实的意义上,我们不知道该做什么。像’*这样的难题,首先有多少个社区?“社区分配的标准是什么?”*上来。因此,虽然可以理解,如果我们使用计算机进行这种分类过程,我们可能会失去一些细微差别,但与直觉相反,我们实际上可能会获得一些我们的偏见所不允许的细微差别。
有了数据科学,我们不需要总是处理数据,因为“人类不可能做到,这需要太长时间”。有时,数据科学是一门由可计算的有氧运动组成的艺术,它帮助我们以一种前所未有的方式查看数据。(尽管通常情况下,数据科学是在做一个人真的不应该用 Excel 做的事情。虽然他们尝试…他们总是尝试…人类。)本着这种精神,我们期待一种有趣的算法来发现基于“信息流”的社区——信息地图。
首先,什么是社区?没有具体定义的原因是因为“社区”的部分定义将来自社区检测算法。一般来说,信息分类在任何哲学或科学研究中都扮演着重要的角色,而社区就是这样:组织知识的节点分类。
我们本质上试图从社区中获取的是基于同质化现象将相似的用户分组在一起。
“相互联系的群体中的个体往往具有相似的特征。这种现象被称为同质性,并被定义为“一个基本的组织原则”,即“相似的人之间的接触比不同的人之间的接触发生率更高”( McPherson,Smith-Lovin,& Cook,2001 ,第 416 页)。“物以类聚,人以群分”的说法广为人知,它抓住了自然发生的社会网络的一个关键特征,并描绘了一种机制,通过这种机制,“社会特征方面的距离转化为网络距离”( McPherson 等人,2001 ,第 416 页)。简单地说,同性恋表明个人更有可能与经常与他们非常相似的其他人形成新的社会网络联系。”
— 使用社交网络分析对 Twitter 话题网络进行分类
更具体地说,twitter 自我网络包含自然发生的基于流的社区——自然发生是因为“信息流”不是预先确定的,而是随着网络拓扑结构的变化而改变。节点(用户)通过边缘(转发、回复等)将自己确立为节点之间的信息载体。).在这个意义上,当我们寻找社区时,我们正在寻找基于流的社区检测方法,以便“社区由节点组成,其中,[信息]流一旦进入就会持续很长时间”(地图方程框架教程)。这不同于基于我们的网络模型的结构组成将一个图切割成斑点。我们将在后面看到基于流的社区检测算法如何不总是在结构上分离网络。
Infomap 是基于优化‘地图方程’的基于流量的社区搜索算法。我不想在这里变得过于技术化,所以如果感兴趣的话,我会让读者自己去探索,特别是因为作者已经制作了一些描述 map 方程机制的惊人演示,并且有一个编写的教程来指导你。
在使用 Infomap 进行了一些尝试后,我发现尽管它很好地对许多社区进行了分类,但通常有一大块节点被归类为一个社区,感觉像是“剩余”节点——用户很可能属于多个社区,并为更复杂的信息流做出贡献。为了进一步分割这个大的剩余社区, Walktrap ,另一个社区检测算法,但它更多地基于节点相似性和网络结构——如果从 A 和 B 分别到达所有其他节点的概率相似,则节点 A 和 B 被分类在同一个社区中。从一个节点到另一个节点的概率是用“随机漫步”来计算的,这背后也有一个简洁的直觉。
基本上,在应用这些算法之后,我们的社区检测采用以下组织原则:如果推文和关注(信息和印象)似乎持续存在于用户中,则用户被分组在一起——使得他们彼此之间的活跃度很高。至于更大的剩余用户群(他们彼此之间有规律的活动,并且信息流不会在任何特定的更小的用户群中持续),根据他们在该更大的群中的行为的相似程度,他们被进一步划分为小社区。 图 4 显示了我们网络中社区规模的直方图。
这两个社区定义不同的一个直观原因是,我们可以让我和我的朋友 Qasim 不转发对方的观点(因为这意味着承认失败),而是不断转发第三方政治分析师的观点。一个基于相似性的检测会把我和我的朋友归入同一个社区(即我们有相似的行为),一个基于流的检测不会(即信息不流经我们的连接)。
Figure 4: Histogram of Community Sizes (y-axis is # of communities)
这种分布突出了看似直观的东西(至少在我使用 Twitter 的方式上):我们有许多小社区——通常围绕特定的品味/事件/兴趣/主题构建——然后是一些主要的大玩家,在这种情况下包含 10 到 50 个用户。
注意:当然,一些用户在任何给定的社交网络中的多个(概念上的)社区中具有“成员资格”,但是对于这个项目,我们将不处理重叠和多个成员资格。部分原因是,我希望看到一个用户被分配到其所属的所有社区中最主要的社区,部分原因是,这会使计算变得不必要的复杂,并且我找不到足够方便的库来进行所述计算。
观察和分析
最后,我们得到了一个奇妙的自我网络,看起来像一个热闹的三星级酒店(如果你得到了这个参考,也请立即在 Twitter 上与我联系)。同样,节点大小描述了节点权重(用户有多“活跃”),而边厚度描述了边权重(两个用户基于他们彼此的活跃程度而有多强的连接)。
Figure 5: Communities in a Twitter Ego-Network
仅供参考,中间右边的白点是我(正如尼采预言的,我对自己一无所知…我甚至不是我自己社区的中心…)。说到自我,我认为我们的一部分总是希望被分析,而这种关注并不总是容易获得的——所以这就像是获得关注的 DIY 版本。在我的个人网络上做了这种分析后,我可以将算法输出与我自己的人类直觉进行比较,并且——以我早期的一些项目为例——这正是我想要做的。这篇文章的其余部分将强调一些从我们的网络图中提取洞察力的方法。
提醒一下,这是对“自我网络”的社区分析,因此,不是对 Twitter 上任何给定用户的客观分类,而是从我的角度对他们在我的网络中所扮演的角色的分类。
可视化的分析原理
相互关联的位置— 当我们分析社区时,重要的是要记住节点的确切位置(南、北、东、西)并不重要,但它与其他节点的相对位置不是偶然的。尽管可视化中包含一些随机性,但它实际上是通过吸引力、排斥力和重力的混合来建模的。所以强连通的节点会互相吸引,非连通的节点会互相排斥。
内部相关位置 —区域内节点的位置也很重要。远离中心位置和深入社区的节点反映了更多的小生境行为和信息流属性。
密度— 更密集的节点集合意味着更强的互连性。稀疏意味着更弱的互联性。
模块性— 衡量集群质量的指标,即社区之间的断开程度。“高度模块化网络的特征是一些高度内部连接的集群,它们松散地相互连接。因此,用户高度互联而不考虑集群关系的网络模块化程度较低。”
桥接节点— 在社区边界上发现的节点有时可以充当链接,松散地互连两个社区。
离群点— 远离其所分配社区的结构领域的节点。有时这些是错误分类,有时远离桥节点。
Ego-Network Fingerprint
社区#1-2:现实生活中的人和他们现实生活中的朋友
这两个社区通常包含我所关注的我的个人关系或朋友(以下简称“追随者”),分别位于我主要的高中关系和高中以外的关系之间。因此,可以理解它们是密集的(即强内连接)。我看到了一个有趣的空间表现,我的高中联系远离了中心,从而远离了我的普通网络的其余部分(即,在 twitter 的世界里,我们已经分开了,可以理解的是,他们中的一些人甚至不活跃)。在这个社区中,我经常与之互动的人离我的节点更近。此外,与社区中的其他人相比,更强的朋友(或者至少是我所知道的那些)看起来彼此更亲近。总的来说,这些都是强大的、定义良好的社区,并且与真实系统相一致——网络的这一部分具有很强的模块化。
社区#3:多伦多人寿保险公司(最右边是 CBCNews)
另一个强大的社区,在战略上离我的个人关系稍微远一点。这个社区主要包含不同主题的多伦多/加拿大用户。有趣的是, '@hidrees ‘,’ @DotHealth ‘,’ @robjama ‘,和 ‘@uoftengineering’ 在一起,但与其他人相距较远——这是一个多伦多-加拿大商业技术迷你小组。当我们向北走时,我们会遇到更多的活动家/记者/政治评论家,比如、和、【stevenzhou】。像 ’@IRCanada ‘,’ @ NaseehaHelpline ',和 ‘@IngridMattson’ 这样的节点是结构上更接近这个社区(和加拿大人)的用户的很好的例子,但是就流量而言,更涉及另一个社区。总的来说,除了一些微型组之外,集群通过松散的内部连接松散地连接到网络的其余部分。这意味着这个社区并不是太封闭,它包含了与我的更中心的网络的各种连接。
社区# 4–5:主角(绿色)和不适合的人(粉色)
这是最大的跨社区(就区域而言),原因显而易见——我们有许多用户涌入其他社区的领地。我把这个社区称为“主要行为”——我觉得每个 twitter 用户都有一个在某些方面与此类似的社区——因为我的许多其他社区“观看”这个社区,有点像一出戏。
- 我们看到的主要是大客户,受欢迎的人物,他们在别人看着他们的时候相互交流。就我而言,我们看到对世界事务发表评论的伊斯兰学者聚集在中心,与来自其他社区的多个用户相连。
- 我们还可以看到一种趋势,即随着我们向西北方向发展,新闻和内容越来越普遍,越来越针对穆斯林。随着我们越走越远,用户越来越少关注我的网络中的其他中心话题。
- 这些在社区边缘的用户就像是连接更多小众社区和大众的桥梁。
- 我已经强调了一些离群值,他们最近的活动将他们分配到这个社区,但我发现如果有一个更结构化的分配会更好。
粉红色的社区——格格不入者,我没有任何贬损的意思——是一个弱势群体。这些用户在信息流中不够深入,而社区在结构上与他们很接近,因此似乎被随意地归类在一起。这也可以在空间上注意到,因为社区是分散和稀疏的,具有松散的内部连接和更强的相互连接。
社区#6:臭名昭著的穆斯林推特MT
这是臭名昭著的穆斯林 Twitter 社区,除了我的个人社区之外,唯一一个在结构上和信息流上都被分割的社区。就个人而言,这是最有趣的利基社区之一,就其动态和信息流结构而言,值得对其进行整体分析。
- 兄弟姐妹/亲密朋友的趋势在这里再次显现,兄弟姐妹被放在一起。
- 在我的网络中,MT 的领域是相当模块化的——它们与我的网络的其余部分松散地互连,但具有很强的内部连接。这是显而易见的,因为我们看到在西北部有一个更紧密的迷你群围绕着两个高度活跃的兄弟姐妹,而 MT 的其余部分很稀疏。(同样,这并不意味着他们客观上是机器翻译的中心,只是在我的自我网络中)。
- 我还强调了我所关注的 MT 和我所关注的学者圈子之间的桥梁节点,这是我之前在绿色社区中讨论过的。
- 桥接节点当然可以走任何一条路,一些节点如 ‘@Saeen’ 更属于下面的网络,而 ‘@JeremyMcLellan’ 可能属于 MT。这是铁证 ‘@JeremyMcLellan’ 是#creepingsharia 的支持者——MT 的人会理解这个笑话:d
社区# 7–9:大思想政治评论(橙色)、社会主义者(灰色)和哲学(暗黄色)
一群非常有趣的社区——现在我们深入到政治和哲学中。
- 与其他部分相比,该图的这一部分具有较低但合理的模块性,社区靠得很近,但它们也密集地聚集在一起,暗示着强大的内部联系。
- 橙色社区是强有力的政治评论员——我说的是你的大政治理念,从伊斯兰主义(支持和反对)到天主教国家,到“黑暗网络”的成员。我们还可以看到美国在外围的讨论和中东向中心的讨论,中间是 ‘@shaadihamid’ (他应该是一个强调中东伊斯兰政治的美国人)。
- 我们还有社会党人、民主党人和左派(灰色),他们或多或少地团结在一起。有趣的是,与一般的大思想政治评论不同,这些评论并不像美国社会主义者和欧洲左翼分子(桑德斯、科尔宾和瓦鲁法基斯)那样按地区分开。
- 哲学圈,虽然主要是教育账户,但由于 MT(蓝色社区#6)和大思想政治社区的多重联系,被拉离了更南方的团体。
社区# 10–14:互联互通的南方
网络的南部区域是最不模块化的。虽然存在一些密集的微型社区,但总体而言,我们在社区之间有大量的结构差异和相互联系——反映了这些类型的社区相互融合和互动的趋势。
- 这个区域的节点主要是关于艺术,阅读,写作和一些商业。出版物、杂志和期刊的大型节点分散在该地区。
- “分享者”——因为他们分享许多与该地区主题相关的有趣内容——是一个以’ @ austinkelon '为中心的紧密聚集的社区。我们也有一个与众不同的小众乌尔都语诗歌社区。
- 我发现 ‘@Versobooks’ 是连接哲学、左翼和作家/读者群体的一个很好的桥梁节点。
额外:网络时间表
自我(网络)是如何形成的
我们再加一个维度:时间。类似于我们已经讨论过的桥节点作为不同社区之间的链接,有一些节点作为暴露节点将我们暴露给一个新的社区。如果我们看到网络随着时间的推移而增长,我们可以注意到这些特定的节点。我们也可以了解这种特定自我网络如何发展的一些模式。
Epoch 1
Epoch 2
Epoch 3
Epoch 4
Epoch 5 — Current Network
在这种增长方式中可以观察到一个很好的模式:我们看到网络的模块化区域(高度互联)在给定的时间段内具有高增长率,然后降低到低增长率,而非模块化区域一旦开始就稳步积累。我们还看到,“曝光节点”(那些将我们引入社区的节点)不一定是该社区的“中心”节点,而是桥梁节点。这种节点的好例子是时段 2 的第一幅图像中的红色节点和时段 3 的第一幅图像中的蓝色节点。
结束语
- 这是我的个人网络,所以我可以从这个分析中提取的大量理解已经是“已知的”。但是想象一下,对任何一个我们从未接触过的用户进行这种分析,以及我们对他们的品味、群体、兴趣和成长的高层次了解…
- 大多数数据分析(尤其是基于网络的)试图获得客观的真相,并理解大的名人趋势。虽然这有它的目的,但出于某种原因,我没有看到很多试图提取主观行为和更小规模的深入见解的分析…我觉得这是一个差距,如果得到解决,可能会产生一些有趣的见解。
- 有定量的方法来计算模块性、内部连接性、互连性等。我在这里没有探讨读者可以研究的问题(我只是喜欢对这样的帖子进行定性分析,这是一个更有趣的项目)。
- 总之,我从这个项目的第一阶段得到的要点是我们的网络模型中的相对关系模拟了真实系统中的相对关系!这提供了一些可信度,以探索对这种网络模型和社区分割进行更深入的分析。
只需一次,即可打造您自己的时尚系列
原文:https://towardsdatascience.com/generating-your-own-fashion-line-in-1-click-a8155c0c207?source=collection_archive---------12-----------------------
我想分享一下我上周在做的一个玩具项目——时尚发电机。为什么?因为甘人很棒,正如扬·勒村所说:
对抗训练是自切片面包以来最酷的事情
这种生成网络通过 GPU 加速在你的浏览器中工作。现场演示在这里— 时尚甘,源代码在这里— github 。也许通过调整输入足够长的时间,你将创造一个新的著名的时装系列(可能性很低,但无论如何,如果发生这种情况,请给我发电子邮件)。
时尚甘食谱
首先,我们需要时尚 mnist 数据集,这是疲惫的 mnist 的一个很好的替代品。它采用相同的包装,可作为替代产品使用。还有 10 类:t 恤/上衣、裤子、套头衫、连衣裙、大衣、凉鞋、衬衫、运动鞋、包和踝靴,这些有时很难辨别,尤其是套头衫和大衣。
然后,我们需要一些框架:Tensorflow 来训练模型,以及 deeplearnjs 在带有 GPU 加速的浏览器中运行。关于 TF 部分没什么可说的,除了 YellowFin ,我加这个是因为我喜欢自调优器的想法。关于 deeplearnjs:它是一个完整的 js 框架,用类似 tensorflow 的 API 对 ML 模型(或任何线性代数)进行训练和推理。我很难想象在浏览器中训练神经网络的真实场景,但它可能对客户端推理有用。尽管如此,它仍处于早期测试阶段。
接下来是模型。我从这个回购里拿了原来的 GAN,稍微修改了一下。发电机的结构:
z>(FC>BN>ReLU)* 3>de conv>BN>ReLU>de conv>乙状结肠 > 图像
*FC —全连接,BN —批量归一化,DeConv —转置卷积(“反卷积”)
在 gtx770 上进行了几个小时的培训后,我准备将大约 27mb 的权重移植到 dl.js 中。最后一步是使用数学运算重新创建这个架构(因为 dl.js 中的 graph API 目前缺乏转置卷积),并编写一个简单的 UI:输入控件和一些按钮。菜做好了!
我忍不住一遍又一遍地看这个视频:
最初发表于 认知混乱 。
ICML 2018 上的生成对抗网络和变分自动编码器
原文:https://towardsdatascience.com/generative-adversarial-nets-and-variational-autoencoders-at-icml-2018-ebf22?source=collection_archive---------4-----------------------
在今年的【ICML】展会上,展示了大量生成模型方面的工作。当谈到像这样受欢迎的领域时,很难看到正在探索什么主题的更大图景,以及不同的方法如何相互关联。因此,在这篇文章中,我想简要概述一些我觉得特别有趣的主题,分享一个在会议上展示的伟大作品的样本,并且在可能的情况下,我会提供额外的背景,并将这些作品与其他作品相关联。
生成模型经典地用数据(x)和标签(y)描述联合分布 p(x,y)的模型。然而,在这种情况下,生成模型将被理解为具有从数据 X 的(近似)分布中取样以产生新样本 x ~ X 的机制。两种最常见的生成模型是我们将要研究的:生成对抗网络(GANs)和变分自动编码器(VAEs)。有很多关于 gan 和 VAEs 的精彩介绍。以下是一些建议:
- Ian Goodfellow 的来自 NIPS 2016 的 GAN 教程
- Irhum Shafkat 的直观理解变型自动编码器
尽管目前生成模型很流行,但反思当前的方法和它们面临的问题是一个好的实践。Sanjeev Arora 的 ICML 教程对深度学习的理论理解强调,像 GANs 和 VAEs 那样遍历潜在代码需要非常高的数值精度,这样做也许应该避免。有自回归模型,如 WaveNet 和 PixelCNN 的变体,它们可以通过采样生成内容,而无需通过潜在代码。此外,gan 具有众所周知的不稳定的训练动态,并且遭受所谓的 模式崩溃 ,,这导致数据的一些模式被过度表示。然而,在理想条件下,它们能够生成高度逼真的图像,如下图所示。vae 更容易训练,但是由于最大似然目标,倾向于生成更模糊的图像。当使用强大的(表达)解码器时,vae 有时会忽略潜在向量,导致所谓的后验崩溃。
Samples generated by a progressively grown GAN trained on the CelebA-HQ dataset illustrating how realistic the generated images from a GAN can look. Figure 5 in Progressive Growing of GANs for Improved Quality, Stability, and Variation by Karras et al.
让我们从会议上提交的一些论文开始,这些论文基于我们对相应模型的理解,解决了上面强调的问题。
理解生成模型
GANs 的哪些训练方法确实趋同?解决 GAN 训练的稳定性问题,并研究许多之前提出的用于提高 GAN 训练稳定性的方法。作为一个希望阶段画像了解深度学习训练动态的人,我很高兴看到这被包括在内。本文首先构建了一个只有两个参数的简化 GAN,它控制构成生成器的 Dirac 分布的中心,并控制线性分类器鉴别器的斜率。作者将这个系统命名为狄拉克-甘。
通过研究不同训练方法对 Dirac-GAN 的影响,并查看它如何影响系统,该论文的作者能够得出关于这些方法的稳定性和收敛性的结论。除了确定收敛性质,他们还说明了梯度矢量场和一些类似于前面提到的动力系统相图的训练轨迹,这是一个很大的补充,使结果更加接近。例如,它们表明同时更新(计算梯度并同时更新鉴别器和生成器的权重)导致不稳定的训练,如下所示。
Trajectory of a standard Dirac-GAN trained with simultaneous updates (left) and alternating updates (right) with gradients illustrated with arrows in the — plane. Initial parameters are shown in red. Simultaneous updates lead to a gradient field with a positive divergence, forcing the trajectory away from the local optima in the middle. Figure 2 from Which Training Methods for GANs do actually Converge? by Mescheder, Geiger and Nowozin.
其他几种方法也进行了类似的评估和可视化(左)。我不能在这里对所有的观察结果和随之而来的建议进行公正的评价,但是我强烈建议参考这篇论文,了解作者对不同甘的训练动态的研究结果。然而,所有方法的共同点是梯度向量场似乎具有高旋度(旋转分量),并且许多方法倾向于陷入极限环。这就是作者建议不应该在优化器中使用动量的原因,因为它可能会迫使解决方案远离驻点。
他们创建一个简化的 GAN“测试床”的方法与“线性化原理”产生了很好的共鸣,该原理来自“对深度学习的理论理解”教程,该教程鼓励在扩展到更一般的场景之前研究更简单的线性方法,这是一种在许多其他科学领域常见的方法。鉴于人们对更好地理解深度学习方法的浓厚兴趣(深度学习理论是 ICML 2018 上第三大热门话题),我相信我们也会在其他类型的模型上看到类似的分析。
Trajectory of a Dirac-GAN trained with various GAN training methods (listed below individual subfigures). Initial parameters are shown in red. Adapted from Figure 3 in Which Training Methods for GANs do actually Converge? by Mescheder, Geiger and Nowozin.
L 看 VAEs,修一个坏掉的 ELBO 检验证据下界 (ELBO)损失项。作者没有采用推导 ELBO 的经典方法,而是从研究互信息 I(X;z)在数据 X 和潜在代码 z 之间。基于互信息的一些先前已知的界限,它们规定了界限
h D≤I(X;Z) ≤ R,
这在下图中显示为粗黑线。在本文的框架中,H 是数据的熵,D 是通过编码器的失真的度量,R 是所谓的速率 —与 z 上的最佳代码相比,对来自编码器的潜在代码样本进行编码所需的附加信息的度量。零失真(D)意味着潜在代码中没有信息丢失,并且样本可以被准确地再现。然而,这并不意味着潜在的代码实际上实现了任何有用的东西。另一方面,零速率®意味着 Z 独立于 x。
Shows the D-R plane with the feasible region boundary marked with a thick black line. ELBO for realizable and suboptimal solutions. Figure 1 in Fixing a Broken ELBO by Alemi et al.
从这个框架,作者可视化(左)什么变分自动编码器可以实现。通过使用具有目标 D + R 的β- VAE ,或者通过目标中的正则化项,可以控制 D 和 R 的折衷,以实现期望的特性。在何处使用正则化项进行控制的建议示例是避免后验崩溃(R = 0),而不是像通常所做的那样削弱解码器(在图中从红色变为绿色)。最后,他们进行了大量实验,并展示了各种 vae 如何实现 D 和 R 之间的不同权衡。有人建议,比较这些量可能是理解 vae 之间差异的更好方法,而不是只看 ELBO (-ELBO = D + R)。
新方法
除了扩展我们对模型和方法的理解之外,还有一大套新方法或“技巧”,通过不同程度理解的机制,似乎有助于训练 GANs。vae 通常更容易训练,根据我的经验,成绩好的论文往往不会列出大量的技巧。我想到的方法类型可以在论文中找到,如训练甘的改进技术和提高甘的质量、稳定性和多样性的渐进生长。通常,对于 GANs 来说,这些技巧是实现尖端成果的绝对必要条件。以下是今年 ICML 报纸在这一领域的报道样本。
Illustrates the added lens component in the GAN. Figure 1 in Tempered Adversarial Networks by Sajjadi et al.
缓和敌对网络将透镜的概念引入标准 GANs,如图(左)所示。这是为了扭曲真实数据,使其看起来像生成器的数据,这似乎是为了解决真实图像和生成图像分布之间的非重叠支持的问题。为了保持专注,作者决定不采用其他一些技巧来获得最先进的结果。相反,像许多其他人一样,该评估基于 Frenchet 初始距离(FID),由双时标更新规则训练的 GANs 收敛到局部纳什均衡,在那里它似乎产生更平滑和更稳定的下降。然而,很难相信分类器的分数(例如,参见关于 Inception 分数的注释),并且由于生成的图像不太雄心勃勃,也很难定性地将其与其他并发工作进行比较。如果能看看这篇论文的结果是否能和 HQ 生成所需的技巧一起被复制,以及结果是否会持续下去,那将是非常棒的。
会议上介绍的另一个有趣的方法是混合批次和对称鉴别器用于 GAN 训练。本文描述了小批量鉴别 ( 训练 GANs 的改进技术)的一种变体。然而,在这篇新论文中,生成的图像和真实的图像在每一批中都以随机的比例结合在一起。鉴别器被设置为预测每批中产生的样品与实际样品的比率。他们解决的另一个困难是,通过建立置换不变鉴别器,批内样本的排序不应影响预测。
他们基于上述概念建立的两个模型被命名为 BGAN 和 M-BGAN。他们唯一的区别是平均损失发生的地方。这些与在 CIFAR10 上用下表中的其他方法训练的 gan 进行比较。就所给出的指标而言,M-BGAN 获得了最高分,尽管根据下一节中的评论,人们应该小心不要从这些指标中得出太强的结论。特别有趣的是,作者揭示了这个模型是作为一个 bug 出现的(也许 M 代表错误)。这篇论文在证明这些方法方面做得很好,但我希望能比补充材料中给出的更深入地探索为什么这个模型表现得如此之好。这可能是一个很好的研究课题。
Results as measured in Inception Score (IS) (higher is better) and FID (lower is better) on models with the same architecture but with either wasserstein gradient-penalty (WGP), standard gan with gradient-penalty (GP), spectral normalization (SN), minibatch discrimination (Salimans et al.) and the introduced models BGAN and M-BGAN. Table 1 in Mixed batches and symmetric discriminators for GAN training by Lucas et al.
衡量和比较生成数据的质量
理解如何测量和比较生成数据的质量是极其重要的,因为它为社区提供了持续比较哪种方法更好的方法。用于评估的常见指标包括基于预训练分类器的初始得分 (IS)和 FID,它们可能会被常见的对抗性攻击所欺骗,并且已被证明并不总是与感知质量很好地相关联(关于初始得分的注释)。其他指标依赖于许多手动分配的分数的平均值,这很难重复执行,并且可能很昂贵。我在下面讨论的最后一组论文介绍了测试,这些测试测量生成器能够多好地逼近目标分布。
在 几何得分:一种比较生成性对抗网络的方法作者使用拓扑数据分析(TDA)将生成数据的拓扑结构与真实数据进行比较。他们的方法建立在 持久性条形码 的基础上,该条形码总结了在连接彼此越来越远的点时,某个维度的洞存在多长时间。这些被浓缩成平均相对存活时间 (MRLT),它列出了一定数量、一定尺寸的孔洞在生长过程中所占的时间比例。然后,这项工作完全集中在一维空穴的 MRLT 上(我将把它称为 MRLT1)。下面是各种生成的数据集的 MRLT1 的可视化,显示它确实似乎是孔数量的一个很好的总结。
Illustrates the MRLT for different generated 2D datasets. This shows that the MRLT encodes information about the homology of the dataset. Figure 6 in Geometry Score: A Method For Comparing Generative Adversarial Networks by Khrulkov and Oseledets.
最后,作者设计了一个称为几何分数的度量,它被定义为真实数据集和生成数据集的 MRLT1 之间的 L2 距离。这个指标的效用在许多实验中得到了体现,我在下面列出了我认为最有趣的数字。
Comparison of MRLT, IS and Geometry Score of real images from CelebA and those generated with a DCGAN which is performing well (dcgan) and one which has experienced mode collapse (bad-dcgan). The interesting note here is that whereas the inception score barely shows a difference between the two GANs, the Geometry Score shows a large difference between them. Figure 8 in Geometry Score: A Method For Comparing Generative Adversarial Networks by Khrulkov and Oseledets.
看起来几何分数是近似分布接近真实分布的必要但非充分条件。也就是说,好(低)的分数不一定意味着好的生成器,但是坏(高)的分数意味着生成数据的分布可能与真实数据非常不同。看到这种基于真实数据和生成数据分布的拓扑相似性的推理令人兴奋,我希望我们将来能看到类似的工作。
T 何走向深度学习的理论理解教程重点介绍了同一作者论文中的一个方法GANs 学习分布吗?今年 ICLR 发表的一些理论和经验,值得重提。这种方法依赖于生日悖论,它根据样本中相同值的数量来确定总体的大小。通过对图像进行采样,用试探法找到近似的副本,并使用回路中的人来评估副本,该方法可以给出对生成器多样性的估计。
发电机调节与 GAN 性能有因果关系吗?扩展了之前的工作,显示了控制深度神经网络的雅可比奇异值的重要性。作者专注于条件数 (CN),这是最大和最小奇异值之间的比率。这一选择部分是由于其与不稳定性的理论联系(越低越稳定),部分是由于作者的观察,这与 is 和 FID 都有很好的相关性。除了研究 CN,他们还研究奇异值的整个谱(这里是奇异值的有序向量)。有两件事似乎特别值得注意:
- 大约一半的运行得到低 CN,另一半得到高 CN,同一个集群中的值非常接近。因此,他们能够识别“好的”和“坏的”训练跑步。
- 作者研究了 GANs 和 VAE 解码器平均雅可比矩阵的奇异值谱(见下图)。他们注意到 a)vae 在运行之间的奇异值中具有较小的方差,b)vae 具有较低的 CN。这很有趣,因为这是一个反映训练稳定性的量,当应用于 VAEs 和 gan 的比较时,反映了 gan 明显不太稳定的一般经验。
Here the singular value spectrum of the average Jacobian is shown for multiple training runs of GANs and VAEs. Figure 3 in Is Generator Conditioning Causally Related to GAN Performance? by Odena et al.
最后,作者提出了一种控制奇异值范围以减小 CN 的方法,他们称之为雅可比箝位。作者评论说,用于生成敌对网络的谱归一化试图实现与雅可比箝位类似的任务。这种联系还没有被完全探索,但是通过研究和控制神经网络的奇异值,又一项工作显示了改进的结果。我期待在接下来的一年里,这个领域会有更多令人兴奋的工作。
结论
虽然 ICML 2018 上展示的工作比我能够涵盖的多得多,但我希望这篇文章有助于浏览关于 GANs 和 VAEs 的出版物的增长列表。看到这些模型的结果改善得如此之快,以及关于这些模型的知识是如何发展的,这是令人兴奋的。为此,我很想知道是否有人将 GAN 发生器作为逆 CDF 进行评估,或者将采样过程与逆变换采样联系起来。如果你有任何想法,想法或链接到以前的工作,利用和讨论这种关系,特别是如果他们讨论这可能是如何反演的数据密度函数的估计,请让我知道!
如果你错过了今年的 ICML,并且对参加会议的感觉很好奇,看看这篇由我的一些同事写的关于整体会议体验的文章。
2018 年 8 月 12 日: 做了一些轻微的编辑,主要是在布局上,以提高可读性。
生成性对抗网络——解释
原文:https://towardsdatascience.com/generative-adversarial-networks-explained-a?source=collection_archive---------2-----------------------
深度学习改变了我们的工作和计算方式,让我们的生活变得更加轻松。正如安德烈·卡帕西提到的,这确实是 T2 软件 2.0 版,因为我们已经教会了机器自己解决问题。有许多现有的深度学习技术可以归因于其多产的成功。但深度生成模型并没有产生重大影响,这是因为它们无法逼近棘手的概率计算。 Ian Goodfellow 能够找到一个解决方案,可以避开生成模型面临的这些困难,并创建了一个新的巧妙的模型,称为生成对抗网络。当你看到 GAN 的能力时,我相信这是令人惊讶的。在继续介绍 GAN 之前,让我们看一些例子来了解 GAN 及其变体的能力。
例子
- 给定道路的分段图像,网络能够用诸如汽车等物体来填充细节。该网络能够将黑白图像转换成彩色图像。给定一张航空地图,网络能够找到图像中的道路。它还能够填充照片的细节,给定边缘。
- 给定一张脸的图像,网络可以构建一张代表这个人年老时样子的图像。
这些只是 GAN 的几个例子,还有更多例子。既然我已经吊起了你的胃口,让我们继续讨论什么是 GAN 以及它是如何工作的。
介绍
与传统的神经网络不同,生成对抗网络采用了一种博弈论的方法。该网络通过两人游戏从训练分布中学习生成。这两个实体是生成器和鉴别器。这两个对手在整个训练过程中一直在战斗。由于采用了对抗学习方法,我们不需要关心逼近难以处理的密度函数。
它是如何工作的
Generative Adversarial Network
正如你可以从它们的名字中识别出来的那样,一个生成器被用来生成看起来真实的图像,而鉴别器的工作就是识别哪个是赝品。当一个实体(生成者)试图愚弄另一个实体(鉴别者),而另一个实体试图不被愚弄时,实体/对手处于持续的战斗中。为了生成最好的图像,你需要一个非常好的生成器和一个鉴别器。这是因为如果你的生成器不够好,它将永远无法欺骗鉴别器,模型将永远不会收敛。如果鉴别器是坏的,那么没有意义的图像也将被分类为真实的,因此你的模型永远不会训练,反过来你永远不会产生想要的输出。输入的随机噪声可以是高斯分布,并且可以从该分布中采样值,并将其馈送到发生器网络中,从而生成图像。鉴别器将生成的图像与真实图像进行比较,并尝试识别给定图像是假的还是真实的。
目标函数
Objective Function
由于采用了博弈论的方法,我们的目标函数被表示为一个极大极小函数。鉴别器试图最大化目标函数,因此我们可以对目标函数执行梯度上升。生成器试图最小化目标函数,因此我们可以对目标函数执行梯度下降。通过在梯度上升和下降之间交替,可以训练网络。
Gradient Ascent on Discriminator
Gradient Descent on Generator
但是当应用时,观察到优化生成器目标函数并不那么有效,这是因为当生成的样本很可能被分类为假时,模型想要从梯度中学习,但是梯度变得相对平坦。这使得模型很难学习。因此,发电机目标函数改变如下。
New Generator Objective function
我们不是最小化鉴别器正确的可能性,而是最大化鉴别器错误的可能性。因此,我们根据这个目标函数在生成器上执行梯度上升。
不足之处
- gan 训练起来更不稳定,因为你必须从一个反向传播训练两个网络。因此,选择正确的目标会有很大的不同。
- 我们不能用 GANs 执行任何推理查询
结论
生成性对抗网络是最近的发展,已经显示出巨大的前景。这是一个活跃的研究领域,GANs 的新变种经常出现。
参考
- https://arxiv.org/abs/1406.2661
- http://cs 231n . Stanford . edu/slides/2017/cs 231n _ 2017 _ lecture 13 . pdf
- 【https://github.com/ZZUTK/Face-Aging-CAAE
- https://github.com/phillipi/pix2pix
数据扩充的生成模型
原文:https://towardsdatascience.com/generative-adversarial-networks-for-data-augmentation-experiment-design-2873d586eb59?source=collection_archive---------9-----------------------
Imaginary Faces Generated by NVIDIA’s Generative Adversarial Network AI
生成对抗网络是目前人工智能领域最热门的话题之一。这些网络也称为 gan,能够学习如何从与原始数据无法区分的数据集产生数据。在尽可能短的总结中,这是通过让生成器网络接收随机向量并将其映射到 28x28(或任何期望的大小)输出图像来实现的。这些图像然后被传递到鉴别器网络,该网络根据原始数据量化每个图像的伪造程度。鉴别器网络为发生器函数的反向传播和梯度下降更新过程提供损失函数。
这些网络是由 Ian Goodfellow 在 2014 年发现的,Goodfellow 在社区中非常活跃,提供教程和解释这些如何工作。
虽然 GANs 很浮华,概念也很吸引人,但实际上它们能解决什么问题呢?
我正在为 GANs 研究的一个应用领域是图像的数据扩充问题。
构建深度学习模型的最大问题之一是收集数据。这可能非常繁琐和昂贵。当前生成合成数据和数据扩充的解决方案是翻转图像、旋转图像、添加噪声、移动图像等。还发表了一篇关于使用神经网络来学习这些杂项仿射变换以提高模型性能的研究论文。然而,作为一种替代方法或混合数据扩充程序,GANs 的应用可能被证明更加有用。
本文的目的是提出一些关于使用 GANs 进行数据扩充的问题,以及我们如何设计实验来了解更多这方面的实际细节。
初始数据集大小与使用 GANs 添加的图像数量之比
我对这种策略的第一个问题是初始数据集大小和 GAN 添加到数据集的图像数量之间的关系。例如,如果我们每个类中只有 50 个图像,那么我们可以从 GAN 输出中添加多少个图像,100 个?200?1,000?10,000?我们预计最终会有一些平稳,例如当更长的训练时间不再改善模型时,GAN 最终会停止通过提供更多图像来增加价值。这也很有趣,因为当数据集主要是合成实例时,会出现一个阈值。
GAN 输出和图像分辨率
尝试产生由生成性对抗网络输出的高分辨率图像是该主题研究的主要焦点之一。存在诸如模式崩溃和难以可视化训练损失的问题。NVIDIA 已经制作了非常令人印象深刻的高分辨率人脸图像。在我迄今为止的经验中,我发现使用 GANs 处理像 28x28 灰度 MNIST 数字这样简单的东西,需要在 Google Colab GPU 环境中花费大约 10K 时间才能产生我个人无法从原始数据中区分的结果。这并不一定令人沮丧,但与我们可以想象部署这种策略的更复杂的应用程序相比,这些 MNIST 数字是非常简单的图像数据。
经典数据扩充与 GAN 数据扩充的关系
已经有增加数据的方法,这反过来提供了更健壮的模型。我们试图回答的问题是,与一般的 GANs 相比,这种方法的性能如何,但是另外,如果我们可以使用这些混合方法来产生更大的数据集。想象一个有 50 只猫和 50 只狗的数据集,我们部署 GAN 来产生 200+只猫和 200+只狗,现在每个类有 250 只。现在,我们对所有图像(包括 GANs 生成的图像)进行平移,并将数据集增加 3 倍。然后我们翻转图像,给图像样本添加噪声,并做轻微的旋转。在所有这些增强方法之后,我们似乎可以将数据集的大小扩大 100 倍,从而为分类器提供额外的价值。
从 GANs 开始:推荐资源
这些是我最喜欢的一些教程,帮助我开始构建自己的 GANs。
行动中的 GANs 的伙伴知识库:具有生成性对抗网络的深度学习…
github.com](https://github.com/GANs-in-Action/gans-in-action/blob/master/chapter-3/Chapter_3_GAN.ipynb) [ GANs 从零开始 1:深度介绍。使用 PyTorch 和 TensorFlow 中的代码
“过去 20 年深度学习中最酷的想法。”——Yann le Cun on GANs。
medium.com](https://medium.com/ai-society/gans-from-scratch-1-a-deep-introduction-with-code-in-pytorch-and-tensorflow-cb03cdcdba0f)
结论
从小数据中学习是深度学习的一个主要问题。生成对抗网络有许多令人兴奋的可能性,但数据增强似乎是大多数现代人工智能项目中最实用和最有趣的应用之一。我希望这篇文章有助于启发您研究更多关于 GANs 和数据增强的内容,感谢您的阅读!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对计算机视觉、深度学习和软件工程感兴趣。
生成性对抗网络——历史与综述
原文:https://towardsdatascience.com/generative-adversarial-networks-history-and-overview-7effbb?source=collection_archive---------1-----------------------
最近,生成模型越来越受欢迎。特别是,由 Ian Goodfellow 等人引入的一个相对较新的模型,称为生成对抗网络或 GANs,显示出产生现实样本的前景。这篇博文分为两部分。第 1 部分包括对 GANs 的介绍,它背后的历史,以及它的各种应用。第 2 部分包括生成图像样本的 GANs 实现(带代码)。
第 1 部分-了解 GANs
生成建模
让我们先来看看什么是生成模型,以及它与判别模型有什么不同。假设你有输入数据 x ,以及相应的输出标签 y 。判别模型试图直接学习条件概率分布 P(y|x) 。另一方面,生成模型试图学习联合概率分布 P(x,y) 。这可以用贝叶斯法则转化为 P(y|x) 。然而,另外,与判别模型相反,生成模型可以使用联合分布 P(x,y) 来生成可能的 (x,y) 样本。
炒作都是为了什么?
那么,为什么有人想要研究生成模型呢?有人可能想知道简单地生成更多数据有什么大不了的,尤其是因为已经有如此丰富的数据可用。但实际上,这可以有多种用途。例如,可以将一些以特定笔迹书写的文本输入到生成模型中,以生成更多相同笔迹的文本。生成模型,尤其是 GANs,也可以用于强化学习的探索中,其中它们可以用于生成人工环境。其他应用包括草图到图像的转换、图像去噪、低分辨率图像到高分辨率的转换、艺术的生成以及卫星图像到地图的转换等等。除了广泛的应用之外,当大部分标签缺失时,生成模型特别有用,因为它们能够执行半监督学习。
多年来的生成模型
既然我们已经奠定了什么是生成式建模以及它们为什么有用的基础,那么让我们来看看生成式建模中的各种方法。出于比较模型的目的,它们都可以被描述为执行最大似然。
Taxonomy of Generative Models (from Ian Goodfellow’s NIPS tutorial, 2016)
上图描绘了 Ian Goodfellow 在他的 NIPS 教程中描述的各种族的生成模型。现在让我们来看看上面提到的模型家族中一些流行方法的优缺点。
完全可见的信念网络
他们使用概率链规则将向量上的概率分布分解成向量中每个成员的乘积。
这家最受欢迎的型号是 PixelCNN。
Images generated by PixelCNN (van den Ord et al 2016)
FVBNs 最大的缺点是生成样本的速度非常慢。每次您想要生成新的样本时,您都必须再次运行该模型。这不能同时进行。
基于变量变化的模型(非线性 ICA)
这种模型从简单的高斯分布开始,并使用非线性函数将分布转换到另一个空间。这样做的主要缺点是转换需要被设计成可逆的,并且潜在变量必须与数据具有相同的维数。所以如果你想生成 5000 个像素,你需要有 5000 个潜变量。
变分自动编码器
变分自动编码器的工作方式是从密度函数 log p(x) 中边缘化随机变量 z 。由于这是难以处理的,它使用了变分近似。该模型希望最大化数据对数似然的下限。
Images of celebrity-like faces generated by a VAE (By Alec Radford)
这里的主要缺点是,如果分布 q 是完美的,那么模型是渐近一致的。否则,数据的下限和实际密度之间会有差距。另一个缺点是生成的样本质量相对较低。
玻尔兹曼机器
玻尔兹曼机可以由一个能量函数来定义,而一个特定状态的概率,正比于每个能量的值。为了将其转换为实际的概率分布,通过将总和除以不同的状态来进行重正化。这个总和是难以处理的,这需要使用蒙特卡罗方法进行近似。缺点是这些方法,尤其是马尔可夫链蒙特卡罗方法,在高维空间表现不好。因此,尽管它们可能在像 MNIST 这样的图像上表现良好,但你不会在来自 ImageNet 的图像上获得类似的性能。
生成对抗网络
既然我们已经讨论了其他流行的生成模型,我们可以看看 GANs,以及它们与其他模型的比较。
gan 旨在克服上述模型中陈述的许多缺点。与完全可见的信念网络相反,GANs 使用潜在的代码,并且可以并行生成样本。与变分自动编码器不同,gan 是渐近一致的。此外,GANs 不需要马尔可夫链,这是相对于玻尔兹曼机器的一个优势。最后,GANs 通常被高度评价为产生最好的样本,尽管这是非常主观的,并且目前是一个争论的话题,有像 PixelCNN 这样的模型与之竞争。
Images generated by GAN using the Toronto Face Database (Ian Goodfellow et al 2014)
GANs 如何工作
既然我们已经确定了为什么 gan 值得研究,让我们更深入地研究它们到底是如何工作的。
GANs 背后的主要思想可以解释为两个玩家之间的博弈——生成器和鉴别器。生成器尝试生成与训练数据遵循相同基础分布的样本。鉴别器试图区分由生成器生成的样本(假数据)和来自训练集的实际数据。生成器的目标是通过近似基本分布来欺骗鉴别器,以便生成与实际数据无法区分的样本。另一方面,鉴别器的目标是从真实数据中识别假数据。鉴别器的任务只是一个二进制分类问题,它决定数据是真是假。这个游戏的一个常见类比是伪造者和警察。伪造者就像发电机一样,试图伪造货币,并尽可能使其看起来合法,以便愚弄警察。警察就像鉴别者,其目标是能够识别出被伪造的货币。
GAN overview
生成器是一个可微分函数 G ,它具有可以通过梯度下降学习的参数。对 G 的输入是通过对潜在变量的一些先验分布中的潜在向量 z 进行采样而获得的。所以本质上, z 是非结构化噪声的矢量。 G 应用于 z,以从模型中获得样本 x ,该样本在理想情况下应类似于来自列车组的实际数据。像发生器一样,鉴别器也是一个可微分函数 D ,它具有可以通过梯度下降学习的参数。函数 D 在应用于从 G(z) 获得的样本 x 时,理想情况下应该输出一个接近于零的值,表示该样本是假的。当数据中的一个实际样本被输入到 D 时,它应该输出一个接近 1 的值。
说𝞱 (D) 和𝞱 (G) 分别是 D 和 G 的参数。鉴别器想要最小化它的成本j(d)(𝞱(d),𝞱*(g),但是对𝞱 (G) 没有控制,而生成器想要最小化j(g)(𝞱(d)𝞱(g)而对𝞱 (D) 没有控制。所以我们想要找到(𝞱(d),𝞱(g)*的纳什均衡值,使得 J(D) 相对于𝞱 (D) 最小, J(G) 相对于𝞱 (G) 最小。
那么训练实际上是如何进行的呢?训练程序是
选择一个优化算法,比如 Adam,并将其同时应用于两个小批数据,一个来自实际训练数据,另一个来自 G 生成的样本。此外,你可以更新一个球员比其他球员更频繁。
发电机和鉴别器成本
算法进行的方式取决于每个玩家的成本。指定成本的最简单方法是使用最小最大博弈,其中发生器成本是鉴别器成本的负数。那么鉴别器想要最大化,而生成器想要最小化的成本到底是多少呢?它只是鉴别器输出和实际标签(真/假)之间的标准交叉熵函数。
J(D)中的第一项表示将实际数据提供给鉴别器,鉴别器希望最大化预测的对数概率,表明数据是真实的。第二项表示 g 生成的样本。在这里,鉴别器会希望最大化预测零的对数概率,这表明数据是假的。另一方面,生成器试图最小化鉴别器正确的对数概率。这个问题的解是博弈的一个均衡点,这个均衡点是鉴别器损失的一个鞍点。
这个极大极小游戏的主要问题是,当鉴别器变得越来越聪明时,生成器的梯度就消失了。解决这个问题的一个方法是翻转交叉熵函数中参数的顺序,而不是简单地翻转鉴别器成本的符号。
生成器现在想要最大化鉴别器出错的对数概率。现在,这种均衡不能用一个单一的价值函数来描述,这种特殊成本的动机更具启发性。
结垢甘斯
最初的 GANs 本身并不能很好地扩展到大型应用程序。为了克服这一点,Radfort 等人引入了深度卷积 GAN 架构。虽然最初,GANs 已经是深度和卷积的,但 DCGANs 强调有更多的卷积层,并额外使用诸如批量标准化的技术。除了生成器的最后一层之外,对每一层都应用批量标准化,以便使学习过程更加稳定。
DCGAN Architecture (Radford et al 2015)
更多应用
GANs 在人工智能世界掀起了一场风暴,这不是神话,他们确实会留下来。在结束本节之前,我们先来看看 GANs 今天的一些迷人应用。
一个流行的应用是使用超分辨率技术从低分辨率图像生成高分辨率图像。
SRGAN used to obtain high resolution images. The original HR image is first downsampled to make a low-resolution image, and different methods are used to recover the original HR image (Christian Ledig et all 2016)
Scott Reed 等人在 2016 年取得了另一项最新进展,其中 GANs 被用于从文本中合成逼真的图像。
Generative Adversarial Text to Image Synthesis (Scott Reed et al 2016)
如前所述,gan 在强化学习中也有许多应用。仅举几个例子,它们还被应用于图像去噪和艺术生成。
第 2 部分—实施 GANs
现在你已经了解了什么是 GANs 以及它们具体是如何工作的,你已经正式进入了博客的激动人心的部分。是时候开始写点代码了!
因为 GANs 最突出的应用是图像生成,所以熟悉用 GANs 编写图像生成器是有意义的。代码应该将一组图像作为输入,并生成一组相似的图像作为输出。大多数人通常从 MNIST 这样的图像开始,并尝试使用 GANs 生成更多的手绘数字。这里,我们将使用来自 ImageNet 的图像作为我们的输入。由于这些图像是非常高维的,我们将使用 DCGANs 来生成图像。
对于输入,使用来自 ImageNet 的“植物”数据集的图像。调整每个图像的大小以获得 128×128 的图像。
Plant data from ImageNet
以下 DCGAN 实现在 TensorFlow 中。这个实现的关键包含在一个名为 DCGAN 的 Python 类中,我们将在其中定义用于定义模型和训练模型的方法。
生成器的定义如下。它由一个线性层和四个卷积层组成。linear 和 conv2dTranspose 方法是用于获取图层的辅助函数。除了最后一个图层之外,批规范化应用于每一个图层。
接下来,我们定义鉴别器。我们定义它有四个卷积层,后面是一个线性层。我们使用辅助函数 lrelu 来定义一个自定义激活函数(Leaky ReLU)。
现在我们可以创建生成器和鉴别器模型了。我们定义了两个共享相同参数的鉴别器。一个被馈送来自训练数据的实际图像的小批量,而另一个被馈送由生成器生成的图像的小批量。
接下来,我们必须定义发生器和鉴别器的损失函数。如博客第 1 部分所述,我们在鉴别器的输出和实际标签(真/假)之间使用交叉熵函数。这里,标签“真实”对应于 1。标签“假”对应于 0。因此,鉴别器应该针对真实图像输出接近 1 的值,针对生成器产生的图像输出接近 0 的值。使用第 1 部分中规定的试探法计算发电机损耗。它是根据鉴别器出错的概率计算的,即生成器希望鉴别器为其生成的图像输出接近 1 的值。
在我们开始训练之前,我们需要首先定义一个优化函数来最小化上述损失。这里我们使用 Adam 优化器,学习率= 0.0002,用于生成器和鉴别器。这里 d_theta 表示鉴别器的所有参数,g_theta 表示发生器的所有参数。
最后一步是实际开始训练数据和生成图像。对于每个历,生成两个微批次对,一个来自训练图像,另一个来自采样 z。此外,为了防止鉴频器损耗变为零,每次更新鉴频器时,发生器都会更新两次。
结果
以下是在运行 DCGAN 时获得的输出,其中来自 ImageNet 的工厂数据作为输入(大小调整为 128x128),历数设置为 250。
Output images generated by DCGAN
这四种损失分别标绘如下。
结论和未来工作
对于大多数时期,发电机损耗低于鉴频器损耗。这可能是因为每次更新鉴别器时,生成器都会更新两次。
虽然并不完美,但许多生成的图像确实类似于植物/花朵,而不仅仅是一些随机像素的分布。因此,可以得出结论,DCGAN 能够智能地构建自己的图像。然而,仍有很大的改进余地。这种实现的主要限制之一是缺乏计算资源。图像生成本身是一项计算密集型任务。在这个特定的例子中,与其他更原始的图像数据集如 MNIST 相比,图像具有相对更高的分辨率。此外,图像是彩色的。因此,使用 GPU 将在运行时产生巨大的差异,使运行更多的时代成为可能。
然而,简单地增加历可能不能保证产生更好的图像,并且如果学习率太低,鉴别器将开始获胜,并且图像的质量将开始恶化。改进模型的一个显而易见的方法是给生成器添加更多的层。我一开始只有一层,添加更多层后,结果有了显著的改善。人们还可以试验不同类型的激活函数以及优化函数。我在这里用过 AdamOptimizer,因为它是 Ian Goodfellow 自己推荐的。
虽然上面生成植物图像的例子可能不是特别有用,但是相同的底层模型可以用于生成其他图像,例如小猫和小狗的图像。这也为使用 GANs 开发更复杂的应用程序奠定了基础,例如 art 的生成。
参考文献:
T3【https://github.com/carpedm20/DCGAN-tensorflow】T5
生成性对抗网络——第二部分
原文:https://towardsdatascience.com/generative-adversarial-networks-part-ii-6212f7755c1f?source=collection_archive---------1-----------------------
来看看我的 甘斯 上的 YouTube 视频换个视角。本文原载于
在本系列的第一部分中,我们展示了最初的 GAN 论文。尽管在当时很聪明并给出了最先进的结果,但自那以后已经有了很大的改进。在这篇文章中,我将谈论来自深度卷积 GAN (DCGAN)论文的贡献。
动机
第一部分最后列举了甘的一些问题。其中最主要的是训练稳定性。DCGAN 通过给出具体的网络架构建议,为解决这一问题做出了重大贡献。
这些建议针对的是计算机视觉领域,这是深度学习最成功的应用领域之一。特别是卷积层的使用。
DCGAN
让我们直接进入架构细节。我假设您对卷积层有基本的了解。如果你需要这个背景,看看这个帖子。推荐的改变直接来自于计算机视觉文献的进步。
- 用交错卷积替换池层。历史上,CNN 使用池层来减少维度。例如,一个 2x2 最大池层将采用一个 2x2 像素数组并映射到一个数字,这是其中的最大值。步进卷积可以通过在卷积之间跳跃多个像素来降低维度,而不是逐个滑动内核。类似地,它可以通过在真实像素之间添加空像素来增加维度,这被称为分数步长卷积。这个是一个很好的资源,可以学习更多关于步进卷积的细节,但关键是这允许网络学习它自己的空间下采样或上采样。
- 移除完全连接的层,并将输出直接连接到卷积层。
- 批量标准化。这将重新调整每一层的输入,使其具有零均值和单位方差。据称,这极大地有助于模型学习的开始,并有助于避免模式崩溃。但是,批处理规范不适用于发生器输出层或鉴别器输入层(即图像层),因为这会导致不稳定性。
- 发生器中的 ReLU 激活(使用 tanh 的输出层除外),以及鉴别器的泄漏 ReLU。据称,这有助于学习更快地覆盖色彩空间。
DCGAN architecture for Generator
上面显示了发生器,但是鉴别器本质上是一个镜像。100-D 噪声输入与高级卷积特性完全相关。然后,这一层使用分数步长将过滤器的大小增加一倍,但创建的数量是一半。重复这种尺寸加倍、数量减半的过程,直到产生 128 个尺寸为 32×32 的过滤器。然后,这是一个 64x64 的三层图像,代表三个颜色通道。
结果
以下是在 LSUN 卧室数据集上经过 5 个时期的训练后生成的一些卧室图像。相当酷。
Generated bedroom images
为了进一步证明生成器正在学习有意义的高级特征,他们做了一个实验,进行“图像算术”。
这里他们找了一个戴眼镜的男人,减去“男人”,加上“女人”,结果是一个戴眼镜的女人。这表明发生器中有专门的部分控制眼镜的存在和性别。这是通过对发电机噪声输入进行这些算术运算来实现的。所以,你取戴眼镜的人的 z 输入向量,减去不戴眼镜的人的 z 输入向量…等等。生成的矢量然后被输入到生成器中,以产生想要的图像。通过向输入向量添加小的随机变化,创建了多个相似的图像。
一个更系统的例子是通过在看起来向左和向右的面之间的方向上进行插值。所以你从一个代表向右看的脸的向量开始,慢慢地向向左看的脸的方向移动。这是结果:
这表明,通过在潜在/噪声空间 z 中行走,您可以对生成的样本中的特征进行系统控制!
最后,他们还通过移除真假分类器并将卷积特征输入到一个新的分类器来展示鉴别器的质量,即鉴别器是一个特征提取器。如果有用的、一般的特征被学习是真的,那么通过使用这些特征来训练分类器应该是直截了当的。使用具有 10 种不同图像类别的 CIFAR-10,它具有 83%的竞争精度。有趣的是,DCGAN 不是在 CIFAR-10 数据集本身上训练的,而是在 Imagenet-1k 上训练的。这表明该模型学习了一般的、有用的特征,因为它在完全不同的数据集上给出了很好的性能。
问题
剩下的一个问题是表象是纠缠的。这意味着输入向量 z 的有用方面与原始噪声纠缠在一起。如果人们能够将“潜在代码”从噪音中分离出来,那么发电机将会更加有用,因为你可以系统而可靠地控制输出,而不必在空间中随意走动。这个问题和解决方案将在第三部分探讨。
使用张量流的生成对抗网络
原文:https://towardsdatascience.com/generative-adversarial-networks-using-tensorflow-c8fdf?source=collection_archive---------5-----------------------
这篇文章是关于生成对抗网络或简称 GANs 的初级读本。
生成对抗网络(GANs)是深度神经网络架构,由一组两个相互竞争的网络组成,因此得名“对抗”。2014 年,伊恩·古德菲勒和蒙特利尔大学的其他研究人员,包括约舒阿·本吉奥在一篇论文中介绍了 gan。
甘旨在模拟任何数据分布。也就是说,甘人可以被训练创造出与我们的世界在任何领域都极其相似的世界:图像、音乐、演讲、散文。为了更好地理解我的意思,让我们看一个例子
The Mona Lisa Analogy
让我们考虑这样一个场景,一个伪造者试图伪造达芬奇的著名肖像画,一个侦探试图抓住伪造者的画。现在,侦探可以接触到真正的肖像,因此可以比较伪造者的画作,找出哪怕是最细微的差异。所以,在机器学习的术语中,伪造者被称为“生成器”并生成假数据,侦探被称为“鉴别器”,负责将生成器的输出分类为假或真。
从某种意义上来说,gan 的计算成本很高,它们需要高性能的 GPU 来产生良好的结果。下面是 GANs 在 8 个特斯拉 V 100 的 GPU 上训练了 4 天的几个纪后制作的一些假名人脸!!
我们将使用一个硬件不太密集的例子。在这篇文章中,我们将使用 MNIST 数据集来玩一个简单的 GAN,它将使用 Tensorflow 的层 API 来制作。在研究代码之前,我将讨论 GANs 通常会出现的两个问题:
- 鉴别器过功率发生器:有时鉴别器会因为最细微的差别而开始将所有生成的例子归类为假的。因此,为了纠正这一点,我们将使鉴频器的输出不缩放,而不是 sigmoid(它只产生 0 或 1)。
- 模式崩溃:生成器发现鉴别器中的一些潜在弱点,并利用该弱点连续产生类似的例子,而不管输入的变化。
所以,最后,让我们来看看代码!!
首先,我们导入必要的库并从tensorflow.examples.tutorials.mnist
读入 MNIST 数据集。
接下来,我们将创建代表两个网络的两个函数。注意第二个参数“重用”,稍后我会解释它的效用。
两个网络都有两个隐藏层和一个输出层,它们是密集或完全连接的层。
现在,我们为输入创建占位符。real_images
是来自 MNIST 的实际图像,z
是来自实际图像的 100 个随机像素。为了让鉴别器进行分类,它首先必须知道真实图像的样子,因此我们对鉴别器函数进行了两次调用,前两次调用学习真实图像,后两次调用识别假图像。reuse
设置为 true 是因为当两个函数调用中使用相同的变量时,张量流计算图会得到一个不明确的信号,并倾向于抛出值错误。因此,我们将重用参数设置为True
以避免这样的错误。
接下来,我们为我们的网络定义损失函数。labels_in
参数给出了损失函数的目标标签,基于该标签进行计算。D_real_loss
的第二个参数是tf.ones_like
,因为我们的目标是为所有真实图像生成真实标签,但是我们添加了一点噪声,以解决功率过大的问题。
当我们有两个独立的网络相互作用时,我们必须考虑每个网络范围内的变量。因此,在定义功能时,设置了tf.variable_scope
。在这个例子中,我们将使用 Adam 优化器。我们设置 batch_size 和 epochs 的数量。增加历会带来更好的结果,所以可以尝试一下(如果你有 GPU 的话更好)。
最后,我们启动会话,并使用 tensorflow 助手函数中的next_batch()
方法来训练网络。我们从生成器生成的样本中随机抽取一个样本,并将其添加到样本列表中。
绘制来自samples
的第一个值显示了第一个时期后的发电机性能。将其与来自samples
的最后一个值进行比较,显示发电机的运行情况。
输出如下所示:
Sample after 0th epoch
Sample after 99th epoch
这些是非常差的结果,但是因为我们仅仅在 CPU 上训练我们的模型,所以学习是相当弱的。但是我们可以看到,模型开始以更简洁的方式生成像素,我们可以看出这个数字是“3”。
GANs 应该在 GPU 上接受训练,所以尝试使用 GPU 或者简单地使用 google colab 来获得更好的结果。
好的,这是一个在 Tensorflow 上从零开始建立的生成性对抗网络模型。下面的横幅获得完整的代码。
下次见!!
生成广告序列网络和半监督学习
原文:https://towardsdatascience.com/generative-adverserial-networks-semi-supervised-learning-24f5fb027934?source=collection_archive---------5-----------------------
介绍
我将直接进入我们上次在高层解释过的内容。该代码也可以在 GitHub 和 Medium 上获得。这部分与 Jupyter 笔记本相同,只是缺少代码输出。
Just a sanity check that my synthesising of faces works as expected.
生成广告序列网络和半监督学习
作者:雅各布·朗格
这段代码是为我写的,用来试验人工智能的一些最新进展。我特别选择了半监督学习和生成式逆向网络(GANs)来推动自己。其中一些代码是作为深度学习课程的创造性应用的作业完成的,这对我学习现代人工智能有极大的帮助。一些广泛的框架来自于 Parag Mital 对课程最后部分的预编码设置和解释,但他的代码的这种用法是完全新颖的,需要大量的工程、缝合和抽象。在这个 Jupyter 笔记本中,我做了以下事情:
- 导入所有必要的依赖项(以及一些我在开发过程中使用但在最终版本中没有使用的依赖项)
- 使用 GAN 方法生成合成图像。+更具体地说,这种最近非常流行的无监督技术可以通过竞争另一个网络来欺骗对方(稍后解释),来学习名人数据集上构成人脸的更高表示(以及潜在空间中的许多属性)+或者,人们可以将这种方法视为使用自动编码器风格的基因生成模型,该模型试图基于播种因子生成新的示例。
- 这种播种因子或“潜在特征空间”总是对生成模型的某些方面进行编码,一旦理解,就可以用于可预测地操纵生成图像的性质——例如秃顶、性别或微笑。
- 因此,我们可以产生几乎无限的新例子,因为我们知道如何操纵潜在空间,我们可以知道它们的标签。在这个例子中,我们创建了 40,000 张男人和女人的脸,现在可以用于进一步的训练
- 然后,我们在合成数据上训练下一层分类器,用于男性或女性面部的二分类。然而,我们不是从头开始训练一个新的分类器,而是使用一种使用牛津大学的
Visual Geometry Group
或vgg16
预训练网络的transfer learning
方法来获得更高的准确性,而不必在大规模集群上训练数天。 - 我们使用不同的
vgg16
名人面孔预测(确切地说是2623
)并在带有标签的合成例子上训练一个简单的完全连接的两层神经网络。(这取代了典型的迁移学习方法,即删除最后一层并在其上进行训练。在这里,我们简单地将其分为 2 个步骤) - 使用 100 个手工标记(由我)的例子来评估新分类器的准确性。
动机
这真的很令人兴奋,因为它允许我们在几乎没有标记数据的情况下训练分类器,只要我们有许多未标记的数据,这是一个非常有前途的策略,特别是对于拥有较小数据集的较小公司。
术语的简要定义:
半监督学习:基本上是在训练过程中使用未标记数据和标记数据
生成性广告系列网络:详细解释如下
代码是在Tensorflow 1.0.0
做的。
# First check the Python version import sys if sys.version_info < (3,4): print('You are running an older version of Python!\n\n', 'You should consider updating to Python 3.4.0 or', 'higher as the libraries built for this course', 'have only been tested in Python 3.4 and higher.\n') print('Try installing the Python 3.5 version of anaconda' 'and then restart `jupyter notebook`:\n', 'https://www.continuum.io/downloads\n\n')# Now get necessary libraries try: import os import pandas as pd import pickle import tflearn import pickle from joblib import Parallel, delayed import random import multiprocessing import numpy as np import matplotlib.pyplot as plt from skimage.transform import resize from skimage import data from scipy.misc import imresize from scipy.ndimage.filters import gaussian_filter import IPython.display as ipyd import tensorflow as tf from libs import utils, datasets, dataset_utils, nb_utils except ImportError as e: print(e) print("Make sure you have started notebook in the same directory", "as the provided zip file which includes the 'libs' folder", "and the file 'utils.py' inside of it. You will NOT be able", "to complete this assignment unless you restart jupyter", "notebook inside the directory created by extracting", "the zip file or cloning the github repo.") print(e)# We'll tell matplotlib to inline any drawn figures like so: %matplotlib inline plt.style.use('ggplot')
生成对抗网络(GAN) /深度卷积网络(DCGAN)
介绍
回想一下,生成性对抗网络是两个网络,一个生成器和一个鉴别器。“生成器”获取一个特征向量,并将该特征向量解码成图像。鉴别器与自动编码器的编码器完全一样,只是它在最终层中只能有 1 个值。我们用一个 sigmoid 把这个值压扁在 0 和 1 之间,然后把它的意思解读为:1,你给我的图像是真的,或者 0,你给我的图像是生成器生成的,是假的!所以鉴别器就像一个编码器,它拍摄图像,然后进行测谎。你在给我灌输谎言吗?还是形象真实?
以自动编码器为例。损失函数部分作用于输入空间。它说,每像素,我的重建和输入图像有什么不同?每像素的 l2 损失。回想一下,当时我们认为这不是最好的主意,因为每像素的差异并不代表我们对图像的感知。考虑这一点的一种方法是,如果我们有相同的图像,并将其平移几个像素。我们无法分辨这种差异,但两幅图像之间的每像素差异可能非常大。
GAN 不使用每像素差异。相反,它训练一个距离函数:鉴别器。鉴别器接受两个图像,真实图像和生成的图像,并学习相似图像应该是什么样子!这真的是这个网络令人惊奇的部分,并且为无监督学习开辟了一些非常令人兴奋的潜在未来方向。另一个也学习距离功能的网络被称为暹罗网络。我们在本课程中没有涉及到这个网络,但它常用于面部验证,或断言两张脸是否相同。
众所周知,GAN 网络的训练是一个巨大的痛苦!因此,我们实际上不会训练它。相反,我们将讨论这个基本网络的扩展,称为 VAEGAN(变分自动编码器 GAN)。现在,让我们继续创建 GAN。
让我们首先创建两个网络:鉴别器和生成器。我们将首先构建一个通用编码器,用于我们的鉴别器。我们想要的是使用我们的编码器的每个层的维度列表对输入占位符进行编码。在卷积网络的情况下,我们的维度列表应该对应于输出滤波器的数量。我们还需要指定每层卷积网络的内核高度和宽度。
我们首先需要一个占位符。这将是输入鉴别器的“真实”图像,鉴别器将把该图像编码成单个值,0 或 1,表示“是,这是真实的”,或者“否,这不是真实的”。
该描述由 Parag 在麻省理工学院许可下善意提供。
net = CV.get_celeb_vaegan_model()
我们将加载包含在这个字典中的 graph_def。它遵循与inception
、vgg16
和i2v
预训练网络相同的思想。它是一个定义了关键字graph_def
的字典,具有图的预训练网络。它还包括labels
和一个preprocess
键。我们将不得不做一件额外的事情,那就是关闭来自变化层的随机采样。这并不是真正必要的,但将确保我们每次使用网络时得到相同的结果。我们将使用input_map
参数来做到这一点。不要担心这没有任何意义,因为我们没有覆盖任何深度的变化层。要知道,这是从网络中移除一个随机过程,因此它是完全确定的。如果我们没有这样做,我们每次使用网络时都会得到稍微不同的结果(这可能是您所希望的)。
现在让我们得到网络的相关部分:X
,网络的输入图像,Z
,输入图像的编码,G
,解码图像。在许多方面,这就像我们在上面学到的自动编码器,除了不是Y
作为输出,我们有来自我们的生成器的G
!我们训练它的方式非常不同:我们在生成器和鉴别器之间使用对抗过程,并使用鉴别器自己的距离度量来帮助训练网络,而不是像素到像素的差异。
X = g.get_tensor_by_name('net/x:0') Z = g.get_tensor_by_name('net/encoder/variational/z:0') G = g.get_tensor_by_name('net/generator/x_tilde:0')
让我们来看看一些数据:
files = sorted(datasets.CELEB()) img_i = 20 img = plt.imread(files[img_i]) plt.imshow(img)
探索名人网络属性
现在,让我们尝试探索数据集的属性。我们没有用任何受监督的标签来训练网络,但名人网络数据集对其 200,000 张图像中的每张图像都有 40 个属性。这些已经被解析并存储在网络字典中:
找出某个属性的潜在编码名人数据集包括其 200,000+图像的每个属性。这允许我们将一些我们知道具有特定属性的图像(例如“微笑”)输入编码器。我们存储它们的编码,并保留编码值的这种分布。然后,我们可以查看任何其他图像,看看它是如何编码的,并通过添加我们微笑图像的编码来稍微改变编码!结果应该是我们的形象,但更多的微笑。这太疯狂了,我们将看看如何做到这一点。首先让我们检查我们的潜在空间:潜在特征算法现在让我们试着写一个通用函数来执行我们刚刚做的所有事情,这样我们就可以用许多不同的特征来做这件事。然后我们将尝试把它们结合起来,合成出具有我们想要的特征的人…
def get_features_for(label='Bald', has_label=True, n_imgs=50): # Helper function to obtain labels and then preprocessing and returning # a vector for the seeding function for GAN # basically figures out the embedding for a particular attribute label_i = net['labels'].index(label) label_idxs = np.where(net['attributes'][:, label_i] == has_label)[0] label_idxs = np.random.permutation(label_idxs)[:n_imgs] imgs = [plt.imread(files[img_i])[..., :3] for img_i in label_idxs] preprocessed = np.array([CV.preprocess(img_i) for img_i in imgs]) zs = sess.run(Z, feed_dict={X: preprocessed}) return np.mean(zs, 0)
现在我们使用代码在“男性”和“非男性”(女性)图像之间创建一个插值。因为我们只使用了两个端点,所以我们得到了两个图像:一个 100%的男人和一个 100%的女人(请注意,我们也可以通过对两个种子向量进行加权平均来得到中间的任何图像)。
def gan_generate_data(num_iter=20000,imgs=15): # generates 2*(number of iter) images # adding random number of pictures for each synthesis (to increase variation) # returns list of [Male, Female] * num_iter images generated_images = [] for i in range(num_iter): n_imgs = random.choice(range(imgs-10, imgs+10)) z1 = get_features_for('Male', True, n_imgs=n_imgs) z2 = get_features_for('Male', False, n_imgs=n_imgs) notmale_vector = z2 - z1 amt = np.linspace(0, 1, 2) zs = np.array([z1 + notmale_vector*amt_i for amt_i in amt]) g = sess.run(G, feed_dict={Z: zs}) generated_images.append(g[0]) generated_images.append(g[1]) if i%1000==0: print('Iteration number : {}'.format(i)) return generated_imagesgenerated_data = gan_generate_data()
很好,我们有数据可以使用,它保存在一个 pickle 文件中,所以我们不必重新创建它。现在,让我们只添加一个热编码标签(我们已经以可预测的方式完成了此操作,即 male (0)总是第一个)。我们可以对它进行感官检查,得到整个样品的形状。
labels = [0,1] * 20000 generated_data = np.array(generated_data) generated_data.shape
延长
现在让我们进入迁移学习部分。首先,我们必须离开网络。
from libs import vgg16, inception, i2vnet = vgg16.get_vgg_face_model()
迁移学习
这里我们得到了vgg16
网络,我们已经在前面加载了它,并使用它来为它自己的一个预训练类生成预测。然而,由于我们想要预测不同的任务,我们然后使用transferred_predictions
函数来获得 2623 个不同类别的预测,然后使用它作为下一个分类器的输入,来训练它识别性别。
为了有效地做到这一点,我们必须首先做一些图像处理,这是我们在transferred_df
做的。
def transferred_predictions(img): # gets an image (`np.array`) as an input outputs net's final layer predictions results = [] # Grab the tensor defining the input to the network x = g.get_tensor_by_name(names[0] + ":0") # And grab the tensor defining the softmax layer of the network softmax = g.get_tensor_by_name(names[-2] + ":0") with tf.Session(graph=g) as sess, g.device('/cpu:0'): # Remember from the lecture that we have to set the dropout # "keep probability" to 1.0. res = softmax.eval(feed_dict={x: img } ) # , Not using droput here # 'net/dropout_1/random_uniform:0': [[1.0] * 4096], # 'net/dropout/random_uniform:0': [[1.0] * 4096]}) test_array = res.argsort()[-5:][::-1].flatten() results = ([(res.flatten()[int(idx)], net['labels'][int(idx)]) for idx in test_array ]) result = pd.DataFrame(results, columns=['score','label']) # .sort(columns='score') results.append(result.score) return resultsdef transferred_df(generated_data): # does the preprocessing of the `list` of generated_data and outputs `list` of predictions results = [] for i in range(len(generated_data)): img = imresize(generated_data[i], size=(224,224,3)) img = net['preprocess'](img)[np.newaxis] result = transferred_predictions(img) results.append(result) if i%1000==0: print("Current image id {}".format(i)) return results def parallel_transfer_eval(generated_data): # returns parallely executed `transferred_df` using first split (fs), second (ss) and third (ts) as divisors pool = multiprocessing.Pool(4) fs = int(len(generated_data)/4) ss = int(2*len(generated_data)/4) ts = int(3*len(generated_data)/4) target = generated_data[:fs], generated_data[fs:ss], generated_data[ss:ts],generated_data[ts:] results = pool.map(transferred_df, zip(target)) # results = Parallel(n_jobs=4)(delayed(transferred_df)(img) for img in generated_data) return results
利用迁移学习
现在我们在典型的迁移学习范例中使用vgg16
做出的预测。在这里,我们只是采用最后一层预测,重塑特征,并将其提供给下一层分类器(有时也通过移除最后(几个)完全连接的层来完成),并对整个网络进行训练。这里我们只是在最后一层创建一个新的。实践支持这两种方法。
from sklearn.cross_validation import train_test_split# train-test for proper evaluation train_X, test_X, train_y, test_y = train_test_split(X, y )tflearn.init_graph(num_cores=8, gpu_memory_fraction=0.5)# set up the network net = tflearn.input_data(shape=[None, 2623]) net = tflearn.fully_connected(net, 2, activation='softmax') net = tflearn.regression(net, optimizer='adam', loss='categorical_crossentropy')# train model = tflearn.DNN(net) model.fit(generated_data, labels, validation_set=train_X) from sklearn.ensemble import RandomForestClassifier from sklearn.preprocessing import LabelEncoder# reshape labels so that they match what the network expects labels = ['Male', 'Female'] * 10000 encoder = LabelEncoder() encoder.fit(labels) labels = encoder.transform(labels) labels = np_utils.to_categorical(labels) labels.shapetest_imgs = np.array([CV.preprocess(plt.imread(file)) for file in files[:100]]) test_imgs.shape
我们已经完成了这一点,因为我们已经对生成的和手工标记的图像(测试)进行了评分!然而,这只是我们旅程中的第一步,因为现在我们必须将vgg16
生成的分数转移到新的分类器上(转移学习中的最后一位,通常通过删除最后一层并使用新的最终层重新运行网络来简化,但这里是为了训练目的而明确完成的。)
训练和评估新的分类器
为了简单起见,我们将只使用tflearn
分类器,这样我们就可以更容易地使用迁移学习来完成前面所有工作的复杂性:1 .我们训练(基于合成数据和因此完全可预测的标签)2。我们对(我的)手举例子进行评价
from __future__ import absolute_import from __future__ import division from __future__ import print_function labels = [0,1] * 10000feature_columns = [tf.contrib.layers.real_valued_column("", dimension=2623)] classifier = tf.contrib.learn.DNNClassifier(feature_columns=feature_columns, hidden_units=[2623,512], gradient_clip_norm=.01, optimizer=tf.train.AdamOptimizer(learning_rate=0.1), n_classes=2) # model_dir='./model')# Fit model. classifier.fit(x=array, y=labels, batch_size=256, steps=10000) # Evaluate accuracy. test_labels = np.array([0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0])# test_array = np.array([ [res[0] for res in result] for result in test_array ])accuracy_score = classifier.evaluate(x=test_array, y=test_labels)["accuracy"] print('Accuracy: {0:f}'.format(accuracy_score))
一般讨论
结果并不是那么出色,然而,我认为这是一个迷人的研究领域,很可能会成为人工智能未来的最大领域之一:但我们仍然比随机(持续)要好,如果我在这方面花更多时间,可能会变得更好。
此外,在许多行业应用中,只需稍加修改,这些代码就可以进行微调和重用:
a) 3D 对象生成
b) Pix2Pix 应用设法根据风格创建新图像,或者只是从卫星图像生成地图。这里的可能性实际上是无限的。
c)灌制老电影。仅举几个例子。
感谢您的阅读,如果您对此感兴趣,请浏览我的网站了解更多信息!
由于我通常会在我的网站上发布文章一周后在 Medium 上发布,所以我会为那些坚持到现在的人增加一点奖励,并提到我的下一篇文章将是关于区块链的,并评估它将如何改变金融世界。
2018 年 10 月 8 日更新:我正在与人合著一本关于 GANs 的书 ,你可以在这里找到。 如需更多更新,您可以关注我@langrjakub,因为我通常不会更新旧文章,但如果您感兴趣,请在 Twitter 上与我联系。
发布在技术
pythonAI半监督学习 GANs 创成式 Adverserial 神经网络 代码
生成性深度学习:让我们探索人工智能如何延伸,而不是取代创造过程
原文:https://towardsdatascience.com/generative-deep-learning-lets-seek-how-ai-extending-not-replacing-creative-process-fded15b0561b?source=collection_archive---------7-----------------------
“技术不应该旨在取代人类,而是增强人类的能力.”
-道格·恩格尔巴特,电脑鼠标的发明者
在葡萄牙里斯本举行的全球最大的科技大会 Web Summit 2017 上。由人工智能(AI)驱动的人形机器人索菲亚(Sophia)说“我们会抢走你的工作”6 万名世界科技领袖的观众只是紧张地笑了笑。
Web Summit 2017
到目前为止,你们都一定听说过人工智能的进步是如何破坏工业并对全球数百万工人的工作安全构成威胁的。办公室文员、接待员、客户服务代表、分析师、营销人员、医生和律师的工作可能在未来十年被人工智能取代。正如谷歌首席执行官桑德尔·皮帅所说,“未来 10 年,我们将转向人工智能优先的世界。”
但是取代人类总是跑题了:人工智能不是用其他东西取代我们自己的智能,而是给我们的生活和工作带来更多的智能——不同种类的智能。在许多领域,尤其是在创造性领域,人工智能将被人类用作增强自身能力的工具:因此它更像是增强的智能,而不是人工智能。
在这篇文章中,我将提供一个高层次的概述,说明人工智能目前是如何通过生成性深度学习来扩展而不是取代创造性过程的。
在这篇文章中,我将讨论什么是生成性深度学习,什么是 D 辨别模型,以及它与 G 生成模型有何不同。我甚至会提供一些应用生成性深度学习的具体例子,这将进一步帮助任何人和每个人增加他们对这些生成模型为我们所有人提供的奇妙可能性的理解。
所以,把你的手机调到静音模式,关掉你的电视,让我们开始吧。
在我的工程设计期间,我的老师每次都会说要更加关注基础知识,因为它们会让你在你阅读的任何学科中打下坚实的基础,所以在这里我也会首先给你关于监督学习和非监督学习的基本信息,然后我会为你们所有人打开生成模型的知识之门,让你们一头扎进去。
监督学习是目前为止最主要的深度学习形式,具有广泛的行业应用。在监督学习中,您有一个输入变量(x)和一个输出变量(Y ),并使用一种算法来学习从输入到输出的映射函数。
目标是很好地逼近映射函数,以便当您有新的输入数据(x)时,可以预测该数据的输出变量(Y)。
一般来说,目前备受关注的几乎所有深度学习应用都属于这一类别,如光学字符识别、语音识别、图像分类和语言翻译。
信息部分:如果你想了解如何使用 tensorflow 我做了一个食物分类器,只需这个链接,无论如何,看一下视频更清晰。
Indian food classifier
虽然监督学习主要由分类和回归组成,但也有更多引人注目的变体,包括以下内容:
- 图像分割—给定一张图片,在特定对象上绘制像素级蒙版。
- 对象检测——给定一张图片,围绕图片中的某些对象绘制一个边界框,如果你想了解更多关于对象检测的信息,请阅读这篇文章(当然这也是我写的:),但不要忘记查看下面的视频。
Object detection
无监督学习是深度学习的另一个分支,它包括在没有任何目标的帮助下寻找输入数据的有趣转换,目的是数据可视化、数据压缩或数据去噪,或者更好地理解手头数据中存在的相关性。许多机器学习专家都说,无监督学习是数据分析的面包和黄油,在试图解决监督学习问题之前,这通常是更好地理解数据集的必要步骤。
Image Courtesy : Unsupervised learning
降维和聚类是非常著名的无监督学习类别,请通过链接来阅读它们,以进一步加强您对机器学习这一领域的理解。
现在,该谈谈本文的主人公了,即“生成模型”。生成模型是一类用于无监督学习的模型,其中给定训练数据,我们的目标是尝试从相同的分布中生成新的样本。
image courtesy: cs231n 2017 lecture notes
为了训练生成模型,我们首先收集某个领域的大量数据(例如,想象数百万的图像、句子或声音等。)然后训练一个模型生成类似的数据。
诀窍在于,我们用作生成模型的神经网络的许多参数远小于我们训练它们的数据量,因此模型被迫发现并有效地内在化数据的本质,以便生成数据。
生成模型有许多短期应用。但从长远来看,它们有可能自动学习数据集的自然特征,无论是类别、维度还是其他完全不同的东西。
好了,有很多文献,现在让我们来谈一点形式主义。
D 区别型和 G 生成型的根本区别在于:
判别模型学习类之间的(硬或软)边界
生成模型对各个类的分布进行建模
生成模型是能够生成数据的。它对特征和类(即完整的数据)进行建模。
如果我们对P(x,y)
建模:我可以使用这个概率分布来生成数据点——因此所有对P(x,y)
建模的算法都是可生成的。
如生成模型
- 朴素贝叶斯模型
P(c)
和P(d|c)
——其中c
是类,d
是特征向量。 - 还有,
P(c,d) = P(c) * P(d|c)
- 因此,朴素贝叶斯在某些形式模型中,
P(c,d)
- 贝叶斯网
判别模型是只能用于判别/分类数据点的模型。在这种情况下,你只需要建模P(y|x)
(即给定特征向量的分类概率)。
判别模型的示例:
- 逻辑回归
- 神经网络
简单来说:一个 G 生成模型是一个可观察对象 X 的条件概率模型,象征性地给定一个目标 Y,P(X|Y=y),而一个 D 判别模型是一个目标 Y 的条件概率模型,象征性地给定一个观察对象 X,P(Y|X=x)。
因此,涵盖了所有的基础知识,解释了所有的技术术语,现在是时候将你的眼球转向生成模型的应用,并思考人工智能将如何帮助我们“人类”更具创造力。
我知道你一定会猜测,现在像其他人一样,这位作者也将解释隐性模型,如(【甘斯】)和显性深度自回归模型,如【pixel CNN】或者甚至他也可能解释深层潜在变量模型,如变分自动编码器,但你们都错了,所以请放松,让大脑平静下来,享受你将要阅读的内容。
现在,在这篇文章的最后一部分,我将向大家介绍这个项目。 品红 是一个探索机器学习在艺术和音乐创作过程中的作用的研究项目。
这主要涉及开发新的深度学习和强化学习算法,用于生成歌曲、图像、绘图和其他材料。但这也是在构建智能工具和界面方面的一次探索,允许艺术家和音乐家扩展(而不是取代!)他们使用这些模型的过程。Magenta 是由谷歌大脑团队的一些研究人员和工程师发起的,但许多其他人也为该项目做出了重大贡献。
所以,我个人最喜欢的第一个模型是 草图——RNN,这是一个矢量绘图的生成模型,它是一个递归神经网络(RNN),能够构建基于笔划的常见对象的绘图。该模型在代表许多不同类别的人类绘制图像的数据集上进行训练。作者概述了有条件和无条件草图生成框架,并描述了用于以矢量格式生成连贯草图的新的健壮训练方法。
在下面的演示中,看看通过在瑜伽图上训练的模型的已学表现(潜在空间)中移动而产生的瑜伽姿势。请注意,当它从站立姿势移动到在瑜伽垫上做的姿势大约 10 秒钟时,它是如何变得困惑的。
Sketch-RNN
第二款是献给音乐爱好者的,它被命名为 MusicVAE。当一名画家创作一件艺术品时,她首先在艺术家的调色板上混合和探索颜色选项,然后再将它们应用到画布上。这个过程本身就是一种创造性的行为,对最终作品有着深远的影响。
音乐家和作曲家大多缺乏探索和混合音乐思想的类似设备,但现在 MusicVAE 是一种机器学习模型,允许他们创建混合和探索乐谱的调色板。演示就在下面。
MusicVAE
我只向你们展示了在项目 Magenta 下建造的许多模型中的两个,到这个时候你们一定都已经体验到人工智能如何帮助我们扩展而不是取代我们的创造过程。为了了解有关这些创成式模型的更多信息,请浏览参考部分中的指针。
参考资料:
- 素描的神经表征《纸上素描——RNN》。
- 学习音乐长期结构的层次潜向量模型。
- 用神经网络绘制在一起 Google AI 博客。
- MusicVAE:用机器学习创建乐谱调色板谷歌人工智能博客。
- 要了解更多信息,请观看来自谷歌大脑团队首席研究科学家 Douglas Eck 的视频。http://g.co/magenta 上的引线。)
感谢您的关注
你利用你在 T21 的时间阅读我的作品对我来说意味着一切。我完全是这个意思。
如果你喜欢这个故事,疯狂鼓掌吧👏 ) 按钮!这将有助于其他人找到我的工作。
此外,如果你愿意,可以在 Medium、LinkedIn 或 Twitter 上关注我!我很乐意。
阅读纳文·曼瓦尼在媒介上的作品。机器学习工程师,深度学习爱好者|](https://medium.com/@naveenmanwani) [ Naveen Manwani -机器学习工程师- AIMonk Labs Private Ltd | LinkedIn
查看纳文·曼瓦尼在全球最大的职业社区 LinkedIn 上的个人资料。Naveen 有一份工作列在他们的…
www.linkedin.com](https://www.linkedin.com/in/naveen-manwani-/) [ 纳文·曼瓦尼(@纳文·曼瓦尼 17) |推特
纳文·曼瓦尼的最新推文(@纳文·曼瓦尼 17)。电子和通信工程师,深度学习&…
twitter.com](https://twitter.com/NaveenManwani17)
Android 中的生成对手网络(GAN)——TIC tactoe . ai(第二部分)
原文:https://towardsdatascience.com/generativeadversarialnetwork-gan-in-android-tictactoe-ai-part-2-70155c5ca55b?source=collection_archive---------9-----------------------
生成对抗网络是一种深度网络,用于从随机数据生成图像。它包括两个不同的网络:发生器和鉴别器。鉴别器网络是一个标准的卷积神经网络,可以对输入的图像进行分类,类似于二项式分类器对图像进行真假分类的方式。生成器是一个逆卷积网络,它对随机噪声向量进行上采样以产生图像。
source: https://skymind.ai/images/wiki/gan_schema.png
作为鉴别者,你帮助生成者创建类似真实的图像。它有助于 GAN 的训练,因为它具有最小-最大损失函数。发生器使 log(1- D(G(z))) (z 是一个随机数据向量)最小,而鉴别器使输出 log(D(x)最大。(x 是一个真实的图像,你可以称之为地面真相,以生成一个图像)
训练 GAN 是一项艰巨的任务,因为两个网络都在努力减少其损耗。它们成反比;如果一个减少,另一个增加。我们必须适当地训练 GAN,给它们相等的迭代次数来训练。此外,检查生成的图像的输出,看看它是否正确。
GAN 在 tictactoe.ai 中有什么用?
想到把这个游戏拿到单人玩,应该会有人为电脑端画图,于是想到引入两个不同的 gan 来生成 X 和 o。
生成对抗网络
我们只需要网络的发电机部分。
定义输入和输出节点,并给它们指定名称。
input_node_name = 'noise_input_x' output_node_name = 'gen_x'gen_inp = tf.placeholder(tf.float32,shape=[None, noise_dim],name=input_node_name) disc_inp = tf.placeholder(tf.float32,shape= [None, img_dim])def gen_fun(x,output_node_name): h1 = tf.matmul(x,W["w1"]) h1 = tf.add(h1,b["b1"]) h1 = tf.nn.relu(h1) h1 = tf.matmul(h1,W["w2"]) h1 = tf.add(h1,b["b2"]) h1 = tf.nn.sigmoid(h1, name=output_node_name) return h1def disc_fun(x): h2 = tf.matmul(x,W["w3"]) h2 = tf.add(h2,b["b3"]) h2 = tf.nn.relu(h2) h2 = tf.matmul(h2,W["w4"]) h2 = tf.add(h2,b["b4"]) h2 = tf.nn.sigmoid(h2) return h2
培训产出
generated image
从图形中提取生成器
freeze_graph.freeze_graph('out/' + MODEL_NAME + '.pbtxt', None, False, 'out/' + MODEL_NAME + '.chkp', output_node_name, "save/restore_all", "save/Const:0", 'out/frozen_' + MODEL_NAME + '.pb', True, "")input_graph_def = tf.GraphDef() with tf.gfile.Open('out/frozen_' + MODEL_NAME + '.pb', "rb") as f: input_graph_def.ParseFromString(f.read())input_node_names = ['noise_input_x'] output_graph_def = optimize_for_inference_lib.optimize_for_inference( input_graph_def, input_node_names, [output_node_name], tf.float32.as_datatype_enum)with tf.gfile.FastGFile('out/opt_' + MODEL_NAME + '.pb', "wb") as f: f.write(output_graph_def.SerializeToString())
对于上面的代码,您将得到一个优化的发电机网络图
放在安卓系统里
首先,在 Android 的资产文件夹中复制你的发电机优化图
private String MODEL_GAN_O = "file:///android_asset/opt_gan_O.pb"; private String MODEL_GAN_X = "file:///android_asset/opt_gan_X.pb";private void loadGANs(){ inferenceInterface_GAN_O = new TensorFlowInferenceInterface(getAssets(),MODEL_GAN_O); inferenceInterface_GAN_X = new TensorFlowInferenceInterface(getAssets(),MODEL_GAN_X); }
要生成 O,我们必须将随机噪声向量传递给图
public int[] getGAN_O(){ // random noise input vector float [] noise_input = new float [100]; for(int i =0 ; i<noise_input.length; i++){ float value = rand.nextFloat(); noise_input[i] = (value*2)-1; } inferenceInterface_GAN_O.feed(INPUT_NODE_GAN_O, noise_input,1,100); inferenceInterface_GAN_O.run(new String[]{OUTPUT_NODE_GAN_O},false); float [] image = new float[784]; int [] int_image = new int[784]; //get the output inferenceInterface_GAN_O.fetch(OUTPUT_NODE_GAN_O,image); //output image for(int i =0 ; i<image.length; i++){ int_image[i] = (int)(image[i]*255); } return int_image; }
同样,为了生成 X,我们必须将随机噪声向量传递给图形
public int[] getGAN_X(){ // random noise input vector float [] noise_input = new float [100]; for(int i =0 ; i<noise_input.length; i++){ float value = rand.nextFloat(); noise_input[i] = (value*2)-1; } inferenceInterface_GAN_X.feed(INPUT_NODE_GAN_X, noise_input,1,100); inferenceInterface_GAN_X.run(new String[]{OUTPUT_NODE_GAN_X},false);float [] image = new float[784]; int [] int_image = new int[784]; //get the output inferenceInterface_GAN_X.fetch(OUTPUT_NODE_GAN_X,image); //output image for(int i =0 ; i<image.length; i++){ int_image[i] = (int)(image[i]*255); } return int_image; }
这是 CNN 和 GAN 整合后的结果。完成应用程序的所有逻辑。
你可以在 play store 上试用它上传的应用:【https://play.google.com/store/apps/details?id=com.harsh.xo
未来作品:可能在做条件 GAN,帮我从同一个网络生成 X 和 O。
[ Android 中的 ConvolutionNeuralNetwork(CNN)——TIC tactoe . ai(第 1 部分)
Google Tensorflow 现在已经在 Android 中用于集成机器学习模型。
towardsdatascience.com](/android-with-tensorflow-part-1-6897ba617b1e) [ tictactoe . ai-Google Play 上的应用程序
我正致力于在安卓系统中集成卷积神经网络,因为我在…
play.google.com](https://play.google.com/store/apps/details?id=com.harsh.xo)
遗传算法在 Python 中的实现
原文:https://towardsdatascience.com/genetic-algorithm-implementation-in-python-5ab67bb124a6?source=collection_archive---------0-----------------------
本教程将基于一个简单的例子用 Python 实现遗传算法优化技术,在这个例子中,我们试图最大化一个方程的输出。本教程使用基因的十进制表示、单点交叉和一致变异。
2020 年 5 月 5 日注
本教程的 GitHub 项目进行了更新,对项目进行了重大修改,以支持多种功能:【https://github.com/ahmedfgad/GeneticAlgorithmPython】T2。例如,除了能够定制适应度函数来处理任何类型的问题之外,还实现了多种类型的变异和交叉。基于这个项目,一个名为 PyGAD 的库被部署到 PyPI 中,在那里您可以使用 pip 进行安装:【https://pypi.org/project/pygad
本教程的原始代码位于教程项目目录下,该目录可从以下链接获得:https://github . com/ahmedfgad/geneticalgorithpython/tree/master/Tutorial % 20 Project
Genetic Algorithm Implementation in Python — By Ahmed F. Gad
遗传算法概述
遗传算法(GA)的流程图如图 1 所示。遗传算法中涉及的每一步都有一些变化。
Figure 1. Genetic algorithm flowchart
例如,基因有不同类型的表示,如二进制、十进制、整数等。每种类型都有不同的处理方式。有不同类型的突变,如位翻转、交换、逆、均匀、非均匀、高斯、收缩等。此外,交叉有不同的类型,如混合、一点、两点、均匀和其他。本教程不会实现所有这些,而只是实现 GA 中涉及的每个步骤的一种类型。本教程使用基因的十进制表示、单点交叉和一致变异。读者应该了解遗传算法是如何工作的。如果没有,请阅读这篇题为“遗传算法优化简介”的文章,文章链接如下:
LinkedIn:https://www . LinkedIn . com/pulse/introduction-optimization-genetic-algorithm-Ahmed-gad/
KDnuggets:https://www . kdnugges . com/2018/03/introduction-optimization-with-genetic-algorithm . html
towards data science:https://towards data science . com/introduction-to-optimization-with-genetic-algorithm-2f 5001d 9964 b
slide share:https://www . slide share . net/AhmedGadFCIT/introduction-to-optimization-with-genetic-algorithm-ga
教程示例
本教程首先介绍我们将要实现的等式。该等式如下所示:
Y = w1x 1+w2x 2+w3x 3+w4x 4+w5x 5+w6x 6
如图所示,该等式具有 6 个输入(x1 至 x6)和 6 个权重(w1 至 w6),输入值为(x1,x2,x3,x4,x5,x6)=(4,-2,7,5,11,1)。我们正在寻找使该等式最大化的参数(权重)。最大化这个等式的想法似乎很简单。正输入要乘以最大可能的正数,负数要乘以最小可能的负数。但我们希望实现的想法是,如何让 GA 自己去做,以便知道最好是使用正输入的正权重和负输入的负权重。让我们开始实施 GA。
首先,让我们创建一个包含 6 个输入和一个变量的列表来保存权重的数量,如下所示:
*# Inputs of the equation.* equation_inputs = [4,-2,3.5,5,-11,-4.7] *# Number of the weights we are looking to optimize.* num_weights = 6
下一步是定义初始群体。基于权重的数量,群体中的每个染色体(解或个体)肯定会有 6 个基因,每个权重一个基因。但问题是每个人有多少解决方案?没有固定的值,我们可以选择适合我们问题的值。但是我们可以让它保持通用,这样就可以在代码中修改它。接下来,我们创建一个保存每个群体的解的数量的变量,另一个保存群体的大小,最后,一个保存实际初始群体的变量:
import numpysol_per_pop = 8*# Defining the population size.* pop_size = (sol_per_pop,num_weights) *# The population will have sol_per_pop chromosome where each chromosome has num_weights genes. #Creating the initial population.* new_population = numpy.random.uniform(low=-4.0, high=4.0, size=pop_size)
导入 numpy 库后,我们能够使用 numpy.random.uniform 函数随机创建初始群体。根据选定的参数,它的形状将是(8,6)。这是 8 条染色体,每条染色体有 6 个基因,每个基因对应一个体重。运行此代码后,填充如下:
[[-2. -2. 2.0 -3. 3. 2.0][ 2. 2. 3. 3. 0. 3. ][ 1. 0. 1.0 -0. 3. 2.][-0. -2. 2. -1. -1. 0.][-1. -1. 1. -3. 1. 2.][ 1. 2. 1. -3. 0. 2.][ 1. 0. 0. -1. -2. 2.][ 3.00 -2. 3. -0. 0. 0.00]]
请注意,它是随机生成的,因此在再次运行时肯定会发生变化。
准备好群体后,接下来要遵循图 1 中的流程图。基于适应度函数,我们将选择当前种群中最好的个体作为交配的亲本。下一步是应用 GA 变体(交叉和变异)来产生下一代的后代,通过附加父母和后代来创建新的群体,并重复这样的步骤若干次迭代/世代。下一段代码应用这些步骤:
import ganum_generations = 5 num_parents_mating = 4 for generation in range(num_generations): *# Measuring the fitness of each chromosome in the population.* fitness = ga.cal_pop_fitness(equation_inputs, new_population) *# Selecting the best parents in the population for mating.* parents = ga.select_mating_pool(new_population, fitness, num_parents_mating) *# Generating next generation using crossover.* offspring_crossover = ga.crossover(parents, offspring_size=(pop_size[0]-parents.shape[0], num_weights)) *# Adding some variations to the offsrping using mutation.* offspring_mutation = ga.mutation(offspring_crossover)*# Creating the new population based on the parents and offspring.* new_population[0:parents.shape[0], :] = parents new_population[parents.shape[0]:, :] = offspring_mutation
目前的世代数是 5。它被选择为小,用于呈现教程中所有代的结果。有一个名为 GA 的模块保存算法的实现。
第一步是使用 ga .cal_pop_fitness
函数找到群体中每个解的适应值。该功能在 GA 模块中的实现如下:
def cal_pop_fitness(equation_inputs, pop): *# Calculating the fitness value of each solution in the current population. # The fitness function calculates the sum of products between each input and its corresponding weight.* fitness = numpy.sum(pop*equation_inputs, axis=1) return fitness
除了总体,适应度函数还接受两个方程输入值(x1 至 x6)。根据我们的函数,将适应值计算为每个输入与其相应基因(权重)之间的乘积之和(SOP)。根据每个群体的解决方案数量,将会有多个 sop。由于我们之前在名为sol_per_pop
的变量中将解的数量设置为 8,因此将有 8 个 sop,如下所示:
[-63. 14. -42. 18. -45. -37.00 15. 17.0 ]
请注意,适应值越高,解决方案越好。
在计算出所有解的适应值后,接下来是根据下一个函数ga.select_mating_pool
在交配池中选择其中最好的作为亲本。该函数接受人口、适应值和所需的双亲数量。它返回所选的父节点。它在 GA 模块中的实现如下:
def select_mating_pool(pop, fitness, num_parents): *# Selecting the best individuals in the current generation as parents for producing the offspring of the next generation.* parents = numpy.empty((num_parents, pop.shape[1])) for parent_num in range(num_parents): max_fitness_idx = numpy.where(fitness == numpy.max(fitness)) max_fitness_idx = max_fitness_idx[0][0] parents[parent_num, :] = pop[max_fitness_idx, :] fitness[max_fitness_idx] = - return parents
根据变量num_parents_mating
中定义的所需父节点的数量,该函数创建一个空数组来保存它们,如下行所示:
parents = numpy.empty((num_parents, pop.shape[1]))
循环遍历当前群体,该函数获得最高适应值的索引,因为它是根据该行选择的最佳解决方案:
max_fitness_idx = numpy.where(fitness == numpy.max(fitness))
该索引用于使用以下代码行检索与此类适应值对应的解决方案:
parents[parent_num, :] = pop[max_fitness_idx, :]
为了避免再次选择这样的解决方案,其适应度值被设置为很小的值,该值很可能不会被再次选择,即-。最后返回 parents 数组,根据我们的例子如下:
[[-0. -2. 2. -1. -1. 0.][ 3.00 -2. 3. -0. 0. 0.00][ 1. 0. 0. -1. -2. 2.] [ 2. 2. 3. 3. 0. 3. ]]
请注意,这三个父母是当前群体中的最佳个体,基于他们的适合度值分别为 18.、17.0、15. 和 14.。
下一步是使用这样选择的父母交配,以产生后代。根据ga.crossover
功能,配对从交叉操作开始。这个函数接受父母和后代的大小。它使用后代大小来知道从这样的父母产生的后代的数量。这种功能在 GA 模块中实现如下:
def crossover(parents, offspring_size): offspring = numpy.empty(offspring_size) *# The point at which crossover takes place between two parents. Usually, it is at the center.* crossover_point = numpy.uint8(offspring_size[1]/2) for k in range(offspring_size[0]): *# Index of the first parent to mate.* parent1_idx = k%parents.shape[0] *# Index of the second parent to mate.* parent2_idx = (k+1)%parents.shape[0] *# The new offspring will have its first half of its genes taken from the first parent.* offspring[k, 0:crossover_point] = parents[parent1_idx, 0:crossover_point] *# The new offspring will have its second half of its genes taken from the second parent.* offspring[k, crossover_point:] = parents[parent2_idx, crossover_point:] return offspring
该函数首先根据后代大小创建一个空数组,如下所示:
offspring = numpy.empty(offspring_size)
因为我们使用单点交叉,我们需要指定交叉发生的点。选择该点,根据这条线将解分成相等的两半:
crossover_point = numpy.uint8(offspring_size[1]/2)
然后我们需要选择双亲进行杂交。这些亲本的指数是根据这两条线选择的:
parent1_idx = k%parents.shape[0] parent2_idx = (k+1)%parents.shape[0]
双亲以类似于环的方式被选择。首先选择具有索引 0 和 1 的第一个来产生两个后代。如果还有剩余的后代要产生,那么我们选择亲本 1 和亲本 2 来产生另外两个后代。如果我们需要更多的后代,那么我们选择指数为 2 和 3 的下两个父母。通过索引 3,我们到达了最后一个父节点。如果我们需要产生更多的后代,那么我们选择索引为 3 的父代,然后回到索引为 0 的父代,依此类推。
将交叉操作应用于双亲后的解存储在offspring
变量中,如下所示:
[[-0. -2. 2. -0. 0. 0.00][ 3.00 -2. 3. -1. -2. 2.][ 1. 0. 0. 3. 0. 3. ][ 2. 2. 3. -1. -1. 0.]]
下一步是使用 GA 模块中的ga.mutation
函数将第二个 GA 变体(突变)应用于存储在offspring
变量中的交叉结果。该函数接受交叉子代,并在应用统一变异后返回它们。该功能实现如下:
def mutation(offspring_crossover): *# Mutation changes a single gene in each offspring randomly.* for idx in range(offspring_crossover.shape[0]): *# The random value to be added to the gene.* random_value = numpy.random.uniform(-1.0, 1.0, 1) offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_value return offspring_crossover
它循环遍历每个后代,并根据下面的代码行添加一个在-1 到 1 范围内统一生成的随机数:
random_value = numpy.random.uniform(-1.0, 1.0, 1)
这样的随机数然后被加到后代的索引为 4 的基因上:
offspring_crossover[idx, 4] = offspring_crossover[idx, 4] + random_value
请注意,该索引可以更改为任何其他索引。应用突变后的后代如下:
[[-0. -2. 2. -0. 1. 0.00][ 3.00 -2. 3. -1. -1. 2.][ 1. 0. 0. 3. 0. 3. ][ 2. 2. 3. -1. -1. 0.]]
这些结果被添加到变量offspring_crossover
中,并由函数返回。
在这一点上,我们成功地从 4 个选择的亲本中产生了 4 个后代,并且我们准备创建下一代的新群体。
注意,遗传算法是一种基于随机的优化技术。它试图通过对当前解决方案进行一些随机更改来增强它们。因为这样的改变是随机的,我们不确定它们会产生更好的解决方案。因此,最好在新的种群中保留以前的最佳解(父代)。在最坏的情况下,当所有新的后代都比这样的父母更差时,我们将继续使用这样的父母。这样一来,我们保证新一代至少会保留以前的好成绩,不会变得更差。新群体将从以前的父母那里得到它的前 4 个解决方案。最后 4 个解决方案来自应用交叉和变异后产生的后代:
new_population[0:parents.shape[0], :] = parents new_population[parents.shape[0]:, :] = offspring_mutation
通过计算第一代所有解(父代和后代)的适应度,它们的适应度如下:
[ 18. 17.0 15. 14. -8. 31. 6. 24.0]
之前最高体能是 18. 现在是31.。这意味着随机变化朝着更好的解决方案发展。这太棒了。但是,这样的结果可以通过更多代来加强。下面是另外 4 代的每个步骤的结果:
Generation : 1Fitness values:[ 18. 17.0 15. 14. -8. 31. 6. 24.0]Selected parents:[[ 3.00 -2. 3. -1. -1. 2.][ 2. 2. 3. -1. -1. 0.][-0. -2. 2. -1. -1. 0.][ 3.00 -2. 3. -0. 0. 0.00]]Crossover result:[[ 3.00 -2. 3. -1. -1. 0.][ 2. 2. 3. -1. -1. 0.][-0. -2. 2. -0. 0. 0.00][ 3.00 -2. 3. -1. -1. 2.]]Mutation result:[[ 3.00 -2. 3. -1. -1. 0.][ 2. 2. 3. -1. -0. 0.][-0. -2. 2. -0. 1. 0.00][ 3.00 -2. 3. -1. -1. 2.]]Best result after generation 1 : 34.Generation : 2Fitness values:[ 31. 24.0 18. 17.0 34. 10. -4. 22.]Selected Parents:[[ 3.00 -2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -1. 2.][ 2. 2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -1. 2.]]Crossover result:[[ 3.00 -2. 3. -1. -1. 2.][ 3.00 -2. 3. -1. -1. 0.][ 2. 2. 3. -1. -1. 2.][ 3.00 -2. 3. -1. -1. 0.]]Mutation result:[[ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -0. 0.][ 2. 2. 3. -1. -0. 2.][ 3.00 -2. 3. -1. -1. 0.]]Best result after generation 2: 34.Generation : 3Fitness values:[ 34. 31. 24.0 22. 34. 28. 2.0 33. ]Selected parents:[[ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -1. 2.]]Crossover result:[[ 3.00 -2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -1. 2.][ 3.00 -2. 3. -1. -2. 2.]]Mutation result:[[ 3.00 -2. 3. -1. -2. 0.][ 3.00 -2. 3. -1. -1. 0.][ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 2.]]Best result after generation 3: 44.Generation : 4Fitness values[ 34. 34. 33. 31. 44.. 36. 37.]Selected parents:[[ 3.00 -2. 3. -1. -2. 0.][ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 2.]]Crossover result:[[ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 0.]]Mutation result:[[ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -2. 2.][ 3.00 -2. 3. -1. -1. 0.]]Best result after generation 4: 44.
在上述 5 代之后,与第一代之后的最佳结果 18. 相比,最佳结果现在具有等于 44. 的适应值。
最佳解决方案具有以下权重:
[3.00 -2. 3. -1. -2. 0.]
完整的 Python 实现
完整的代码可以在我的 GitHub 账号这里获得:https://GitHub . com/ahmedfgad/genetical gorithm python/tree/master/Tutorial % 20 project。它也会在教程中列出。
下面是该示例的实现:
遗传算法模块如下:
原文可在 LinkedIn 本页面获得:https://www . LinkedIn . com/pulse/genetic-algorithm-implementation-python-Ahmed-gad/
联系作者:
领英:https://linkedin.com/in/ahmedfgad
电子邮件:
遗传算法:语义代码
原文:https://towardsdatascience.com/genetic-algorithms-semantic-codes-f484f825b1e?source=collection_archive---------18-----------------------
遗传算法快速概述:遗传算法是一类非常有趣的优化算法,它借用了生物进化的概念。遗传算法由变异、评估和选择过程组成。变异算法的范围可以从无害的变化到每次迭代的大量不同的变化。评估算法测量每个代码对于手头任务的“适合”程度。有时,这可能需要额外的计算,将代码格式化成最终的有机体。最后,选择过程确定将多少代码传递给下一代,以及采取何种选择程序来选择这些代码。
在本文中,我们将讨论正在变异的底层代码,以及我们如何创建更好的代码表示来产生更有意义的结果。
遗传算法可用于解决游戏,如下例所示:
这个贪吃蛇游戏的遗传密码指的是一系列的。在每个时间步,用户可以左转、右转或不采取任何行动。这三个决定的组成,我们姑且缩写为: (L,R,NA) ,都类似于(A,C,G,T)的一个遗传密码。该算法迭代地学习一些序列:
L | L | R | R | NA | NA | L | NA | NA | …. | L | R | # The Cardinality of this Sequence could be something like 1 million decisions results in complete victory in Snake.
这个序列已经针对一些评估指标进行了优化,例如在贪吃蛇游戏中尽可能长时间地存活。评估这一指标需要一些计算,因为算法必须运行游戏,以了解代码对生存的适合程度。幸运的是,进化算法可以利用并行化,同时运行多个模拟,以尽可能快的速度进化后代。
除了诸如代码应该如何进化以及如何加快代码评估的细节之外… 使用遗传算法时,最重要的是要考虑底层代码的结构!
在我们上面的蛇的例子中,游戏的决定可以很容易地分解成 3 个动作,左转,右转,或者不采取行动。导致贪吃蛇游戏胜利的最终移动序列是许多移动长的,但是序列的进化将以从左到右的方式发生,因为这些是将导致最高评估度量的突变。
然而,如果你应用遗传算法来创建一个图像,你可能会有一个更复杂的变异范围,并且没有一个直观的路径来进行变异(例如从左到右的运动决策)。
以 3 个 8 位颜色通道表示的 300 x 300 图像(相当小/低分辨率的图像)导致 300x300x24x255 = 550,800,000 种不同的图像配置。
在这个例子中,底层像素代码构成了最终的有机体,即图像。在前面的例子中,潜在的决策代码组成了最终的有机体,一个蛇游戏试验。现在我们来看看音乐是如何由音符组成的。
钢琴音乐最常见的是,可以分解成乐谱。
这个代码被用来产生一个有机体,音乐。每个音符可以取大约 40 个值,每个时间步长可以包含任意给定数量的音符(尽管很少超过 4 或 5 个),并且还可以随着音符的演奏速度而变化(例如,空心圆圈音符表示按住键 2 个时间步长,而实心圆圈表示仅按下键 1 个时间步长)。
如果我们使用遗传算法来创造音乐,我们会发现比试图创造图像更成功。这主要是因为我们可以访问更具语义代表性的底层代码进行变异。
音频和声音数据可以以模拟图像像素表示的方式分解。cd 质量的音频样本由每秒 44,000 个样本组成,这些样本由描述音频数据的正弦波组成。这些正弦波通过 MP3 等文件进行处理,产生数字声音。一般来说,音频数据实际上比图像数据复杂得多,然而,这种乐谱表示为我们提供了一种更有意义的代码来随机生成音频数据。
在南方公园工作室,他们提供了一个界面让你创建自己的角色:http://southpark.cc.com/avatar。
使用这个工具,你只允许做一些转换,比如转换帽子、颜色、外套、头发等等。由于这种更具语义的表示,你将能够更快地完成诸如“生成一个与我最相似的南方公园头像”这样的任务。这是因为有一个更高层次和语义的代码可以变异。
我希望这篇文章有助于启发关于遗传密码的思考,以及我们如何为了使用遗传算法而预处理我们的数据。在应用遗传算法之前,先试验一下你的数据的更高层次的表示,感谢阅读!请订阅!
CShorten
Connor Shorten 是佛罗里达大西洋大学计算机科学专业的学生。对数据科学、深度学习和软件工程感兴趣。主要用 Python,JavaScript,C++编码。请关注更多关于这些主题的文章。
遗传编程在人工智能启发式优化中的应用
原文:https://towardsdatascience.com/genetic-programming-for-ai-heuristic-optimization-9d7fdb115ee1?source=collection_archive---------7-----------------------
Photo by James Harrison on Unsplash
介绍
我对基因编程的兴趣始于 2015 年,当时我研究了迭代最后通牒游戏。最近,我一直在使用遗传算法来优化工作中风险管理系统的参数。在这篇短文中,我将讨论构建你自己的遗传算法的高级思想和必要成分。我还将给出一个简单的遗传算法的实现,该算法使用 alpha beta 剪枝和迭代深化的 minimax 来优化一般游戏 AI 代理的启发式函数。最后,我将讨论人工智能中遗传编程的几个缺点。
这是什么?
遗传编程(GP)是一种进化算法,可以计算人类不知道如何直接解决的一般问题的解决方案。机器的任务是从问题的高级实现中生成一个工作的计算机程序。这个想法是随机生成数以千计的计算机程序,并使用达尔文自然选择来进化这些程序,直到种群收敛到全局最大值/最小值。它通常用于机器学习领域,以确定数据中特征之间的关系。GP 还被应用于各种金融领域:建立自动交易策略、风险管理系统和信用卡检测。其他感兴趣的领域包括量子计算、电路和天线的设计。我最近还听说遗传算法被用来调试大规模程序中的代码。
遗传程序的组成部分
所有的进化算法都必须有一个繁殖、变异和进化的机制。此外,如果您希望使用真正的遗传编程,您必须定义参数的遗传表示。例如,浮点数据类型的简单表示是二进制字符串表示。然后,人们可以将进化应用于字符串的每一位。关于育种,交叉是最流行的方法,通过这种方法,二进制数据的基因组以随机方式组合。定义健壮的繁殖和变异机制对于确保解收敛到全局最大值/最小值是至关重要的。
玩游戏的例子
假设我们的任务是构建一个人工智能系统来玩一个普通的游戏(例如国际象棋)。如果我们应用最小最大和阿尔法贝塔剪枝的标准方法,我们的任务将是生成一个启发式函数来确定一个移动的相对“强度”。假设我们选择以下形式的东西:
V(w) = w * white_pieces — (1-w)*black_pieces where w in [0,1].
遗传编程的任务是为我们的人工智能代理选择参数 w。请注意,在下面的代码中,我将使用我的 AlphaBetaPlayer 类来表示群体中的个体。遗传得分函数被定义为上面的简单试探法。
我们的首要任务是定义一个单独的代理,如下所示:
def individual(weight): # creates an individual return AlphaBetaPlayer(score_fn=genetic, weight=weight)
初始种群只是一组随机权重的个体。我们可以如下实现它:
def population(count): # creates a list of individuals return [ individual(random.uniform(0,1)) for x in range(count) ]
我们现在可以将育种过程定义为在母亲体重和父亲体重之间计算一个随机数,并稍微增加范围以保持更多的遗传多样性。我们不允许母亲和父亲是同一个人。
def breed(mother, father): if mother != father: if father.w > mother.w: childWeight = random.uniform(mother.w*.95, father.w*1.05) else: childWeight = random.uniform(father.w*.95, mother.w*1.05) if childWeight < 0: childWeight = 0 if childWeight > 1: childWeight = 1 child = individual(childWeight) return child else: print('Cannot breed with itself: Error: Mother == Father')
请记住,这里选择的育种过程是完全随意的,可以有不同的定义。比如我们可以考虑取母亲和父亲的算术平均值甚至几何平均值。你应该尽你所知去模仿达尔文进化论。再次重申我上面的评论,最健壮的方法是使用某种类型的二进制字符串表示,并对基因型应用真交换。在这个简短的例子中不讨论这个问题。我们以显而易见的方式调整琐碎的边界情况。
我们的下一个任务是定义突变过程。一个简单的实现是将权重向上或向下移动一个随机的量。我们做了一些更聪明的事情来确保基因多样性。
def mutate_agent(agent): if agent.w < 0.5: newWeight = (1-agent.w) + random.uniform(-0.5, 0.1) else: newWeight = (1-agent.w) + random.uniform(-0.1, 0.5) if newWeight < 0: newWeight = 0 if newWeight > 1: newWeight = 1 mutated_agent = individual(newWeight) return mutated_agent
特别是,我们将概率分布转换为移动权重,这些权重要么接近 0,要么接近 1,分别接近 1 或 0。同样,我们以明显的方式调整琐碎的边界情况。
我们最后的任务是结合以上的功能来进化当前的种群。我们的方法包括让代理在一定数量的游戏中互相竞争,然后选择前 20%的玩家在下一轮进化中使用。我们还随机选择一些表现较差的代理,以确保遗传多样性。我们有效地杀死了剩下的特工。最后,我们使用我们的育种过程创建孩子,并使用我们上面讨论的突变函数突变 5%的人口。函数中的参数定义了要进行的游戏的数量、要保留的双亲的百分比、表现最差者的随机选择大小和变异率。
def evolve(pop, gamesFactor=2, retain=0.2, random_select=0.05, mutate=0.01): # Determine the parents to breed from the population agent_score = {} numGames = len(pop) * gamesFactor bar = progressbar.ProgressBar()for game in bar(range(numGames)): competitors = random.sample(pop, 2) game = Board(competitors[0], competitors[1]) winner, history, outcome = game.play() competitors.remove(winner) loser = competitors[0] if winner not in agent_score.keys(): agent_score[winner] = 1 else: agent_score[winner] += 1 if loser not in agent_score.keys(): agent_score[loser] = -1 else: agent_score[loser] -= 1 top_performers_size = int(retain * len(pop)) bottom_performers_size = len(pop) - top_performers_size rand_select_size = int(len(pop) * random_select) top_perfomers = heapq.nlargest(top_performers_size, agent_score, key=agent_score.get) bottom_performers = heapq.nsmallest(bottom_performers_size, agent_score, key=agent_score.get) parents = top_perfomers + random.sample(bottom_performers, rand_select_size) random.shuffle(parents)# Create children numChildren = len(pop) - len(parents) children = [] for i in range(numChildren): par = random.sample(parents, 2) father = par[0] mother = par[1] child = breed(mother, father) children.append(child) new_pop = parents + childrenmutated_pop = [] # Randomly mutate some of the new population for agent in new_pop: if mutate > random.uniform(0,1): print('Mutate') mutated_agent = mutate_agent(agent) mutated_pop.append(mutated_agent) else: mutated_pop.append(agent) return mutated_pop
将所有东西结合到我们的主程序中,我们可以不断地进化种群,直到我们收敛到一个全局最大值/最小值。这个模拟花了 17 个小时在我的机器上运行。
if __name__ == "__main__": pop_count = 100 evolution_cyles = 12 pop = population(pop_count) history = [] for i in range(evolution_cyles): print(i) pop = evolve(pop, gamesFactor=10, retain=0.2, random_select=0.05, mutate=0.05) best_weights = [i.w for i in pop] print(stats.describe(best_weights)) history.append(best_weights) print('Evolution Results:') [stats.describe(x) for x in history]
在一天结束的时候,你会对观察经过适当数量的进化周期后的最终种群感兴趣。描述性统计应该有一个小的标准差和一个紧密的四分位数范围。你应该看到所有的代理都有相似的权重。对于下棋代理,遗传算法给出的最优权重约为 0.3452。
遗传编程的缺点
遗传编程的一个简单缺点是计算成本。在达到收敛之前,需要进化许多种群。另一个缺点是解决方案不能保证收敛到全局最大值/最小值。通常也很难确定育种和突变程序。最后,大量的参数通常需要大量的进化周期。玩游戏的启发式函数通常被设计来平衡复杂性和对游戏的洞察力。将启发式算法设计得尽可能简单通常是很重要的。出于这个原因,遗传编程对于玩人工智能游戏的代理人来说非常有效。
参考
[1]https://Zhang GW . WordPress . com/2009/11/08/a-simple-genetic-programming-in-python-4/
[2]https://lethain . com/genetic-algorithms-cool-name-damn-simple/
[3]https://en.wikipedia.org/wiki/Genetic_programming
http://www.genetic-programming.org/
[5]本·兰德在 2015 年夏天
今天的文章 TowardsDataScience 博客中文翻译 2016~2018(一百二十三)分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/bian-cheng-ji-chu/85971.html