如何训练Keras模型以生成颜色

概观

  1. 选择一种语言模型以最好地表示输入文本

  2. 清理并准备培训数据

  3. 建立一个基本的Keras时序神经网络模型。

  4. 应用递归神经网络(RNN)处理字符序列。

  5. 生成3通道RGB彩色输出。

如何训练Keras模型以生成颜色

构建概述

语言模型

语言建模有两个通用选项:词级模型和字符级模型。各有其优点和缺点。现在让我们来看看它们。

词级语言模型

单词级语言模型可以处理相对较长且干净的句子。“clean”是指文本数据集中的单词不含拼写错误,在英语词汇之外几乎没有单词。单词级语言模型将每个唯一单词编码为相应的整数,并且有一个预定义的固定大小的词汇表字典来查找单词到整数映射。单词级语言模型的一个主要优点是它能够利用预先训练的词嵌入,如Word2Vec或GLOVE。这些嵌入将单词表示为具有有用属性的向量。上下文中接近的词在欧几里德距离上接近,可以用来理解类比,比如“男人对女人,对国王来说是女王”。使用这些想法,您可以训练一个带有相对较小标签的训练集的词级模型。

字符级语言模型

但是还有一种更简单的语言模型,它将文本字符串拆分为字符,并将唯一的整数与每个字符相关联。您可能会选择使用字符级语言模型而不是更受欢迎的字级模型:

  • 您的文本数据集包含大量词外单词或不常用单词。在我们的案例中,一些合法的颜色名称可能是“aquatone”,“chartreuse”和“fuchsia”。对于我来说,我必须检查字典并找出它们的含义,而传统的字级嵌入可能不包含它们。

  • 大部分文本字符串都是短的,有限长度的字符串。通常,字符级语言生成模型可以创建更多种类的文本,因为其想象力不受预定词汇表的限制。

您也可能会意识到采用字符级语言所带来的局限性:

  • 长序列可能无法捕获远程依赖关系以及词级语言模型。

  • 字符级模型在训练中的计算量也更大 - 给定相同的文本数据集,这些模型序列更长,因此需要更长的训练时间。

幸运的是,这些限制不会对我们的颜色生成任务构成威胁。我们将颜色名称限制为25个字符,我们只有14157个训练样本。

数据准备

如何训练Keras模型以生成颜色

数据集中的前5行

我们提到我们将颜色名称限制为25个字符。为了达到这个数字,我们检查了所有训练样本中颜色名称长度的分布并将其可视化,以确保我们选择的长度限制是合理的。

h = sorted(names.str.len().as_matrix())

import numpy as np

import scipy.stats as stats

import pylab as plt

fit = stats.norm.pdf(h, np.mean(h), np.std(h)) #this is a fitting indeed

plt.plot(h,fit,'-o')

plt.hist(h,normed=True) #use this to draw histogram of your data

plt.xlabel('Chars')

plt.ylabel('Probability density')

plt.show()

这给了我们这个图,并且您可以清楚地看到大多数颜色名称字符串的长度小于或等于25,即使最大长度达到30。

在我们的例子中,我们可以选择30的最大长度,但是我们要构建的模型也需要长时间训练更长的序列。我们选择较短序列长度的权衡降低了模型训练的复杂性,同时不影响训练数据的完整性。

如何训练Keras模型以生成颜色

颜色名称长度的分布

在做出最大长度的艰难决定之后,字符级数据预处理的下一步是将每个颜色名称字符串转换为25个整数值列表,并且使用Keras文本标记化实用程序可以轻松实现。

from tensorflow.python.keras.preprocessing.text import Tokenizer

maxlen = 25

t = Tokenizer(char_level=True)

t.fit_on_texts(names)

tokenized = t.texts_to_sequences(names)

padded_names = preprocessing.sequence.pad_sequences(tokenized, maxlen=maxlen)

现在padded_names将具有(14157,25)的形状,其中14157是总训练样本数量,25是最大序列长度。如果一个字符串少于25个字符,将从序列的开头填充值0。

你可能会想,现在所有的输入都是整数形式,我们的模型应该能够处理它。但是,我们可以采取更多的步骤来使后面的模型训练更加有效。

One-hot encoding

我们可以通过检查Keras的Tokenizer实例的t.word_index属性来查看字符到整数映射。

{'':4,'a':2,'b':18,'c':11,'d':13,'e':1,'f':22,'g':14,'h ':16,'i':5,'j':26,'k':21,'l':7,'m':17,'n':6,'o':8,'p': 15,'q':25,'r':3,'s':10,'t':9,'u':12,'v':23,'w':20,'x':27, 'y':19,'z':24}

