素晴らしい!ニューラルネットワークがフロントエンドコードを作成します

素晴らしい!ニューラルネットワークがフロントエンドコードを作成します

今後 3 年間で、ディープラーニングはフロントエンド開発の現状を変え、プロトタイピングの速度を向上させ、ソフトウェア開発の敷居を下げるでしょう

昨年 Tony Beltramelli 氏と Airbnb 氏が pix2code と ketch2code について発表して以来、この分野は急速に発展しています。現在、自動化されたフロントエンド開発の最大のボトルネックとなっているのはコンピューティング能力ですが、ディープラーニング アルゴリズムと包括的なトレーニング データ セットを通じて、人工的なフロントエンド自動化の検討をすでに開始することができます。

この記事では、ニューラル ネットワークをトレーニングして、Web デザインのプロトタイプを基本的な HTML および CSS Web ページに直接変換できるようにします。

トレーニング プロセスの概要は次のとおりです。

1) ウェブデザイン画像をトレーニング済みのニューラルネットワークにインポートする

2) HTMLタグ

3) 結果を表示する

「ニューラルネットワークの3つのバージョンを構築します」

この最初のバージョンでは、動的な部分を理解するために最小限のバージョンを実装します。

HTML バージョンでは、プロセス全体の自動化に重点を置き、各ニューラル ネットワーク レイヤーについて説明します。最終的な Bootstrap バージョンでは、LSTM に基づくモデルを作成します。

この記事のモデルは、Beltramelli の pix2code 論文と Brownlee の画像注釈チュートリアルに基づいています。この投稿のコードは、 PythonKeras ( TensorFlowベース) で記述されました。

ディープラーニングをまだ知らない場合は、まず Python、バックプロパゲーション アルゴリズム、畳み込みニューラル ネットワークを学習することをお勧めします。前回の 3 つの記事が、始める際に役立ちます。

コアロジック

私たちの目標をもう一度見直してみましょう。Web ページのスクリーンショットを対応する HTML/CSS コードに変換できるニューラル ネットワークを構築したいと考えています。

私たちは、Web ページのスクリーンショットと対応する HTML コードをニューラル ネットワークに入力してトレーニングします。一致する HTML タグを 1 つずつ予測して学習します。次のタグを予測する必要がある場合、次のタグが開始されるまで、Web ページのスクリーンショットと対応する完全なタグを受け取ります。 Google スプレッドシートには、トレーニング データの簡単な例が用意されています。単語ごとの予測モデルを作成することが、現在最も一般的なアプローチです。他にもアプローチはありますが、このチュートリアルでは単語ごとの予測モデルを使用します。

各予測に同じ Web ページのスクリーンショットを使用するため、20 語を予測する必要がある場合は、デザイン プロトタイプ (Web ページのスクリーンショットなど) を 20 回表示する必要があることに注意してください。ここで、ニューラル ネットワークがどのように動作するかについては心配する必要はありません。ニューラル ネットワークの入力パラメータと出力パラメータに焦点を当てる必要があります。

前面のラベルに注目してみましょう。 「私はコーディングできます」という文を予測するようにニューラル ネットワークをトレーニングするとします。 「I」を受け取ると、「can」と予測します。すると、「I can」を受け取り、「code」を予測します。前の単語をすべて取り込み、次の単語を予測するだけです。

データにより、ニューラル ネットワークは機能を作成できます。機能は入力データを出力データに接続します。ニューラル ネットワークは、次の HTML タグを予測するために、学習した Web ページのスクリーンショットと HTML 文法を構築する必要があります。

目的に関係なく、モデルをトレーニングする方法は常に似ています。各反復で同じ画像を使用してコード スニペットを生成します。ニューラル ネットワークに正しい HTML タグを入力するのではなく、生成したタグを使用して次のタグを予測します。予測は「開始タグ」で初期化され、「終了タグ」を予測するか上限に達すると終了します。 Google スプレッドシートに別の例があります。

「Hello World!」バージョン

「Hello World」バージョンをビルドしてみましょう。 「Hello World」を表示する Web ページのスクリーンショットをニューラル ネットワークに入力し、対応するラベルを生成する方法を教えます。

まず、ニューラル ネットワークが設計モデルをピクセル値のリストにマッピングします。ピクセル値は 0 ~ 255 で、3 つのチャネルは赤、黄、青です。

ラベルをニューラル ネットワークが理解できるようにするために、ワンホット エンコーディングを使用したので、「I can code」は次のようにマッピングされます。

上の図に示すように、開始タグと終了タグを導入しました。これにより、ニューラル ネットワークが開始場所と終了場所を予測できるようになります。最初の単語から始まり、後続の単語を順番に接続する連続したフレーズを入力として使用します。出力は常に 1 つの単語になります。

連続フレーズのロジックは単語の場合と同じですが、同じフレーズの長さが必要です。

語彙によって制限されるのではなく、フレーズの最大長によって制限されます。最長のフレーズ長よりも短い場合は、すべてゼロの単語である空の単語で完成させる必要があります。

