我们将在三个迭代中建立神经网络。
在第一个版本中,我们将制作一个最低限度的版本来获得移动部件的中止。第二个版本,HTML,将集中于自动化所有的步长和解释神经网络层。在最终版本Bootstrap中,我们将创建一个模型,该模型可以泛化并探索LSTM层。
所有的代码都是在Github和FloydHub的Jupyter notebook上编写的。所有的FloydHub notebook都在FloydHub目录中,本地的对应项都在local目录下
。
Github地址:https://github.com/emilwallner/Screenshot-to-code-in-Keras/blob/master/README.md
FloydHub地址:https://www.floydhub.com/emilwallner/projects/picturetocode
这些模型是基于Beltramelli的pix2code论文和Jason Brownlee的图像标题教程。代码是用Python和Keras编写的,这是在TensorFlow上的一个框架。
pix2code论文地址:https://arxiv.org/abs/1705.07962
图像标题教程地址:https://machinelearningmastery.com/blog/page/2/
如果你是新手,我建议你去感受一下Python、反向传播和卷积神经网络。建议读以下文章 [1][2] [3]。
让我们来总结一下我们的目标。我们想构建一个神经网络,它将生成对应于屏幕截图的HTML/CSS标记。
当你训练神经网络时,输入几个匹配了HTML的屏幕截图。
它通过预测所有匹配的HTML标记标签逐个学习。当它预测下一个标记标签时,它将接收屏幕截图以及所有正确的标记标签。
这里是谷歌表中的一个简单的训练数据示例。
训练数据示例地址:https://docs.google.com/spreadsheets/d/1xXwarcQZAHluorveZsACtXRdmNFbwGtN3WMNhcTdEyQ/edit?usp=sharing
创建一个可以逐字预测的模型是现今最常用的方法。当然还有其他方法,但本教程中要使用这种方法。
注意,对于每个预测,它都得到相同的屏幕截图。因此,如果它必须预测20个单词,它将会得到20次相同的设计模型。现在,不用担心神经网络的工作原理,专注于理解神经网络的输入和输出。
让我们构建一个hello world版本。我们将在神经网络输入一个显示为“hello world!”的截图,并教它如何生成标记。
首先,神经网络将设计模型映射到一个像素值列表中。从0到255的三个通道——红色、蓝色和绿色。
#Length of longest sentence
max_caption_len = 3
#Size of vocabulary
vocab_size = 3
# Load one screenshot for each word and turn them into digits
images = []
for i in range(2):
images.append(img_to_array(load_img('screenshot.jpg', target_size=(224, 224))))
images = np.array(images, dtype=float)
# Preprocess input for the VGG16 model
images = preprocess_input(images)
#Turn start tokens into one-hot encoding
html_input = np.array(
[[[0., 0., 0.], #start
[0., 0., 0.],
[1., 0., 0.]],
[[0., 0., 0.], #start Hello World!
[1., 0., 0.],
[0., 1., 0.]]])
#Turn next word into one-hot encoding
next_words = np.array(
[[0., 1., 0.], # Hello World!
[0., 0., 1.]]) # end
# Load the VGG16 model trained on imagenet and output the classification feature
VGG = VGG16(weights='imagenet', include_top=True)
# Extract the features from the image
features = VGG.predict(images)
#Load the feature to the network, apply a dense layer, and repeat the vector
vgg_feature = Input(shape=(1000,))
vgg_feature_dense = Dense(5)(vgg_feature)
vgg_feature_repeat = RepeatVector(max_caption_len)(vgg_feature_dense)
# Extract information from the input seqence
language_input = Input(shape=(vocab_size, vocab_size))
language_model = LSTM(5, return_sequences=True)(language_input)
# Concatenate the information from the image and the input
decoder = concatenate([vgg_feature_repeat, language_model])
# Extract information from the concatenated output
decoder = LSTM(5, return_sequences=False)(decoder)
# Predict which word comes next
decoder_output = Dense(vocab_size, activation='softmax')(decoder)
# Compile and run the neural network
model = Model(inputs=[vgg_feature, language_input], outputs=decoder_output)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
# Train the neural network
model.fit([features, html_input], next_words, batch_size=2, shuffle=False, epochs=1000)
在hello world版本中,我们使用三个标记:“start”,“hello world!”和“end”。标记可以是任何东西。它可以是一个字符,一个单词或一个句子。字符版本需要较小的词汇量,但这也限制了神经网络。单词级别的标记往往表现最好。
这里我们做预测:
# Create an empty sentence and insert the start token
sentence = np.zeros((1, 3, 3)) # [[0,0,0], [0,0,0], [0,0,0]]
start_token = [1., 0., 0.] # start
sentence[0][2] = start_token # place start in empty sentence
# Making the first prediction with the start token
second_word = model.predict([np.array([features[1]]), sentence])
# Put the second word in the sentence and make the final prediction
sentence[0][1] = start_token
sentence[0][2] = np.round(second_word)
third_word = model.predict([np.array([features[1]]), sentence])
# Place the start token and our two predictions in the sentence
sentence[0][0] = start_token
sentence[0][1] = np.round(second_word)
sentence[0][2] = np.round(third_word)
# Transform our one-hot predictions into the final tokens
vocabulary = ["start", "Hello World!
", "end"]
for i in sentence[0]:
print(vocabulary[np.argmax(i)], end=' ')
start start start
start Hello World!
Hello World!
start Hello World!
end
我犯的错误:
在收集数据之前构建第一个工作版本。在这个项目的早期,我设法得到了Geocities主机托管网站的旧档案。它有3800万个网站。由于被潜在的因素所蒙蔽,我忽略了减少100k字汇所需要的巨大的工作量。
处理一个tb级的数据需要好的硬件或大量的耐心。在我的mac遇到几个问题之后,我最终使用了一个强大的远程服务器。希望租用一个带有8个现代CPU核心和1GPS网络连接的平台,以拥有一个体面的工作流程。
理解输入和输出数据。输入X是屏幕截图和以前的标记标签。输出Y是下一个标签。当我了解这个的时候,就更容易理解他们之间的一切。也更容易尝试不同的架构。
注意兔子洞(rabbit holes)。因为这个项目与很多深入学习的领域交叉,我遇到了很多的兔子洞。花了一个星期的时间从头开始编写RNNs,沉醉于嵌入向量空间,并被奇异的实现所吸引。
图像到代码网络是伪装的图像标题模型。即使我知道了这一点,我仍然忽略了许多图像标题的文章,仅仅是因为它们不够吸引我。
在FloydHub上运行代码
FloydHub是一个深度学习训练平台。当我第一次开始学习深度学习的时候,我就用它们来训练和管理我的深度学习实验。你可以在10分钟内安装它并运行你的第一个模型。它是在云GPU上运行模型的最佳选项。
如果你是使用FloydHub的新手,请执行他们的2分钟安装或5分钟的演练。
2分钟安装地址:https://www.floydhub.com/
5分钟演练地址:https://www.youtube.com/watch?v=byLQ9kgjTdQ&t=21s
复制资源库。
git clone https://github.com/emilwallner/Screenshot-to-code-in-Keras.git
cd Screenshot-to-code-in-Keras
floyd login
floyd init s2c
floyd run --gpu --env tensorflow-1.4 --data emilwallner/datasets/imagetocode/2:data --mode jupyter
所有的Jupyter notebook都是在floydhub目录中编写的。local equivalent在本地目录下。一旦运行,你可以在这里找到第一个notebook:floydhub/Helloworld/helloworld.ipynb。
如果你想要更详细的说明和解释,请查看我之前的文章。
文章地址:https://blog.floydhub.com/colorizing-b&w-photos-with-neural-networks/
在这个版本中,我们将自动执行Hello World模型中的许多步骤。本节将重点介绍如何在神经网络中创建可伸缩的实现和移动的部分。
这个版本无法从随机网站预测HTML,但它仍然是探索动力学问题的一个很好的设置。
有两个主要部分。首先,编码器。这是我们创建图像特征和以前的标记特性的地方。特征是网络创建的构建块,用于将设计模型与标记连接起来。在编码器的末尾,我们将图像的特征与以前标记的每个单词粘在一起。
然后,解码器采用组合设计和标记功能,创建下一个标签特征。该特征通过一个完全连接的神经网络来预测下一个标签。
设计模型特性
由于我们需要为每个单词插入一个屏幕截图,因此在训练网络时这将成为一个障碍(示例)。我们不使用图像,而是提取需要生成标记的信息。
障碍示例:https://docs.google.com/spreadsheets/d/1xXwarcQZAHluorveZsACtXRdmNFbwGtN3WMNhcTdEyQ/edit#gid=0
信息被编码成图像特征。这是通过使用预先训练的卷积神经网络(CNN)完成的。该模型是在Imagenet上预先训练的。
我们在最终分类之前从图层中提取特征。
我们最终得到了1536个被称为特征的8像素图像。虽然我们很难理解它们,但是神经网络可以从这些特征中提取出这些元素的目标和位置。
标记特征
在hello world版本中,我们使用了独热编码来表示标记。在这个版本中,我们将使用字嵌入输入,并保持独热编码的输出。
我们构造每个句子的方式保持不变,但是我们映射每个标记的方法会发生变化。独热编码将每个单词视为一个独立的单元。我们将输入数据中的每个单词转换为数字列表。
这个单词嵌入的维度是8,但根据词汇的大小,通常会在50 - 500之间变化。
每个单词的8个数字是类似于一个vanilla神经网络的权值。他们被用于表示单词之间的关系。
这就是我们标记特征的方法。特征是神经网络开发用来将输入数据与输出数据连接起来的东西。
编码器
我们将使用词嵌入,并通过LSTM运行它们,并返回一个标记特征序列。这些都要经过时间分布的密集层——把它想象成一个有多个输入和输出的密集层。
与此同时,图像特征首先被平面化。不管这些数字是如何被转换成一大堆数字列表的。我们在这个层上应用一个密集层来形成一个高级特征。然后将这些图像特征连接到标记特征。
这可能很难理解,所以让我们把它分解开。
标记特征
我们通过LSTM层运行词嵌入。在这个图形中,所有的句子都被添加到三个标记的容量上限。
为了混合信号并找到高级模式,我们将一个TimeDistributed密集层应用于标记特征。TimeDistributed密集与密集层相同,但有多个输入和输出。
图像特征
同时,我们准备图像。我们获取所有的微型图像特征,并转换成一个长列表。信息没有改变,只是重新组织。
再一次,为了混合信号和提取更高级的概念,我们应用了一个密集层。因为我们只处理一个输入值,所以我们可以使用一个密集层。为了将图像特性连接到标记特性,我们复制了图像特征。
在本例中,我们有三个标记特征。因此,我们最终得到了相同数量的图像特征和标记特征。
连接图像和标记特性
所有的句子都是padd用来创建三个标记特征的。我们已经准备好了图像特征,现在可以为每个标记特征添加一个图像特征。
在下面的示例中,我们使用了三个图像标记特征对,并输出下一个标记特征。
注意,LSTM层的序列设置为false。它只预测一个特征。在我们的示例中,下一个标签特征包含了最终的预测信息。
最终预测
密集层就像传统的前馈神经网络。它连接了下一个标签特性中的512位数字与4个最终预测。在我们的词汇表中有4个单词: start, hello, world, end。
词汇预测可以是[0.1,0.1,0.1,0.7]。密集层的softmax激活的分布概率为0 - 1,所有预测的概率总和为1。在该示例中,它预测第4个单词是下一个标签。然后将一个热编码(0,0,0,1)转换为映射的值,比如“end”。
# Load the images and preprocess them for inception-resnet
images = []
all_filenames = listdir('images/')
all_filenames.sort()
for filename in all_filenames:
images.append(img_to_array(load_img('images/'+filename, target_size=(299, 299))))
images = np.array(images, dtype=float)
images = preprocess_input(images)
# Run the images through inception-resnet and extract the features without the classification layer
IR2 = InceptionResNetV2(weights='imagenet', include_top=False)
features = IR2.predict(images)
# We will cap each input sequence to 100 tokens
max_caption_len = 100
# Initialize the function that will create our vocabulary
tokenizer = Tokenizer(filters='', split=" ", lower=False)
# Read a document and return a string
def load_doc(filename):
file = open(filename, 'r')
text = file.read()
file.close()
return text
# Load all the HTML files
X = []
all_filenames = listdir('html/')
all_filenames.sort()
for filename in all_filenames:
X.append(load_doc('html/'+filename))
# Create the vocabulary from the html files
tokenizer.fit_on_texts(X)
# Add +1 to leave space for empty words
vocab_size = len(tokenizer.word_index) + 1
# Translate each word in text file to the matching vocabulary index
sequences = tokenizer.texts_to_sequences(X)
# The longest HTML file
max_length = max(len(s) for s in sequences)
# Intialize our final input to the model
X, y, image_data = list(), list(), list()
for img_no, seq in enumerate(sequences):
for i in range(1, len(seq)):
# Add the entire sequence to the input and only keep the next word for the output
in_seq, out_seq = seq[:i], seq[i]
# If the sentence is shorter than max_length, fill it up with empty words
in_seq = pad_sequences([in_seq], maxlen=max_length)[0]
# Map the output to one-hot encoding
out_seq = to_categorical([out_seq], num_classes=vocab_size)[0]
# Add and image corresponding to the HTML file
image_data.append(features[img_no])
# Cut the input sentence to 100 tokens, and add it to the input data
X.append(in_seq[-100:])
y.append(out_seq)
X, y, image_data = np.array(X), np.array(y), np.array(image_data)
# Create the encoder
image_features = Input(shape=(8, 8, 1536,))
image_flat = Flatten()(image_features)
image_flat = Dense(128, activation='relu')(image_flat)
ir2_out = RepeatVector(max_caption_len)(image_flat)
language_input = Input(shape=(max_caption_len,))
language_model = Embedding(vocab_size, 200, input_length=max_caption_len)(language_input)
language_model = LSTM(256, return_sequences=True)(language_model)
language_model = LSTM(256, return_sequences=True)(language_model)
language_model = TimeDistributed(Dense(128, activation='relu'))(language_model)
# Create the decoder
decoder = concatenate([ir2_out, language_model])
decoder = LSTM(512, return_sequences=False)(decoder)
decoder_output = Dense(vocab_size, activation='softmax')(decoder)
# Compile the model
model = Model(inputs=[image_features, language_input], outputs=decoder_output)
model.compile(loss='categorical_crossentropy', optimizer='rmsprop')
# Train the neural network
model.fit([image_data, X], y, batch_size=64, shuffle=False, epochs=2)
# map an integer to a word
def word_for_id(integer, tokenizer):
for word, index in tokenizer.word_index.items():
if index == integer:
return word
return None
# generate a description for an image
def generate_desc(model, tokenizer, photo, max_length):
# seed the generation process
in_text = 'START'
# iterate over the whole length of the sequence
for i in range(900):
# integer encode input sequence
sequence = tokenizer.texts_to_sequences([in_text])[0][-100:]
# pad input
sequence = pad_sequences([sequence], maxlen=max_length)
# predict next word
yhat = model.predict([photo,sequence], verbose=0)
# convert probability to integer
yhat = np.argmax(yhat)
# map integer to word
word = word_for_id(yhat, tokenizer)
# stop if we cannot map the word
if word is None:
break
# append as input for generating the next word
in_text += ' ' + word
# Print the prediction
print(' ' + word, end='')
# stop if we predict the end of the sequence
if word == 'END':
break
return
# Load and image, preprocess it for IR2, extract features and generate the HTML
test_image = img_to_array(load_img('images/87.jpg', target_size=(299, 299)))
test_image = np.array(test_image, dtype=float)
test_image = preprocess_input(test_image)
test_features = IR2.predict(np.array([test_image]))
generate_desc(model, tokenizer, np.array(test_features), 100)
如果你在点击这些链接时看不到任何东西,你可以右键点击“查看页面源代码”。这是原始网站提供的参考。
我犯的错误:
视频地址:http://course.fast.ai/lessons/lesson6.html
在我们的最终版本中,我们将使用来自pix2code论文的生成的Bootstrap网站的数据集。通过使用Twitter的引导,我们可以结合HTML和CSS,减少词汇量。
pix2code论文地址:https://arxiv.org/abs/1705.07962
我们将使它能够生成它之前未见过的屏幕截图标记。我们还将深入了解它是如何构建屏幕截图和标记的常识。
我们将使用17个简化标记,然后将它们转换成HTML和CSS,而不是在Bootstrap上进行训练。数据集包括1500个测试截图和250个验证图像。对于每个屏幕截图平均有65个标签,共有96925个训练示例。
数据集地址:https://github.com/tonybeltramelli/pix2code/tree/master/datasets
通过对pix2code论文中的模型进行调整,该模型预测web组件的准确率可以达到97%(BLEU 4-ngram greedy搜索,稍后会详细介绍)。
端到端的方法
从预先训练的模型中提取特征可以很好地应用于图像标题模型。但经过几次实验,我意识到pix2code的端到端方法对这个问题更有效。预先训练的模型没有在web数据上进行训练,而是为分类定制的。
在这个模型中,我们用一个较轻的卷积神经网络代替了预先训练的图像特征。我们不使用max-pooling来增加信息密度,而是增加了跨步。这保持了前端元素的位置和颜色。
有两种核心模型可用:卷积神经网络(CNN)和递归神经网络(RNN)。最常见的递归神经网络是长期短期记忆(LSTM)。
有很多很棒的CNN教程,我在前一篇文章中介绍过。在这里,我将主要介绍LSTM。
文章地址:https://blog.floydhub.com/colorizing-b&w-photos-with-neural-networks/
理解LSTM的时间步
LSTM的难点之一是时间步。一个vanilla神经网络可以被认为有两个时间步。如果你给它“Hello”,它会预测出“World”。但它很难再预测更多的时间步。在下面的示例中,输入有4个时间步,每个时间步包含一个词。
LSTM利用时间步进行输入。我们的模型看起来是这样的:每个向下的步骤,都有相同的权值。将一组权值应用到前面的输出,另一组用于新的输入。
将加权输入和输出连接起来,再加上一个激活,这是时间步的输出。由于我们重用了权值,它们从多个输入中提取信息,并构建了序列的知识。
下面是LSTM中每个时间步的简化版本。
为了理解这个逻辑,我建议学习Andrew Trask的教程从头开始构建一个RNN。
教程地址:https://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/
理解LSTM层中的单元
每个LSTM层的单元数量决定了它的记忆能力。这也对应每个输出特征的大小。同样,一个特征是一长串用于在层之间传输信息的数字。
LSTM层中的每个单元都学习跟踪语法的不同方面。下面是单元的可视化示例,它跟踪行div中的信息。这是我们用来训练bootstrap模型的简化标记。
每个LSTM单元保持储存格状态。把储存格状态当做记忆。权值和激活被用来以不同的方式修改状态。这使得LSTM层可以对每个输入保留和删除的信息进行微调。
除了传递每个输入的输出特征外,它还会转发储存格状态,在LSTM中每个单元都有一个值。如果想了解LSTM中的组件是如何交互的,我推荐Colah的教程、Jayasiri的Numpy实现,以及Karphay的演讲和文章。
dir_name = 'resources/eval_light/'
# Read a file and return a string
def load_doc(filename):
file = open(filename, 'r')
text = file.read()
file.close()
return text
def load_data(data_dir):
text = []
images = []
# Load all the files and order them
all_filenames = listdir(data_dir)
all_filenames.sort()
for filename in (all_filenames):
if filename[-3:] == "npz":
# Load the images already prepared in arrays
image = np.load(data_dir+filename)
images.append(image['features'])
else:
# Load the boostrap tokens and rap them in a start and end tag
syntax = ' ' + load_doc(data_dir+filename) + ' '
# Seperate all the words with a single space
syntax = ' '.join(syntax.split())
# Add a space after each comma
syntax = syntax.replace(',', ' ,')
text.append(syntax)
images = np.array(images, dtype=float)
return images, text
train_features, texts = load_data(dir_name)
# Initialize the function to create the vocabulary
tokenizer = Tokenizer(filters='', split=" ", lower=False)
# Create the vocabulary
tokenizer.fit_on_texts([load_doc('bootstrap.vocab')])
# Add one spot for the empty word in the vocabulary
vocab_size = len(tokenizer.word_index) + 1
# Map the input sentences into the vocabulary indexes
train_sequences = tokenizer.texts_to_sequences(texts)
# The longest set of boostrap tokens
max_sequence = max(len(s) for s in train_sequences)
# Specify how many tokens to have in each input sentence
max_length = 48
def preprocess_data(sequences, features):
X, y, image_data = list(), list(), list()
for img_no, seq in enumerate(sequences):
for i in range(1, len(seq)):
# Add the sentence until the current count(i) and add the current count to the output
in_seq, out_seq = seq[:i], seq[i]
# Pad all the input token sentences to max_sequence
in_seq = pad_sequences([in_seq], maxlen=max_sequence)[0]
# Turn the output into one-hot encoding
out_seq = to_categorical([out_seq], num_classes=vocab_size)[0]
# Add the corresponding image to the boostrap token file
image_data.append(features[img_no])
# Cap the input sentence to 48 tokens and add it
X.append(in_seq[-48:])
y.append(out_seq)
return np.array(X), np.array(y), np.array(image_data)
X, y, image_data = preprocess_data(train_sequences, train_features)
#Create the encoder
image_model = Sequential()
image_model.add(Conv2D(16, (3, 3), padding='valid', activation='relu', input_shape=(256, 256, 3,)))
image_model.add(Conv2D(16, (3,3), activation='relu', padding='same', strides=2))
image_model.add(Conv2D(32, (3,3), activation='relu', padding='same'))
image_model.add(Conv2D(32, (3,3), activation='relu', padding='same', strides=2))
image_model.add(Conv2D(64, (3,3), activation='relu', padding='same'))
image_model.add(Conv2D(64, (3,3), activation='relu', padding='same', strides=2))
image_model.add(Conv2D(128, (3,3), activation='relu', padding='same'))
image_model.add(Flatten())
image_model.add(Dense(1024, activation='relu'))
image_model.add(Dropout(0.3))
image_model.add(Dense(1024, activation='relu'))
image_model.add(Dropout(0.3))
image_model.add(RepeatVector(max_length))
visual_input = Input(shape=(256, 256, 3,))
encoded_image = image_model(visual_input)
language_input = Input(shape=(max_length,))
language_model = Embedding(vocab_size, 50, input_length=max_length, mask_zero=True)(language_input)
language_model = LSTM(128, return_sequences=True)(language_model)
language_model = LSTM(128, return_sequences=True)(language_model)
#Create the decoder
decoder = concatenate([encoded_image, language_model])
decoder = LSTM(512, return_sequences=True)(decoder)
decoder = LSTM(512, return_sequences=False)(decoder)
decoder = Dense(vocab_size, activation='softmax')(decoder)
# Compile the model
model = Model(inputs=[visual_input, language_input], outputs=decoder)
optimizer = RMSprop(lr=0.0001, clipvalue=1.0)
model.compile(loss='categorical_crossentropy', optimizer=optimizer)
#Save the model for every 2nd epoch
filepath="org-weights-epoch-{epoch:04d}--val_loss-{val_loss:.4f}--loss-{loss:.4f}.hdf5"
checkpoint = ModelCheckpoint(filepath, monitor='val_loss', verbose=1, save_weights_only=True, period=2)
callbacks_list = [checkpoint]
# Train the model
model.fit([image_data, X], y, batch_size=64, shuffle=False, validation_split=0.1, callbacks=callbacks_list, verbose=1, epochs=50)
测试准确度
很难找到一种公平的方法来衡量准确度。如果你预测的是一个不同步的词,准确性可能为0%的。如果你删除一个与预测同步的单词,准确性可能会达到99%。
我使用了BLEU评分,它是验证机器翻译和图像标题模型的最佳方法。它将句子从1-4个词序列分成4个n-grams。在下面的预测中,“cat”应该是“code”。
为了得到最后的分数,你要将每一个分数乘以25%,, (4/5) * 0.25 + (2/4) * 0.25 + (1/3) * 0.25 + (0/2) * 0.25 = 0.2 + 0.125 + 0.083 + 0 = 0.408。然后乘以一个句子长度损失。因为我们例子中的长度是正确的,它成为我们的最终分数。
你可以增加n-gram的数目,使它更难。四个n-gram的模型是最适合人类转化的模型。我建议使用下面的代码运行几个示例,并阅读wiki。
wiki地址:https://en.wikipedia.org/wiki/BLEU
#Create a function to read a file and return its content
def load_doc(filename):
file = open(filename, 'r')
text = file.read()
file.close()
return text
def load_data(data_dir):
text = []
images = []
files_in_folder = os.listdir(data_dir)
files_in_folder.sort()
for filename in tqdm(files_in_folder):
#Add an image
if filename[-3:] == "npz":
image = np.load(data_dir+filename)
images.append(image['features'])
else:
# Add text and wrap it in a start and end tag
syntax = ' ' + load_doc(data_dir+filename) + ' '
#Seperate each word with a space
syntax = ' '.join(syntax.split())
#Add a space between each comma
syntax = syntax.replace(',', ' ,')
text.append(syntax)
images = np.array(images, dtype=float)
return images, text
#Intialize the function to create the vocabulary
tokenizer = Tokenizer(filters='', split=" ", lower=False)
#Create the vocabulary in a specific order
tokenizer.fit_on_texts([load_doc('bootstrap.vocab')])
dir_name = '../../../../eval/'
train_features, texts = load_data(dir_name)
#load model and weights
json_file = open('../../../../model.json', 'r')
loaded_model_json = json_file.read()
json_file.close()
loaded_model = model_from_json(loaded_model_json)
# load weights into new model
loaded_model.load_weights("../../../../weights.hdf5")
print("Loaded model from disk")
# map an integer to a word
def word_for_id(integer, tokenizer):
for word, index in tokenizer.word_index.items():
if index == integer:
return word
return None
print(word_for_id(17, tokenizer))
# generate a description for an image
def generate_desc(model, tokenizer, photo, max_length):
photo = np.array([photo])
# seed the generation process
in_text = ' '
# iterate over the whole length of the sequence
print('\nPrediction---->\n\n ' , end='')
for i in range(150):
# integer encode input sequence
sequence = tokenizer.texts_to_sequences([in_text])[0]
# pad input
sequence = pad_sequences([sequence], maxlen=max_length)
# predict next word
yhat = loaded_model.predict([photo, sequence], verbose=0)
# convert probability to integer
yhat = argmax(yhat)
# map integer to word
word = word_for_id(yhat, tokenizer)
# stop if we cannot map the word
if word is None:
break
# append as input for generating the next word
in_text += word + ' '
# stop if we predict the end of the sequence
print(word + ' ', end='')
if word == '' :
break
return in_text
max_length = 48
# evaluate the skill of the model
def evaluate_model(model, descriptions, photos, tokenizer, max_length):
actual, predicted = list(), list()
# step over the whole set
for i in range(len(texts)):
yhat = generate_desc(model, tokenizer, photos[i], max_length)
# store actual and predicted
print('\n\nReal---->\n\n' + texts[i])
actual.append([texts[i].split()])
predicted.append(yhat.split())
# calculate BLEU score
bleu = corpus_bleu(actual, predicted)
return bleu, actual, predicted
bleu, actual, predicted = evaluate_model(loaded_model, texts, train_features, tokenizer, max_length)
#Compile the tokens into HTML and css
dsl_path = "compiler/assets/web-dsl-mapping.json"
compiler = Compiler(dsl_path)
compiled_website = compiler.compile(predicted[0], 'index.html')
print(compiled_website )
print(bleu)
我犯的错误:
下一个步骤
前端开发是应用深度学习的理想空间。它很容易生成数据,并且当前的深度学习算法可以映射大部分的逻辑。
注意力也是标记、样式表、脚本和最终后端之间通信的关键。注意力层可以跟踪变量,使网络能够在编程语言之间进行通信。
但是在最近的特性中,最大的影响将来自于构建一个可伸缩的方法来合成数据。然后可以一步一步地添加字体、颜色、文字和动画。
到目前为止,大多数的进展都是在将草图转化为模板应用程序的过程中发生的。在不到两年的时间里,我们就可以在纸上绘制出一个应用,在不到一秒的时间内就能得到相应的前端。Airbnb的设计团队和Uizard已经创建了两个技术原型。