整数值在彼此之间没有自然的有序关系,我们的模型可能无法利用它的任何好处。更糟糕的是,我们的模型最初会假定这些字符之间存在这样的排序关系(即“a”是2,“e”是1,但不应该表示关系),这可能会导致不希望的结果。我们将使用One-hot编码来表示输入序列。

每个整数将由布尔数组表示,其中数组中只有一个元素的值为1.最大整数值将确定字符字典中布尔数组的长度。

在我们的例子中,最大整数值是'x':27,所以一个热点布尔数组的长度将是28(考虑最低值从0开始,即填充)。

例如,我们不是使用整数值2来表示字符'a',而是使用一个热门数组[0,0,1,0 ...... 0]。

Keras还提供One-hot编码。

from keras.utils import np_utils

one_hot_names = np_utils.to_categorical(padded_names)

生成的one_hot_names的形状(14157,25,28)表示(训练样本数,最大序列长度,唯一令牌数量)

数据标准化

请记住,我们预测3个颜色通道值,每个值在0-255之间。数据规范化没有黄金法则。数据归一化是纯粹实用的,因为在实践中,如果训练数据值散布过多,它可能会永远采用一个模型来收敛。常用的标准化技术是将值缩放到[-1,1]。在我们的模型中,我们在最后一层使用ReLu激活函数。由于ReLu输出非负数,我们将这些值归一化为[0,1]。

# The RGB values are between 0 - 255

# scale them to be between 0 - 1

def norm(value):

return value / 255.0

normalized_values = np.column_stack([norm(data["red"]), norm(data["green"]), norm(data["blue"])])

建立模型

为了建立我们的模型,我们将使用两种类型的神经网络,一个前馈神经网络和一个递归神经网络。前馈神经网络是迄今为止最常见的神经网络类型。在这个神经网络中,信息进入输入单元,并通过隐藏层向一个方向流动,直到每个输入单元都到达输出单元。

在循环神经网络中,信息可以循环流动。这些网络可以长时间记住信息。循环网络是模拟连续数据的一种非常自然的方式。在我们的具体模型中,我们使用了一种称为长期短期记忆(LSTM)的最强大的循环网络。

在Keras中构建深度学习模型的最简单方法是使用它的顺序API,并且我们只需通过调用它的model.add()函数(如连接乐高积木)来连接每个神经网络层。

from tensorflow.python.keras.models import Sequential

from tensorflow.python.keras.layers import Dense, Dropout, LSTM, Reshape

model = Sequential()

model.add(LSTM(256, return_sequences=True, input_shape=(maxlen, 28)))

model.add(LSTM(128))

model.add(Dense(128, activation='relu'))

model.add(Dense(3, activation='sigmoid'))

model.compile(optimizer='adam', loss='mse', metrics=['acc'])

通过调用model.fit()函数来训练模型不会更轻松。请注意,我们预留了10%的样本用于验证目的。如果事实证明模型在训练集上达到了很高的精度,但在验证集上低得多,那么模型可能是过度拟合的。

history = model.fit(one_hot_names, normalized_values,

epochs=40,

batch_size=32,

validation_split=0.1)

生成RGB颜色

让我们定义一些函数来生成并显示预测的颜色。

对于颜色名称输入,我们需要将其转换为one-hot 表示。为了达到这个目的,我们使用与我们处理训练数据相同的标记器将字符标记为整数,并将其填充到最大序列长度25,然后将单热编码应用于整数序列。

对于输出的RGB值,我们需要将其缩小回到0-255,所以我们可以正确显示它们。

# plot a color image

def plot_rgb(rgb):

data = [[rgb]]

plt.figure(figsize=(2,2))

plt.imshow(data, interpolation='nearest')

plt.show()

def scale(n):

return int(n * 255)

def predict(name):

name = name.lower()

tokenized = t.texts_to_sequences([name])

padded = preprocessing.sequence.pad_sequences(tokenized, maxlen=maxlen)

one_hot = np_utils.to_categorical(padded, num_classes=28)

pred = model.predict(np.array(one_hot))[0]

r, g, b = scale(pred[0]), scale(pred[1]), scale(pred[2])

print(name + ',', 'R,G,B:', r,g,b)

plot_rgb(pred)

让我们试一试predict()

predict("tensorflow orange")

predict("forest")

predict("keras red")

如何训练Keras模型以生成颜色

结论和进一步阅读

在这篇文章中,我们讨论了如何构建一个可以使用任何颜色名称并提供RGB颜色值的Keras模型。更具体地说,我们着眼于如何将one-hot编码应用于字符级语言模型,构建具有前馈神经网络和递归神经网络的神经网络模型。

下面是一个图表,总结了我们在帖子中构建的内容,从底部开始展示数据流的每一步。

如何训练Keras模型以生成颜色

相关推荐