ご覧のとおり、左側の空白の単語が埋められています。この方法では、トレーニングするたびに単語の位置が変更され、モデルは各単語の位置を記憶するのではなく、文を学習できるようになります。下の図の各行は予測を表し、合計 4 つの予測があります。カンマの左側には RGB で表現された画像があり、カンマの右側には前の単語があり、括弧の外側には上から下への各予測の結果があり、終了タグは赤い四角で表されます。

: #VGG16 モデルの入力を前処理します。images = preprocess_input(images) #開始トークンをワンホットエンコーディングに変換します。html_input = np.array( [[[0., 0., 0.], #開始 [0., 0., 0.], [1., 0., 0.]], [[0., 0., 0.], #Hello World! を開始 [1., 0.,0.0., 1., 0.]]]) #次の単語をワンホットエンコーディングに変換します。ワンホットエンコーディング next_words = np.array( [[0., 1., 0.], # Hello World! [0., 0., 1.]]) # end# imagenet でトレーニングされた VGG16 モデルをロードし、分類機能を出力します VGG = VGG16(weights='imagenet', include_top=True) # 画像から機能を抽出します features = VGG.predict(images) # ネットワークに機能をロードし、密なレイヤーを適用して、ベクトルを繰り返します vgg_feature = Input(shape=(1000,)) vgg_feature_dense = Dense(5)(vgg_feature) vgg_feature_repeat = RepeatVector(max_caption_len)(vgg_feature_dense) # 入力シーケンスから情報を抽出します language_input = Input(shape=(vocab_size, vocab_size)) language_model = LSTM(5, return_sequences=True)(language_input) # 画像と入力からの情報を連結します。decoder = concatenate([vgg_feature_repeat, language_model]) # 連結された出力から情報を抽出します。decoder = LSTM(5, return_sequences=False)(decoder) # 次にどの単語が来るかを予測します。decoder_output = Dense(vocab_size, activation='softmax')(decoder) # ニューラル ネットワークをコンパイルして実行します。model = Model(inputs=[vgg_feature, language_input], outputs=decoder_output) model.compile(loss='categorical_crossentropy', optimizer='rmsprop') # ニューラル ネットワークをトレーニングします。model.fit([features, html_input], next_words, batch_size=2, shuffle=False, epochs=1000)

「Hello World」バージョンでは、「start」、「Hello World!」、および「end」という 3 つの用語を使用します。

エントリとして文字、単語、または文章を使用できます。文字を用語として使用する場合、必要な語彙は少なくなりますが、ニューラル ネットワークを圧倒する可能性があります。 3つの中では、単語をエントリとして使用するのが最適です。

予測を始めましょう:

  1. # 空の文を作成し、開始トークンを挿入します sentence = np.zeros((1, 3, 3)) # [[0,0,0], [0,0,0], [0,0,0]] start_token = [1., 0., 0.] # 開始 sentence[0][2] = start_token # 空の文に開始を配置します # 開始トークンを使用して最初の予測を行います second_word = model.predict([np.array([features[1]]), sentence]) # 文に2番目の単語を入れて、最終的な予測を行います sentence[0][1] = start_token sentence[0][2] = np.round(second_word) third_word = model.predict([np.array([features[1]]), sentence]) # 開始トークンと2つの予測を文に配置します sentence[0][0] = start_token sentence[0][1] = np.round(second_word) sentence[0][2] = np.round(third_word) # ワンホット予測を最終トークンに変換します vocabulary = ["start", "  
  2.  
  3. 「こんにちは世界」
  4.  
  5. ", "end"] for i in sentence[ 0 ]: print (vocabulary[np.argmax(i)], end= ' ' )

出力:

  1. 10エポック: 開始開始開始
  2.  
  3. 100 エポック: 開始< HTML > < center > < H1 > Hello World! </ H1 > </ center > </ HTML >   < HTML > < center > < H1 >こんにちは世界! </ H1 > </ center > </ HTML >  
  4.  
  5. 300 エポック: 開始< HTML > < center > < H1 > Hello World! </ H1 > </ center > </ HTML >終了

迂回したルート:

  • データを収集する前に最初の実行を構築します。このプロジェクトの早い段階で、Geocities ホスティング サイトの古いバージョンを入手することができました。 3,800 万のウェブサイトがあります。私はこのデータの潜在能力に非常に集中していたため、語彙を 10 万語にまで減らすために必要な膨大な作業量を見落としていました。

  • 1 テラバイトのデータを処理するには、優れたハードウェアか多大な忍耐力が必要です。 Mac でいくつかの問題が発生した後、強力なリモート サーバーを使用することになりました。スムーズなワークフローを実現するには、おそらく 8 コアの CPU と 1GPS のインターネット速度を備えたデバイスをレンタルする必要があります。

  • 入力データと出力データを理解し始めて初めて、すべてが理解できるようになりました。入力データ X は、Web ページのスクリーンショットとその前のラベルです。出力データYは次のラベルです。これを理解すると、その間のすべてを理解しやすくなりました。さまざまなアーキテクチャを試すことも容易になります。

  • マンネリに陥らないでください。このプロジェクトはディープラーニングの多くの分野と交差しているため、途中で多くの困難に遭遇しました。私は 1 週間かけて RNN をゼロから作成し、埋め込みベクトル空間に魅了され、そのユニークな実装方法に魅了されました。

  • 画像からエンコードへのネットワークは、画像キャプション モデルに変装したものです。これを理解していても、私は画像の説明に関する論文の多くを、単にかっこよくないという理由だけで無視していました。しかし、これについてある程度の見通しが持てるようになると、問題領域に対する理解が加速しました。

FloydHubでコードを実行する

FloydHub はディープラーニング トレーニング プラットフォームです。私はディープラーニングを学び始めたときにこのプラットフォームを発見し、ディープラーニング実験のトレーニングと管理に使用しています。 FloydHub をインストールすれば、10 分以内に最初のモデルを実行できるようになります。これは、クラウド GPU 上でモデルを実行する場合の最適な選択肢です。

FloydHub を初めてご利用になる場合は、2 分間のインストール (https://www.floydhub.com/) または 5 分間のウォークスルー (https://www.youtube.com/watch?v=byLQ9kgjTdQ&t=21s) をお試しください。

リポジトリをクローンする

git クローン https://github.com/emilwallner/Screenshot-to-code-in-Keras.git

ログインしてFloydHubコマンドラインツールを起動します

  1. cd スクリーンショットをKerasでコードに変換する
  2.  
  3. フロイドログイン
  4.  
  5. フロイドinit s2c:

FloydHub クラウド GPU マシンで Jupyter Notebook を実行します。

floyd 実行 --gpu --env tensorflow-1.4 --data emilwallner/datasets/imagetocode/2:data --mode jupyter

すべてのノートブックは floydhub ディレクトリにあります。地元のものは地元に残ります。実行後、最初のノートブックは次のアドレスにあります:

floydhub/Hello world/hello world.ipynb。

より詳しい手順と標識の説明が必要な場合は、以前の投稿 (https://blog.floydhub.com/colorizing-b&w-photos-with-neural-networks/) を参照してください。

HTMLバージョン

このバージョンでは、Hello World モデルの複数のステップを自動化します。このセクションでは、スケーラブルな実装とニューラル ネットワーク内のアクティブな部分の作成に焦点を当てます。

このバージョンでは、Web サイトの HTML コードを推測することはできませんが、動的な問題を調査するための優れたアイデアを提供します。

概要

前のグラフのコンポーネントを展開すると、次のようになります。

このバージョンは主に 2 つの部分で構成されています。

1. まず、エンコーダーを使用して画像の特徴と以前のラベルの特徴を作成します。特徴は、ニューラル ネットワークが設計プロトタイプとラベルを接続するために作成する構成要素です。エンコーダーの最後に、画像の特徴とそれに対応するラベルを連結します。

2. デコーダーは、マージされた設計プロトタイプ機能とラベル機能を使用して、次のラベル機能を作成します。この機能は、完全に接続されたニューラル ネットワーク上で実行されます。

プロトタイプの機能設計

各単語の前にウェブページのスクリーンショットを挿入する必要があるため、ニューラル ネットワークのトレーニングのボトルネックになります (例)(https://docs.google.com/spreadsheets/d/1xXwarcQZAHluorveZsACtXRdmNFbwGtN3WMNhcTdEyQ/edit#gid=0)。したがって、画像は使用せず、ラベルを生成するために必要な情報のみを抽出します。

これは、Imagenet で事前トレーニングされた畳み込みニューラル ネットワーク (CNN) を使用して行われます。最終的な分類の前に、ニューラル ネットワーク層から特徴を抽出する必要があります。

最終的な特徴は、1536 個の 8 x 8 ピクセル画像のセットです。この内容を人間が理解するのは困難ですが、ニューラル ネットワークはそこからオブジェクトの位置要素を抽出することができます。

HTML タグの機能

「Hello World」バージョンでは、ラベルを表すためにワンホットエンコーディングを使用します。このバージョンでは、単語埋め込みを入力として使用し、出力データはワンホットエンコード形式のままになります。

文のデータ構造は同じですが、用語のマッピング方法が異なります。ワンホットエンコーディングは、各単語を独立した部分として扱います。代わりに、入力された単語を数字のリストに変換して、タグ間の関係を表します。

単語埋め込みは 8 次元で、語彙のサイズに応じて通常は 50 ~ 500 の間で変化します。単語を表す 8 つの数字は、通常のニューラル ネットワークと同様に重みを表します。単語間の関係性を表現するために常に調整されます。

こうしてラベル機能の開発が始まりました。ニューラル ネットワークでは、入力データと出力データの関係を表す特徴が開発されます。それが何なのかはまだ心配しないでください。後で詳しく説明します。

エンコーダ

単語の埋め込みを LTSM に渡すと、連続したラベル機能が返されます。これらは時間密度の高いレイヤーを介して実行されます。これは、複数の入力と出力を持つ完全に接続されたレイヤーと考えてください。

同時に画像の特徴も抽出されます。画像がどのようなデータ構造で表現されているかに関係なく、画像は非常に長いベクトルに拡張され、完全に接続されたレイヤーに送信されて高レベルの特徴が抽出されます。これらの特徴はラベル特徴と連結されます。

このプロセスは少し複雑です。ステップごとに説明しましょう。

タグ機能

ここで、単語埋め込みを LSTM レイヤーに渡します。下の図に示すように、すべての文は長さ 3 のトークンで埋められます。

信号を混合して高レベルのパターンを発見するために、ラベル機能に TimeDistributed 完全接続レイヤーを導入します。 TimeDistributed 完全接続層は、多数の入力と出力があることを除いて、通常の完全接続層と似ています。

画像の特徴

その間に写真を準備します。これらの画像の特徴を長いリストに変換します。情報は変更されていません。構造が異なるだけです。

同様に、信号を混合し、高レベルの概念を抽出するために、完全に接続されたレイヤーを導入します。処理する必要があるのは単一の入力値だけなので、通常の完全接続層で十分です。画像特徴とラベル特徴を連結するには、画像特徴をコピーします。

画像特徴とラベル特徴のカスケーディング

すべての文がパディングされて、3 つのラベル機能が作成されます。画像機能が準備できたので、各ラベル機能に画像機能を追加できるようになりました。

各ラベル機能に画像機能を追加すると、3 つの画像ラベル機能が得られます。それをデコーダーに渡します。

デコーダ

ここでは、取得した画像とラベルの組み合わせ機能を使用して、次のラベルを予測します。

次の例では、これら 3 つの画像とラベルの特徴のペアを使用して、次のラベルの特徴を出力します。 LSTM レイヤーはシーケンスを「いいえ」に設定することに注意してください。これは、入力シーケンスと同じ長さの特徴記述のシーケンスを返すのではなく、マージされた特徴のみを予測することを意味します。この場合、これは次のタグのプロパティです。最終的な予測結果に必要な情報が含まれています。

最終予測

完全接続層は、従来のフィードフォワード ニューラル ネットワークと同じ役割を果たします。

次のラベル機能に含まれる 512 ビットを 4 つの最終予測と連結します。語彙に start、hello、world、end という 4 つの単語があるとします。

語彙内の単語の予測値は [0.1, 0.1, 0.1, 0.7] になる可能性があります。完全結合層ではソフトマックス関数が有効になっていて、確率を 0 ~ 1 の範囲で離散化し、すべての予測値の合計は 1 になります。この場合、4 番目の単語が次のラベルになると予測されます。次に、デコーダーを使用して、ワンホットエンコードされた結果 [0,0,0,1] をマッピング値の「end」に変換します。

# 画像を読み込み、inception-resnet 用に前処理します。images = all_filenames = listdir('images/') all_filenames.sort for filename inall_filenames: images.append(img_to_array(load_img('images/'+filename, target_size=(299, 299)))) images = np.array(images, dtype=float) images = preprocess_input(images) # 画像を inception-resnet に通し、分類レイヤーなしで特徴を抽出します。IR2 = InceptionResNetV2(weights='imagenet', include_top=False) features = IR2.predict(images) # 各入力シーケンスを 100 トークンに制限します。max_caption_len = 100 # 語彙を作成する関数を初期化します。tokenizer = Tokenizer(filters='', split=" ", lower=False) # ドキュメントを読み取り、文字列を返します。 defload_doc(filename):file = open(filename、 'r')file.read file.close return text#すべてのHTMLファイルをロードx = all_fileNames = listdir( 'html/' for filename inall_filenames:x.append( 'html/'+filename) s(x)#+1を追加して空の単語を残すvocab_size = len(tokenizer.word_index) + 1 IMG_NOのリスト、SEQ INENUMERATE(シーケンス):範囲のi(1、len(seq)):#全体を追加しますシーケンスを入力に追加し、次の単語のみを出力に残します in_seq, out_seq = seq[:i], seq[i] # 文がmax_lengthより短い場合は、空の単語で埋めます in_seq = pad_sequences([in_seq], maxlen=max_length)[0] # 出力をワンホットエンコーディングにマップします out_seq = to_categorical([out_seq], num_classes=vocab_size)[0] # HTMLファイルに対応する画像を追加します image_data.append(features[img_no]) # 入力文を100トークンにカットし、入力データに追加します image_data.append(in_seq[-100:]) y.append(out_seq) X, y, image_data = np.array(X), np.array(y), np.array(image_data) # エンコーダーを作成します 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) # デコーダーを作成するdecoder = concatenate([ir2_out, language_model])decoder = LSTM(512, return_sequences=False)(decoder)decoder_output = Dense(vocab_size, activation='softmax')(decoder) # モデルをコンパイルする model = Model(inputs=[image_features, language_input], outputs=decoder_output) model.compile(loss='categorical_crossentropy', optimizer='rmsprop') # ニューラル ネットワークをトレーニングする model.fit([image_data, X], y, batch_size=64, shuffle=False, epochs=2) # 整数を単語にマッピングする defword_for_id(integer, tokenizer): for word, index intokenizer.word_index.items: if index == integer: return word returnNone # 画像の説明を生成する defgenerate_desc(model, tokenizer, photo, max_length): # 生成プロセスのシード値を設定する in_text = 'START' # シーケンスの全長を反復処理する for i in range(900): # 入力を整数でエンコードするシーケンス シーケンス = tokenizer.texts_to_sequences([in_text])[0][-100:] # 入力を埋め込む シーケンス = pad_sequences([sequence], maxlen=max_length) # 次の単語を予測する yhat = model.predict([photo,sequence], verbose=0) # 確率を整数に変換する yhat = np.argmax(yhat) # 整数を単語にマップする word = word_for_id(yhat, tokenizer) # 単語をマップできない場合は停止する if wordisNone: break # 次の単語を生成するための入力として追加する in_text += ' ' + word # 予測を出力する print(' ' + word, end='') # シーケンスの終わりを予測する場合は停止する if word == 'END': break return # 画像を読み込み、IR2 用に前処理し、特徴を抽出して 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(モデル、トークナイザー、np.array(test_features)、100)

出力

生成されたウェブサイトリンク:

  • 250 エポック

  • 350 エポック

  • 450 エポック

  • 550 エポック

リンクをクリックしても結果が表示されない場合は、右クリックして「ページソースの表示」を選択してください。以下は、この事件の身元分析に使用された元のウェブサイトです。

上記のリンクを開いてもコンテンツが表示されない場合は、右クリックして「ページのソースコードを表示」を選択してください。これらのページの元のソースコードはこちらです。

迂回したルート:

  • LSTM ネットワークは、畳み込みニューラル ネットワークよりも学習がはるかに困難です (私にとって)。 LSTM ネットワークを完全に理解した後、この構造は私にとって簡単になりました。 Fast.ai の再帰型ニューラル ネットワーク ビデオは非常に役に立ちました。また、このネットワーク構造がどのように機能するかを理解する前に、入力と出力の特性を注意深く観察する必要があります。

  • フォント、DIV サイズ、16 進カラー コード、変数名、Web ページ コンテンツを含む膨大な語彙を圧縮するよりも、語彙をゼロから構築する方がはるかに簡単です。

  • 通常、テキスト ファイルの内容はスペースで区切られますが、コード ファイルでは解析方法をカスタマイズする必要があります。

  • Imagenet でトレーニングされたモデルを使用して特徴を抽出できます。 Imagenet に Web 画像がほとんどないというのは直感に反するかもしれません。しかし、pix2code モデルと比較すると、損失は 30% 高くなります。もちろん、Web ページのスクリーンショットに基づいて事前トレーニングされた inception-resnet モデルにも非常に興味があります。

ブートストラップバージョン

最終バージョンでは、pix2code 論文に記載されている bootstrap Web サイトのデータセットを使用します。 Twitter のブートストラップを使用すると、HML と CSS を組み合わせて語彙のサイズを圧縮できます。

これまで見たことのない Web ページのスクリーンショットのタグを生成するように依頼し、スクリーンショットとタグに関する知識を構築する方法についても詳しく調べます。

ブートストラップ タグを使用してトレーニングする代わりに、 17 個の簡略化された用語を使用してこれらのトークンを HTML と CSS に変換します。このデータセットには、 1500 枚のテスト スクリーンショットと250 枚の検証画像が含まれています。平均して、各スクリーンショットには65 個の用語が含まれており、合計96,925 個のトレーニング サンプルが生成されます。

pix2code の論文に記載されているモデルを微調整することで、私たちのモデルは最大 97% の精度で Web ページ コンポーネントを予測できます (BLEU 飽和検索評価に基づきます。詳細は以下を参照してください)。

エンドツーエンドのアプローチ

事前トレーニング済みのモデルを使用して特徴を抽出することは、画像注釈モデルにとって非常に効果的です。しかし、いくつかの実験を行った結果、pix2code のエンドツーエンドのアプローチがこの種の問題に適していることがわかりました。事前トレーニング済みモデルは、Web データではなく、カスタマイズされた分類器を使用してトレーニングされます。

このモデルでは、事前にトレーニングされた画像の特徴を軽量の畳み込みニューラル ネットワークに置き換えます。最大プーリング関数の代わりにストライドを増やすことで情報密度を高めます。これにより、各フロントエンド要素の位置と色の情報を最大限に保持できます。

これを実行できるコアモデルは、畳み込みニューラル ネットワーク (CNN) と再帰型ニューラル ネットワーク (RNN) の 2 つです。最も一般的に使用される再帰型ニューラル ネットワークは Long Short-Term Memory (LSTM) ネットワークであり、次にこれを使用します。前回の記事でも、多くの優れた CNN チュートリアルをまとめました。今回は、LSTM の使用に焦点を当てます。

LSTMの時間ステップを理解する

LSTM を習得する上での難しさは、時間ステップにあります。バニラ ニューラル ネットワークは、2 つの時間ステップを持つものとして考えることができます。 「Hello」と入力すると、「World」と予測されます。しかし、より多くの時間ステップを予測しようとします。

次の例では、入力は各単語に 1 つずつ、計 4 つの時間ステップで構成されます。

LSTM は、時間ステップを含む入力に適しており、順序付けられた情報を持つニューラル ネットワークに適しています。モデルを分析すると、次のようになります。チェーンの各パスは同じ重みを維持します。以前の出力に対して 1 セットの重みを設定し、新しい入力に対して別のセットの重みを設定できます。

重み付けされた入力と出力は、アクティベーションを通じて接続および結合され、その時間ステップの出力を形成します。これらの重みを繰り返し使用するため、複数の入力から情報を引き出し、結果を理解します。重み付けされた入力と出力はカスケードされ、対応する時間ステップの出力として活性化関数に送信されます。これらの再利用された重みのセットは、入力の情報を表し、シーケンスの知識を構築します。

以下は、LSTM モデルでの各タイム ステップの様子を簡略化して示したものです。

RNN ネットワークをゼロから構築し、その背後にあるロジックを理解するには、Andrew Trask の優れたチュートリアル (https://iamtrask.github.io/2015/11/15/anyone-can-code-lstm/) を参照することをお勧めします。

LSTM層のセルを理解する

LSTM の各レイヤーのユニット数によってメモリが決まり、出力機能のサイズも決まります。ここでの機能は、レイヤー間で情報を伝達する長い数字の文字列であることを再度指摘することが重要です。

LSTM レイヤーの各ユニットは、文法のさまざまな側面の記録を保持します。以下は、div 行情報を保持するセルを実装する方法を示しています。これは、ブートストラップ モデルをトレーニングするために使用する簡略化された表記法でもあります。

各 LSTM ユニットはセルの状態を格納します。セルの状態をメモリとして考え、重みと活性化関数によってこの状態がさまざまな方法で変更されると考えます。これにより、LSTM レイヤーは各入力の情報を調整し、どの情報を保持し、どの情報を破棄するかを決定できます。

レイヤー ユニットは、各入力の出力機能を渡すだけでなく、セルの状態も渡し、各 LSTM セルは異なる値に対応します。 LSTM レイヤー内の機能がどのように相互作用するかを理解したい場合は、Colah のチュートリアル、Jayasiri の Numpy 実装、Karphay の講義とコメントを強くお勧めします。

dir_name = 'resources/eval_light/' # ファイルを読み込んで文字列を返します defload_doc(filename): file = open(filename, 'r') text = file.read file.close return text defload_data(data_dir): text = images = # すべてのファイルをロードして順序付けます all_filenames = listdir(data_dir) all_filenames.sort for filename in (all_filenames): if filename[-3:] == "npz": # 配列に既に用意されている画像をロードします image = np.load(data_dir+filename) images.append(image['features']) else: # ブーストストラップ トークンをロードして開始タグと終了タグでラップします syntax = ' ' + load_doc(データディレクトリ+ファイル名) + ' s) # 入力文を語彙インデックスにマップします train_sequences = tokenizer.texts_to_sequences(texts) # ブーストストラップ トークンの最長セット max_sequence = max(len(s) for s) # 語彙を作成する関数を初期化します tokenizer = Tokenizer(filters='', split=" ", lower=False) # 語彙を作成します tokenizer.fit_on_texts([load_doc('bootstrap.vocab')]) # 語彙の空単語用に 1 つのスポットを追加します vocab_size = len(tokenizer.word_index) + 1 # 入力文を語彙インデックスにマップします train_sequences = tokenizer.texts_to_sequences(texts) # ブーストストラップ トークンの最長セット max_sequence = max(len(s) for s) intrain_sequences) # 各入力文に含まれるトークンの数を指定しますmax_length = 48 defpreprocess_data(sequences, features): X, y, image_data = list, list, list for img_no, seq in enumerate(sequences): for i inrange(1, len(seq)): # 現在の count(i) まで文を追加し、現在の count を出力に追加します in_seq, out_seq = seq[:i], seq[i] # すべての入力トークン文を max_sequence までパディングします in_seq = pad_sequences([in_seq], maxlen=max_sequence)[0] # 出力をワンホットエンコーディングに変換します out_seq = to_categorical([out_seq], num_classes=vocab_size)[0] # 対応する画像をブートストラップトークンファイルに追加します image_data.append(features[img_no]) # 出力を入力文を 48 個のトークンに分割して追加します X.append(in_seq[-48:]) y.append(out_seq) returnnp.array(X), np.array(y), np.array(image_data) X, y, image_data = preprocess_data(train_sequences, train_features) #エンコーダーを作成しますimage_model = Sequential image_model.add(Conv2D(16, (3, 3), padding='valid', activation='relu', input_shape=(256, 256, 3,))) image_model.add(Conv2D(16, (33), activation='relu', padding='same', strides=2)) image_model.add(Conv2D(32, (33), activation='relu', padding='same', strides=2)) 'Relu'、Padding = 'Same'、Strides = 264、(33)、activation = 'Relu'、Padding = 'Same64、(33)、activation =' lelu '、padding =' same '、(33)、activation =' lelu '、padding =' same ')imadel.add(flattenddddd( ))image_model.add(dropout(0.3))image_model.add(dense(1024、activation = 'relu'0.3))image_model.add(repeatvector(max_length))visual_inputモデル=埋め込み(vocab_size、50、 _decoder) デコーダー = LSTM(512, return_sequences=True)(decoder) デコーダー = LSTM(512, return_sequences=False)(decoder) デコーダー = Dense(vocab_size, activation='softmax')(decoder) # モデルをコンパイルする model = Model(inputs=[visual_input, language_input], output=decoder) optimizer = RMSprop(lr=0.0001, clipvalue=1.0) model.compile(loss='categorical_crossentropy', optimizer=optimizer) #2 エポックごとにモデルを保存します。 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] # モデルをトレーニングします。 model.fit([image_data, X], y, batch_size=64, shuffle=False, validation_split=0.1, callbacks=callbacks_list, verbose=1, epochs=50)

精度テスト

正確性を公正かつ合理的な方法でテストすることは困難です。単語ごとの比較を想定すると、同期中に 1 つの単語が間違って配置されると、精度は 0% になる可能性があります。また、同期予測に一致する単語を削除すると、精度率は 99% まで高くなる可能性があります。

機械翻訳と画像注釈モデルで優れたパフォーマンスを発揮する BLEU 評価を使用しました。テストでは、文を 1 ~ 4 語の文字列である 4 つの n-gram に分割します。次の予測では、「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-Gramsグループの数を増やすことにより、評価の難しさを増やすことができます。次のコードを使用していくつかの例を実行してから、WikipediaでBLEU評価の説明を読むことをお勧めします。

#createファイルを読み取り、そのコンテンツを返すdefload_doc(filename):file = open(filename、 'r')text = file.close text defload_data(data_dir):text = files_in_folder = os.listdir(data_dir)filenein filenameintdmer(filenameintdmer -3:] == "npz":image = np.load(data_dir+filename)image.append(image ['feations'])else:#テキストを追加して、タグsyntax = 'でテキストを追加してラップします。 ' + load_doc(data_dir + filename) +' ' #Seperate each word with a space' '.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 ordertokenizer.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 modelloaded_model.load_weights("../../../../weights.hdf5") print("Loaded model from disk") # map an integer to a word defword_for_id(integer, tokenizer):for word, index in tokenizer.word_index.items: if index == integer: returnword returnNone print(word_for_id(17, tokenizer)) # generate a description for an image defgenerate_desc(model, tokenizer, photo, max_length): photo = np.array([photo]) # seed the generation process in_text = ' '#シーケンス印刷の全長にわたって反復 ', end='') for i in range(150): # integer encode input sequence sequence = tokenizer.texts_to_sequences([in_text])[0] # pad inputsequence = 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 wordisNone: 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 defevaluate_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 predictedprint(' Real----> ' + 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 =コンパイラ(dsl_path)compiled_website = compiler.compile(predicted [0]、 'index.html')print(compiled_website)print(bleu)

出力

出力サンプルリンク:

  • 生成されたウェブサイト1-オリジナル1

    (https://emilwallner.github.io/bootstrap/pred_1/)(https://emilwallner.github.io/boottrap/real_1/)

  • 生成されたウェブサイト2-オリジナル2

    ()()

  • 生成されたウェブサイト3-オリジナル3

    ()()

  • 生成されたウェブサイト4-オリジナル4

    ()()

  • 生成されたウェブサイト5-オリジナル5

    ()()

回り道:

  • モデルテストをランダムに選択するのではなく、各モデルの欠点を理解します。当初、私が採用した方法は、バッチの正規化、双方向ネットワーキング、さらには注意を向けようとするなど、比較的ランダムでした。テストデータを見た後、これらの方法が色と位置を正確に予測できないことに気付きました。これにより、最大プーリング方法ではなくステップサイズを増やす方法を使用するようになりました。損失は​​0.12から0.02に低下し、BLEUスコアは85%から97%に上昇しました。

  • 関連する場合、事前に訓練されたモデルのみが考慮されます。小さなデータセットの場合、訓練された画像モデルがパフォーマンスを改善できると思います。私の個人的な経験では、エンドツーエンドモデルは時間がかかり、より多くのメモリが必要ですが、精度率は30%増加します。

  • リモートサーバーを使用してモデルを実行する場合は、わずかな逸脱を考慮する必要があります。私のMacはファイルをアルファベット順に読み取りますが、サーバーではファイルがランダムに読み取られます。これにより、スクリーンショットとコード間の不一致につながる可能性があります。予測の結果は収束していますが、有効なデータは再戦前より50%悪くなっています。

  • 参照されているライブラリ関数をマスターします。語彙の空のエントリの塗りつぶしスペースが含まれています。特別な追加が行われない場合、このマークは識別に含まれません。これは、最終結果で「単一」マークが予測されていないといういくつかの観察からこれに気付きました。簡単なチェックの後、私はこれがシソーラスに含まれていないことに気付きました。同時に、トレーニングとテストの場合、同じ順序でのレキシコンを使用する必要があることにも注意する必要があります。

  • 実験するときは軽量モデルを使用します。 LSTMの代わりにGRUを使用すると、各光栄光の反復サイクルの時間を30%短縮でき、結果にあまり影響を与えません。

[[218148]]

次に何が起こるでしょうか?

[[218149]]

  • フロントエンド開発は、深い学習を適用するための理想的な空間です。データの生成は簡単で、今日の深い学習アルゴリズムはほとんどのロジックを実装できます。

  • 興味深い部分は、「LSTMを通じて注目を集める」ことです。精度を向上させるために使用できるだけでなく、CNNがタグの生成に集中できるようにすることもできます。

  • 注意は、ラベル、スタイル、スクリプト、さらにはバックエンド間のコミュニケーションの鍵でもあります。注意層は変数を追跡できるため、ニューラルグリッドはさまざまなプログラミング言語で通信できます。

  • しかし、近い将来、最大の影響は、データを生成するためのスケーラブルな方法を構築することによるものです。次に、フォント、色、コンテンツ、アニメーションを段階的に追加できます。

  • 現在の進捗のほとんどは、スケッチをテンプレートに変換することです。 2年以内に、適用されたテンプレートを紙に描画してから、対応するフロントエンドコードを即座に生成できます。実際、Airbnbのデザインチーム(https://airbnb.design/sketching-interfaces/)およびuizard(https://www.uizard.io/)は、使用できるプロトタイプをすでに確立しています。

さらなる実験

  • 対応する構文に基づいて、安定したランダムアプリケーション/Webジェネレーターを作成します。

  • スケッチからアプリケーションまでのデータを生成します。アプリケーション/Webスクリーンショットをスケッチに自動的に変換し、GANとの多様性を構築します。

  • このモデルのように、各予測の焦点を視覚化するための注意レイヤーを追加します。

  • モジュラーアプローチのフレームワークを作成します。たとえば、フォントエンコーダー、カラーエンコーダー、構造エンコーダー、次にデコーダーを使用してそれらを統合します。安定した画像機能から始めるのは良いことです。

  • ニューラルネットワークにシンプルなHTMLコンポーネントを学習してから、CSSアニメーションを生成します。注意メカニズムと視覚入力ソースは本当に驚くべきものです。

著者について:Emil Wallner

以前はオックスフォードビジネススクールで働いていたディープラーニング近隣のシニアブロガーおよび投資家は、現在フランスに長い間住んでおり、非営利42(écoles)プロジェクトチームのメンバーです。翻訳を承認しました

<<:  ウー・ジアン:nEqual は、優れたユーザー エクスペリエンスで企業がスマートなビジネスを構築できるよう支援します

>>:  ハイブリッドクラウド環境でディープラーニングを取り入れたID認証はより柔軟

ブログ    

推薦する

データセンターで AI を活用する 5 つの理由

人工知能はかなり前から存在しており、その継続的な開発により、パフォーマンスの向上とコストの削減という...

2022年の展望: 自動化におけるイノベーションと機会

テクノロジーへの関心と導入が多様化するにつれ、多くの企業が将来の進路を決める岐路に立たされています。...

機械学習を使用してデータクレンジングを自動化する方法

調査会社ガートナーが最近発表した調査レポートによると、40%の企業がデータ品質の低さのためにビジネス...

AIで製造業を解放する: 企業がアプリケーションシナリオを発見し、課題に対処する方法

まとめ現在、さまざまな業界がデジタルビジネスシナリオを実装または強化するために機械学習機能を構築して...

[NCTSサミットレビュー] Rong360 Ai Hui: AIモデルテストの秘密を探る

2019年10月26日、Testinが主催する第2回NCTS中国クラウドテスト業界サミットが北京で開...

人工知能は何ができるのでしょうか?今日はそれを総合的に見ていきましょう。

電子廃棄物[[277263]]環境の持続可能性のために AI と IoT を活用すると、現在の環境保...

チップ不足は人工知能にどれほどの損害を与えるでしょうか?

現在の半導体サプライチェーンのボトルネックの根本的な原因は何年も前から潜んでいたが、COVID-19...

サイバーセキュリティのための AI: セキュリティ戦略への AI の組み込み

人工知能は、生産性の向上、売上の増加、ユーザーエクスペリエンスの向上など、さまざまな状況で使用されて...

開始から中止まで: ディープラーニングにおけるモデル蒸留技術

[[321813]]この記事の内容の一部はブログリンク[1]からのものであり、私が読んだいくつかの論...

...

...

このスタートアップは、アイドル状態のGPUを分散ネットワークに接続することで、AIモデルのトレーニングコストを90%削減できると主張している。

モンスターAPIは、採掘機器などのGPUコンピューティングパワーを使用してAIモデルをトレーニングし...

Ali Wensheng ビデオが Gen-2 と Pika に挑戦、1280×720 の解像度で圧迫感なし、3500 万のテキスト ビデオ表示効果

ヴィンセントのビデオはどの程度詳細にできますか?最近、アリババの調査により、1280×720 の解像...