Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 ww欧洲ww在线视频看ww,中文字幕亚洲欧美,www亚洲精品

          整合營銷服務(wù)商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          在C 中調(diào)用Dynamic JS和CSS

          在C 中調(diào)用Dynamic JS和CSS

          在本文中,我們將學(xué)習(xí)如何在MVC中設(shè)置JavaScript文件的動態(tài)版本。我們將創(chuàng)建一個簡單的MVC項目并從View中調(diào)用一個JavaScript文件。

          第1步

          打開Visual Studio并選擇“文件”>>“新建”,然后,單擊Project。

          第2步

          選擇“模板”>> Visual C#>> Web,然后ASP.NET Web應(yīng)用程序(.NET Framework),并輸入相應(yīng)的項目名稱,單擊“確定”按鈕。

          第3步

          從這里,選擇MVC項目(您可以根據(jù)您的要求選擇項目)。

          第4步

          現(xiàn)在,轉(zhuǎn)到要在其中創(chuàng)建擴展方法以附加版本的.cs文件。我正在創(chuàng)建一個Helper類,其中將添加以下代碼。

          注意:該類必須是靜態(tài)的且可公開訪問。

          在這里,我們將創(chuàng)建一個 HtmlHelper 擴展方法,我們可以在項目的任何地方使用它。復(fù)制以下代碼并將其放入.cs文件中。

          這樣,我們已經(jīng)創(chuàng)建了擴展方法,我們將在View中使用它來附加動態(tài)版本控制。

          第5步

          轉(zhuǎn)到.cshtml文件(您的視圖)并添加以下行。

          @Html.IncludeVersionedJs 是我們創(chuàng)建的擴展方法。

          用法:@Html.IncludeVersionedJs("YOUR FILE PATH")

          輔助類的完整代碼

          我的布局頁面

          輸出

          深度學(xué)習(xí)自動生成HTML代碼

          選自Floydhub

          作者:Emil Wallner

          機器之心編譯

          如何用前端頁面原型生成對應(yīng)的代碼一直是我們關(guān)注的問題,本文作者根據(jù) pix2code 等論文構(gòu)建了一個強大的前端代碼生成模型,并詳細解釋了如何利用 LSTM 與 CNN 將設(shè)計原型編寫為 HTML 和 CSS 網(wǎng)站。

          項目鏈接:github.com/emilwallner…

          在未來三年內(nèi),深度學(xué)習(xí)將改變前端開發(fā)。它將會加快原型設(shè)計速度,拉低開發(fā)軟件的門檻。

          Tony Beltramelli 在去年發(fā)布了論文《pix2code: Generating Code from a Graphical User Interface Screenshot》,Airbnb 也發(fā)布Sketch2code(airbnb.design/sketching-i…)。

          目前,自動化前端開發(fā)的最大阻礙是計算能力。但我們已經(jīng)可以使用目前的深度學(xué)習(xí)算法,以及合成訓(xùn)練數(shù)據(jù)來探索人工智能自動構(gòu)建前端的方法。在本文中,作者將教神經(jīng)網(wǎng)絡(luò)學(xué)習(xí)基于一張圖片和一個設(shè)計模板來編寫一個 HTML 和 CSS 網(wǎng)站。以下是該過程的簡要概述:

          1)向訓(xùn)練過的神經(jīng)網(wǎng)絡(luò)輸入一個設(shè)計圖

          2)神經(jīng)網(wǎng)絡(luò)將圖片轉(zhuǎn)化為 HTML 標記語言

          3)渲染輸出

          我們將分三步從易到難構(gòu)建三個不同的模型,首先,我們構(gòu)建最簡單地版本來掌握移動部件。第二個版本 HTML 專注于自動化所有步驟,并簡要解釋神經(jīng)網(wǎng)絡(luò)層。在最后一個版本 Bootstrap 中,我們將創(chuàng)建一個模型來思考和探索 LSTM 層。

          代碼地址:

          • github.com/emilwallner…
          • www.floydhub.com/emilwallner…

          所有 FloydHub notebook 都在 floydhub 目錄中,本地 notebook 在 local 目錄中。

          本文中的模型構(gòu)建基于 Beltramelli 的論文《pix2code: Generating Code from a Graphical User Interface Screenshot》和 Jason Brownlee 的圖像描述生成教程,并使用 Python 和 Keras 完成。

          核心邏輯

          我們的目標是構(gòu)建一個神經(jīng)網(wǎng)絡(luò),能夠生成與截圖對應(yīng)的 HTML/CSS 標記語言。

          訓(xùn)練神經(jīng)網(wǎng)絡(luò)時,你先提供幾個截圖和對應(yīng)的 HTML 代碼。網(wǎng)絡(luò)通過逐個預(yù)測所有匹配的 HTML 標記語言來學(xué)習(xí)。預(yù)測下一個標記語言的標簽時,網(wǎng)絡(luò)接收到截圖和之前所有正確的標記。

          這里是一個簡單的訓(xùn)練數(shù)據(jù)示例:docs.google.com/spreadsheet…。

          創(chuàng)建逐詞預(yù)測的模型是現(xiàn)在最常用的方法,也是本教程使用的方法。

          注意:每次預(yù)測時,神經(jīng)網(wǎng)絡(luò)接收的是同樣的截圖。也就是說如果網(wǎng)絡(luò)需要預(yù)測 20 個單詞,它就會得到 20 次同樣的設(shè)計截圖。現(xiàn)在,不用管神經(jīng)網(wǎng)絡(luò)的工作原理,只需要專注于神經(jīng)網(wǎng)絡(luò)的輸入和輸出。

          我們先來看前面的標記(markup)。假如我們訓(xùn)練神經(jīng)網(wǎng)絡(luò)的目的是預(yù)測句子「I can code」。當(dāng)網(wǎng)絡(luò)接收「I」時,預(yù)測「can」。下一次時,網(wǎng)絡(luò)接收「I can」,預(yù)測「code」。它接收所有之前單詞,但只預(yù)測下一個單詞。

          神經(jīng)網(wǎng)絡(luò)根據(jù)數(shù)據(jù)創(chuàng)建特征。神經(jīng)網(wǎng)絡(luò)構(gòu)建特征以連接輸入數(shù)據(jù)和輸出數(shù)據(jù)。它必須創(chuàng)建表征來理解每個截圖的內(nèi)容和它所需要預(yù)測的 HTML 語法,這些都是為預(yù)測下一個標記構(gòu)建知識。把訓(xùn)練好的模型應(yīng)用到真實世界中和模型訓(xùn)練過程差不多。

          我們無需輸入正確的 HTML 標記,網(wǎng)絡(luò)會接收它目前生成的標記,然后預(yù)測下一個標記。預(yù)測從「起始標簽」(start tag)開始,到「結(jié)束標簽」(end tag)終止,或者達到最大限制時終止。

          Hello World 版

          現(xiàn)在讓我們構(gòu)建 Hello World 版實現(xiàn)。我們將饋送一張帶有「Hello World!」字樣的截屏到神經(jīng)網(wǎng)絡(luò)中,并訓(xùn)練它生成對應(yīng)的標記語言。

          首先,神經(jīng)網(wǎng)絡(luò)將原型設(shè)計轉(zhuǎn)換為一組像素值。且每一個像素點有 RGB 三個通道,每個通道的值都在 0-255 之間。

          為了以神經(jīng)網(wǎng)絡(luò)能理解的方式表征這些標記,我使用了 one-hot 編碼。因此句子「I can code」可以映射為以下形式。

          在上圖中,我們的編碼包含了開始和結(jié)束的標簽。這些標簽?zāi)転樯窠?jīng)網(wǎng)絡(luò)提供開始預(yù)測和結(jié)束預(yù)測的位置信息。以下是這些標簽的各種組合以及對應(yīng) one-hot 編碼的情況。

          我們會使每個單詞在每一輪訓(xùn)練中改變位置,因此這允許模型學(xué)習(xí)序列而不是記憶詞的位置。在下圖中有四個預(yù)測,每一行是一個預(yù)測。且左邊代表 RGB 三色通道和之前的詞,右邊代表預(yù)測結(jié)果和紅色的結(jié)束標簽。

          #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 <HTML>Hello World!</HTML>
           [1., 0., 0.],
           [0., 1., 0.]]])
          #Turn next word into one-hot encoding
           next_words=np.array(
           [[0., 1., 0.], # <HTML>Hello World!</HTML>
           [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)
          復(fù)制代碼
          

          在 Hello World 版本中,我們使用三個符號「start」、「Hello World」和「end」。字符級的模型要求更小的詞匯表和受限的神經(jīng)網(wǎng)絡(luò),而單詞級的符號在這里可能有更好的性能。

          以下是執(zhí)行預(yù)測的代碼:

          # 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", "<HTML><center><H1>Hello World!</H1></center></HTML>", "end"]
          for i in sentence[0]:
          print(vocabulary[np.argmax(i)], end=' ')
          復(fù)制代碼
          

          輸出

          • 10 epochs: start start start
          • 100 epochs: start <HTML><center><H1>Hello World!</H1></center></HTML> <HTML><center><H1>Hello World!</H1></center></HTML>
          • 300 epochs: start <HTML><center><H1>Hello World!</H1></center></HTML> end

          我走過的坑:

          • 在收集數(shù)據(jù)之前構(gòu)建第一個版本。在本項目的早期階段,我設(shè)法獲得 Geocities 托管網(wǎng)站的舊版存檔,它有 3800 萬的網(wǎng)站。但我忽略了減少 100K 大小詞匯所需要的巨大工作量。
          • 訓(xùn)練一個 TB 級的數(shù)據(jù)需要優(yōu)秀的硬件或極其有耐心。在我的 Mac 遇到幾個問題后,最終用上了強大的遠程服務(wù)器。我預(yù)計租用 8 個現(xiàn)代 CPU 和 1 GPS 內(nèi)部鏈接以運行我的工作流。
          • 在理解輸入與輸出數(shù)據(jù)之前,其它部分都似懂非懂。輸入 X 是屏幕的截圖和以前標記的標簽,輸出 Y 是下一個標記的標簽。當(dāng)我理解這一點時,其它問題都更加容易弄清了。此外,嘗試其它不同的架構(gòu)也將更加容易。
          • 圖片到代碼的網(wǎng)絡(luò)其實就是自動描述圖像的模型。即使我意識到了這一點,但仍然錯過了很多自動圖像摘要方面的論文,因為它們看起來不夠炫酷。一旦我意識到了這一點,我對問題空間的理解就變得更加深刻了。

          在 FloydHub 上運行代碼

          FloydHub 是一個深度學(xué)習(xí)訓(xùn)練平臺,我自從開始學(xué)習(xí)深度學(xué)習(xí)時就對它有所了解,我也常用它訓(xùn)練和管理深度學(xué)習(xí)試驗。我們能安裝它并在 10 分鐘內(nèi)運行第一個模型,它是在云 GPU 上訓(xùn)練模型最好的選擇。若果讀者沒用過 FloydHub,可以花 10 分鐘左右安裝并了解。

          FloydHub 地址:www.floydhub.com/

          復(fù)制 Repo:

          https://github.com/emilwallner/Screenshot-to-code-in-Keras.git
          復(fù)制代碼
          

          登錄并初始化 FloydHub 命令行工具:

          cd Screenshot-to-code-in-Keras
          floyd login
          floyd init s2c
          復(fù)制代碼
          

          在 FloydHub 云 GPU 機器上運行 Jupyter notebook:

          floyd run --gpu --env tensorflow-1.4 --data emilwallner/datasets/imagetocode/2:data --mode jupyter
          復(fù)制代碼
          

          所有的 notebook 都放在 floydbub 目錄下。一旦我們開始運行模型,那么在 floydhub/Helloworld/helloworld.ipynb 下可以找到第一個 Notebook。更多詳情請查看本項目早期的 flags。

          HTML 版本

          在這個版本中,我們將關(guān)注與創(chuàng)建一個可擴展的神經(jīng)網(wǎng)絡(luò)模型。該版本并不能直接從隨機網(wǎng)頁預(yù)測 HTML,但它是探索動態(tài)問題不可缺少的步驟。

          概覽

          如果我們將前面的架構(gòu)擴展為以下右圖展示的結(jié)構(gòu),那么它就能更高效地處理識別與轉(zhuǎn)換過程。

          該架構(gòu)主要有兩個部,即編碼器與解碼器。編碼器是我們創(chuàng)建圖像特征和前面標記特征(markup features)的部分。特征是網(wǎng)絡(luò)創(chuàng)建原型設(shè)計和標記語言之間聯(lián)系的構(gòu)建塊。在編碼器的末尾,我們將圖像特征傳遞給前面標記的每一個單詞。隨后解碼器將結(jié)合原型設(shè)計特征和標記特征以創(chuàng)建下一個標簽的特征,這一個特征可以通過全連接層預(yù)測下一個標簽。

          設(shè)計原型的特征

          因為我們需要為每個單詞插入一個截屏,這將會成為訓(xùn)練神經(jīng)網(wǎng)絡(luò)的瓶頸。因此我們抽取生成標記語言所需要的信息來替代直接使用圖像。這些抽取的信息將通過預(yù)訓(xùn)練的 CNN 編碼到圖像特征中,且我們將使用分類層之前的層級輸出以抽取特征。

          我們最終得到 1536 個 8*8 的特征圖,雖然我們很難直觀地理解它,但神經(jīng)網(wǎng)絡(luò)能夠從這些特征中抽取元素的對象和位置。

          標記特征

          在 Hello World 版本中,我們使用 one-hot 編碼以表征標記。而在該版本中,我們將使用詞嵌入表征輸入并使用 one-hot 編碼表示輸出。我們構(gòu)建每個句子的方式保持不變,但我們映射每個符號的方式將會變化。one-hot 編碼將每一個詞視為獨立的單元,而詞嵌入會將輸入數(shù)據(jù)表征為一個實數(shù)列表,這些實數(shù)表示標記標簽之間的關(guān)系。

          上面詞嵌入的維度為 8,但一般詞嵌入的維度會根據(jù)詞匯表的大小在 50 到 500 間變動。以上每個單詞的八個數(shù)值就類似于神經(jīng)網(wǎng)絡(luò)中的權(quán)重,它們傾向于刻畫單詞之間的聯(lián)系(Mikolov alt el., 2013)。這就是我們開始部署標記特征(markup features)的方式,而這些神經(jīng)網(wǎng)絡(luò)訓(xùn)練的特征會將輸入數(shù)據(jù)和輸出數(shù)據(jù)聯(lián)系起來。

          編碼器

          我們現(xiàn)在將詞嵌入饋送到 LSTM 中,并期望能返回一系列的標記特征。這些標記特征隨后會饋送到一個 Time Distributed 密集層,該層級可以視為有多個輸入和輸出的全連接層。

          和嵌入與 LSTM 層相平行的還有另外一個處理過程,其中圖像特征首先會展開成一個向量,然后再饋送到一個全連接層而抽取出高級特征。這些圖像特征隨后會與標記特征相級聯(lián)而作為編碼器的輸出。

          標記特征

          如下圖所示,現(xiàn)在我們將詞嵌入投入到 LSTM 層中,所有的語句都會用零填充以獲得相同的向量長度。

          為了混合信號并尋找高級模式,我們運用了一個 TimeDistributed 密集層以抽取標記特征。TimeDistributed 密集層和一般的全連接層非常相似,且它有多個輸入與輸出。

          圖像特征

          對于另一個平行的過程,我們需要將圖像的所有像素值展開成一個向量,因此信息不會被改變,它們只會用來識別。

          如上,我們會通過全連接層混合信號并抽取更高級的概念。因為我們并不只是處理一個輸入值,因此使用一般的全連接層就行了。

          級聯(lián)圖像特征和標記特征

          所有的語句都被填充以創(chuàng)建三個標記特征。因為我們已經(jīng)預(yù)處理了圖像特征,所以我們能為每一個標記特征添加圖像特征。

          如上,在復(fù)制圖像特征到對應(yīng)的標記特征后,我們得到了新的圖像-標記特征(image-markup features),這就是我們饋送到解碼器的輸入值。

          解碼器

          現(xiàn)在,我們使用圖像-標記特征來預(yù)測下一個標簽。

          在下面的案例中,我們使用三個圖像-標簽特征對來輸出下一個標簽特征。注意 LSTM 層不應(yīng)該返回一個長度等于輸入序列的向量,而只需要預(yù)測預(yù)測一個特征。在我們的案例中,這個特征將預(yù)測下一個標簽,它包含了最后預(yù)測的信息。

          最后的預(yù)測

          密集層會像傳統(tǒng)前饋網(wǎng)絡(luò)那樣工作,它將下一個標簽特征中的 512 個值與最后的四個預(yù)測連接起來,即我們在詞匯表所擁有的四個單詞:start、hello、world 和 end。密集層最后采用的 softmax 函數(shù)會為四個類別產(chǎn)生一個概率分布,例如 [0.1, 0.1, 0.1, 0.7] 將預(yù)測第四個詞為下一個標簽。

          # 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)
          復(fù)制代碼
          

          輸出

          訓(xùn)練不同輪數(shù)所生成網(wǎng)站的地址:

          • 250 epochs:emilwallner.github.io/html/250_ep…
          • 350 epochs:emilwallner.github.io/html/350_ep…
          • 450 epochs:emilwallner.github.io/html/450_ep…
          • 550 epochs:emilwallner.github.io/html/550_ep…

          我走過的坑:

          • 我認為理解 LSTM 比 CNN 要難一些。當(dāng)我展開 LSTM 后,它們會變得容易理解一些。此外,我們在嘗試理解 LSTM 前,可以先關(guān)注輸入與輸出特征。
          • 從頭構(gòu)建一個詞匯表要比壓縮一個巨大的詞匯表容易得多。這樣的構(gòu)建包括字體、div 標簽大小、變量名的 hex 顏色和一般單詞。
          • 大多數(shù)庫是為解析文本文檔而構(gòu)建。在庫的使用文檔中,它們會告訴我們?nèi)绾瓮ㄟ^空格進行分割,而不是代碼,我們需要自定義解析的方式。
          • 我們可以從 ImageNet 上預(yù)訓(xùn)練的模型抽取特征。然而,相對于從頭訓(xùn)練的 pix2code 模型,損失要高 30% 左右。此外,我對于使用基于網(wǎng)頁截屏預(yù)訓(xùn)練的 inception-resnet 網(wǎng)絡(luò)很有興趣。

          Bootstrap 版本

          在最終版本中,我們使用 pix2code 論文中生成 bootstrap 網(wǎng)站的數(shù)據(jù)集。使用 Twitter 的 Bootstrap 庫(getbootstrap.com/),我們可以結(jié)合 HTML 和 CSS,降低詞匯表規(guī)模。

          我們將使用這一版本為之前未見過的截圖生成標記。我們還深入研究它如何構(gòu)建截圖和標記的先驗知識。

          我們不在 bootstrap 標記上訓(xùn)練,而是使用 17 個簡化 token,將其編譯成 HTML 和 CSS。數(shù)據(jù)集(github.com/tonybeltram…)包括 1500 個測試截圖和 250 個驗證截圖。平均每個截圖有 65 個 token,一共有 96925 個訓(xùn)練樣本。

          我們稍微修改一下 pix2code 論文中的模型,使之預(yù)測網(wǎng)絡(luò)組件的準確率達到 97%。

          端到端方法

          從預(yù)訓(xùn)練模型中提取特征在圖像描述生成模型中效果很好。但是幾次實驗后,我發(fā)現(xiàn) pix2code 的端到端方法效果更好。在我們的模型中,我們用輕量級卷積神經(jīng)網(wǎng)絡(luò)替換預(yù)訓(xùn)練圖像特征。我們不使用最大池化來增加信息密度,而是增加步幅。這可以保持前端元素的位置和顏色。

          存在兩個核心模型:卷積神經(jīng)網(wǎng)絡(luò)(CNN)和循環(huán)神經(jīng)網(wǎng)絡(luò)(RNN)。最常用的循環(huán)神經(jīng)網(wǎng)絡(luò)是長短期記憶(LSTM)網(wǎng)絡(luò)。我之前的文章中介紹過 CNN 教程,本文主要介紹 LSTM。

          理解 LSTM 中的時間步

          關(guān)于 LSTM 比較難理解的是時間步。我們的原始神經(jīng)網(wǎng)絡(luò)有兩個時間步,如果你給它「Hello」,它就會預(yù)測「World」。但是它會試圖預(yù)測更多時間步。下例中,輸入有四個時間步,每個單詞對應(yīng)一個時間步。

          LSTM 適合時序數(shù)據(jù)的輸入,它是一種適合順序信息的神經(jīng)網(wǎng)絡(luò)。模型展開圖示如下,對于每個循環(huán)步,你需要保持同樣的權(quán)重。

          加權(quán)后的輸入與輸出特征在級聯(lián)后輸入到激活函數(shù),并作為當(dāng)前時間步的輸出。因為我們重復(fù)利用了相同的權(quán)重,它們將從一些輸入獲取信息并構(gòu)建序列的知識。下面是 LSTM 在每一個時間步上的簡化版處理過程:

          理解 LSTM 層級中的單元

          每一層 LSTM 單元的總數(shù)決定了它記憶的能力,同樣也對應(yīng)于每一個輸出特征的維度大小。LSTM 層級中的每一個單元將學(xué)習(xí)如何追蹤句法的不同方面。以下是一個 LSTM 單元追蹤標簽行信息的可視化,它是我們用來訓(xùn)練 bootstrap 模型的簡單標記語言。

          每一個 LSTM 單元會維持一個單元狀態(tài),我們可以將單元狀態(tài)視為記憶。權(quán)重和激活值可使用不同的方式修正狀態(tài)值,這令 LSTM 層可以通過保留或遺忘輸入信息而得到精調(diào)。除了處理當(dāng)前輸入信息與輸出信息,LSTM 單元還需要修正記憶狀態(tài)以傳遞到下一個時間步。

          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='<START> ' + load_doc(data_dir+filename) + ' <END>'
          # 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)
          復(fù)制代碼
          

          測試準確率

          找到一種測量準確率的優(yōu)秀方法非常棘手。比如一個詞一個詞地對比,如果你的預(yù)測中有一個詞不對照,準確率可能就是 0。如果你把百分百對照的單詞移除一個,最終的準確率可能是 99/100。

          我使用的是 BLEU 分值,它在機器翻譯和圖像描述模型實踐上都是最好的。它把句子分解成 4 個 n-gram,從 1-4 個單詞的序列。在下面的預(yù)測中,「cat」應(yīng)該是「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。然后用總和乘以句子長度的懲罰函數(shù)。因為在我們的示例中,長度是正確的,所以它就直接是我們的最終得分。

          你可以增加 n-gram 的數(shù)量,4 個 n-gram 的模型是最為對應(yīng)人類翻譯的。我建議你閱讀下面的代碼:

          #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='<START> ' + load_doc(data_dir+filename) + ' <END>'
          #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='<START> '
          # iterate over the whole length of the sequence
          print('\nPrediction---->\n\n<START> ', 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=='<END>':
          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)
          復(fù)制代碼
          

          輸出

          樣本輸出的鏈接:

          • Generated website 1 - Original 1 (emilwallner.github.io/bootstrap/r…)
          • Generated website 2 - Original 2 (emilwallner.github.io/bootstrap/r…)
          • Generated website 3 - Original 3 (emilwallner.github.io/bootstrap/r…)
          • Generated website 4 - Original 4 (emilwallner.github.io/bootstrap/r…)
          • Generated website 5 - Original 5 (emilwallner.github.io/bootstrap/r…)

          我走過的坑:

          • 理解模型的弱點而不是測試隨機模型。首先我使用隨機的東西,比如批歸一化、雙向網(wǎng)絡(luò),并嘗試實現(xiàn)注意力機制。在查看測試數(shù)據(jù),并知道其無法高精度地預(yù)測顏色和位置之后,我意識到 CNN 存在一個弱點。這致使我使用增加的步幅來取代最大池化。驗證損失從 0.12 降至 0.02,BLEU 分值從 85% 增加至 97%。
          • 如果它們相關(guān),則只使用預(yù)訓(xùn)練模型。在小數(shù)據(jù)的情況下,我認為一個預(yù)訓(xùn)練圖像模型將會提升性能。從我的實驗來看,端到端模型訓(xùn)練更慢,需要更多內(nèi)存,但是精確度會提升 30%。
          • 當(dāng)你在遠程服務(wù)器上運行模型,我們需要為一些不同做好準備。在我的 mac 上,它按照字母表順序讀取文檔。但是在服務(wù)器上,它被隨機定位。這在代碼和截圖之間造成了不匹配。

          下一步

          前端開發(fā)是深度學(xué)習(xí)應(yīng)用的理想空間。數(shù)據(jù)容易生成,并且當(dāng)前深度學(xué)習(xí)算法可以映射絕大部分邏輯。一個最讓人激動的領(lǐng)域是注意力機制在 LSTM 上的應(yīng)用。這不僅會提升精確度,還可以使我們可視化 CNN 在生成標記時所聚焦的地方。注意力同樣是標記、可定義模板、腳本和最終端之間通信的關(guān)鍵。注意力層要追蹤變量,使網(wǎng)絡(luò)可以在編程語言之間保持通信。

          但是在不久的將來,最大的影響將會來自合成數(shù)據(jù)的可擴展方法。接著你可以一步步添加字體、顏色和動畫。目前為止,大多數(shù)進步發(fā)生在草圖(sketches)方面并將其轉(zhuǎn)化為模版應(yīng)用。在不到兩年的時間里,我們將創(chuàng)建一個草圖,它會在一秒之內(nèi)找到相應(yīng)的前端。Airbnb 設(shè)計團隊與 Uizard 已經(jīng)創(chuàng)建了兩個正在使用的原型。下面是一些可能的試驗過程:

          實驗

          開始

          • 運行所有模型
          • 嘗試不同的超參數(shù)
          • 測試一個不同的 CNN 架構(gòu)
          • 添加雙向 LSTM 模型
          • 用不同數(shù)據(jù)集實現(xiàn)模型

          進一步實驗

          • 使用相應(yīng)的語法創(chuàng)建一個穩(wěn)定的隨機應(yīng)用/網(wǎng)頁生成器
          • 從草圖到應(yīng)用模型的數(shù)據(jù)。自動將應(yīng)用/網(wǎng)頁截圖轉(zhuǎn)化為草圖,并使用 GAN 創(chuàng)建多樣性。
          • 應(yīng)用注意力層可視化每一預(yù)測的圖像聚焦,類似于這個模型
          • 為模塊化方法創(chuàng)建一個框架。比如,有字體的編碼器模型,一個用于顏色,另一個用于排版,并使用一個解碼器整合它們。穩(wěn)定的圖像特征是一個好的開始。
          • 饋送簡單的 HTML 組件到神經(jīng)網(wǎng)絡(luò)中,并使用 CSS 教其生成動畫。使用注意力方法并可視化兩個輸入源的聚焦將會很迷人。

          原文鏈接:blog.floydhub.com/turning-des…

          本文為機器之心編譯,轉(zhuǎn)載請聯(lián)系本公眾號獲得授權(quán)。

          . 服務(wù)器的購買

          1. 我選擇的是阿里云的服務(wù)器,學(xué)生價9.5元一個月,百度直接搜索阿里云,然后點擊右上角登錄,推薦大家用支付寶掃碼登錄,方便快捷。阿里云官網(wǎng)的東西比較多,登錄后我找了很久也沒有找到學(xué)生服務(wù)器在哪里賣,購買的時候需要進行學(xué)生認證,按照他的要求一步步來就好,認證大概需要幾個小時。如果你不是學(xué)生那就直接購買ecs服務(wù)器就好,首頁就可以看到ecs服務(wù)器的購買地址,但是要比學(xué)生服務(wù)器貴不少。 在這里要說一下預(yù)裝環(huán)境的選擇,因為大部分服務(wù)器都是linux系統(tǒng),linux中centos的使用又是最多的,所以推薦大家也選擇centos系統(tǒng),然后是應(yīng)用鏡像的選擇,應(yīng)用鏡像的作用主要就是幫你預(yù)裝服務(wù)器的環(huán)境,比如mysql,apache,tomcat這些,有的還會給你提供管理服務(wù)器的面板,方便對服務(wù)器的操作。應(yīng)用鏡像可用可不用,如果你只是想快速的配置好服務(wù)器,推薦大家安裝寶塔linux面板,使用起來很方便,如果你想了解或者已經(jīng)了解一些linux的使用,就可以忽略應(yīng)用鏡像。如果是用來學(xué)習(xí)的話地域的選擇是無所謂的,可以選擇一個離自己近的。

          2.服務(wù)器購買成功之后在阿里云的首頁右上角進入控制臺,控制臺的側(cè)邊欄中有esc服務(wù)器或者輕量級服務(wù)器也就是學(xué)生服務(wù)器,點擊進入后你就可以看到自己購買的服務(wù)器,右下角就是你服務(wù)器的ip地址,接下來要用到。

          二. 服務(wù)器的配置

          1.首先點擊遠程連接中的設(shè)置root密碼,這是連接服務(wù)器要用到的。

          2.然后在防火墻中點擊添加規(guī)則開放端口,為了方便我開啟了如圖中的端口。你也可以只開啟21,22,443,8080這幾個端口,如果你使用的是寶塔linux,則還需要打開8888端口。

          三. 服務(wù)器環(huán)境手動搭建

          現(xiàn)在服務(wù)器已經(jīng)有了,該怎么使用呢?如果要使用命令行手動搭建環(huán)境,最好大家要對linux命令有一些了解,如果你不想使用linux命令來快速搭建環(huán)境,且安裝了寶塔linux面板,請直接看第四部分。

          1. 工具準備
            我們需要兩款軟件來連接到服務(wù)器,一個叫Xshell,用來操控服務(wù)器,另一個叫Xftp,用來進行服務(wù)器和自己電腦之間的文件傳輸。直接百度或者在360寶庫中就可以下載到這兩款軟件。

          2.Xshell的連接Xshell的使用很方便,首先輸入自己服務(wù)器的IP地址,在阿里云服務(wù)器列表的右下角就有你服務(wù)器的IP地址,點擊連接,然后用戶名輸入root,密碼輸入你在前面設(shè)置的root密碼,當(dāng)屏幕顯示welcome to alibaba cloud時,說明你連接成功了。

          3.Xftp的連接Xftp的登錄和Xshell類似,輸入服務(wù)器IP,用戶輸入root,然后輸入root密碼,登錄成功后,左邊框為你自己電腦上的文件,右邊為服務(wù)器上的文件,左右拖動來進行文件的上傳和下載。

          4.JDK的安裝這兩個軟件安裝好之后我們便可以開始服務(wù)器環(huán)境的搭建,因為是學(xué)習(xí)用的簡單環(huán)境,并發(fā)不高,所以并沒有使用nginx,apache或者redis這些,使用的java環(huán)境為簡單的tomcat+mysql,環(huán)境搭建我們需要使用Xshell來完成。在安裝tomcat之前我們首先要進行jdk的安裝,linux系統(tǒng)上jdk的安裝十分簡單,我使用的是1.8版本的jdk,運行命令 yum -y install java-1.8.0-openjdk.x86_64,屏幕上出現(xiàn)Complete時,說明安裝成功了。接著你可以運行java -version,顯示出當(dāng)前java版本說明沒有問題。

          5.Tomcat的安裝接下來是tomcat的安裝,yum上沒有tomcat的源,所以需要wget的方式來下載,首先通過cd /opt來切換到opt目錄下。

          運行命令wget http://mirrors.shu.edu.cn/apache/tomcat/tomcat-8/v8.5.32/bin/apache-tomcat-8.5.32.tar.gzsrc="https://yqfile.alicdn.com/ac733c3534aaa8aedbfb616ce5d0603cc01eaf56.png" alt="image" title="image">

          執(zhí)行完畢之后我們已經(jīng)將tomcat壓縮包下載到了opt目錄下,然后我們運行命令 tar xzf apache-tomcat-8.5.32.tar.gz 來解壓這個壓縮包。

          現(xiàn)在我們在Xftp中是可以看到這兩個文件的,我們可以單擊解壓后的文件按F2來重命名為tomcat8.5,方便我們使用命令行來對他進行操作。

          執(zhí)行命令/opt//tomcat8.5/bin/startup.sh運行tomcat,顯示tomcat started,說明啟動成功了

          我們也可以輸入netstat -anp|grep 8080來查看8080端口

          這個時候我們已經(jīng)可以從外網(wǎng)訪問了,在你的瀏覽器上直接訪問你的服務(wù)器ip地址加端口號,例如http://39.107.104.52:8080/,如果訪問成功說明我們的tomcat已經(jīng)配置好了。

          6.mysql的安裝yum上mysql的資源有問題,所以不能僅僅之用yum。在使用yum之前還需要用其他命令獲取mysql社區(qū)版,執(zhí)行命令wget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm。

          這時候我們就可以通過yum進行安裝了,執(zhí)yum install mysql mysql-server mysql-devel -y,最后顯示complete則說明安裝成功。

          安裝成功后,我們通過systemctl start mysql.service來啟動mysql服務(wù)器,然后我們依舊可以執(zhí)行netstat -anp|grep 3306命令來查看mysql是否啟動。

          通過yum安裝的mysql的管理員賬戶是沒有密碼的,這里通過命令設(shè)置其密碼為 admin ,大家也可以設(shè)為其他,執(zhí)行命令mysqladmin -u root password admin。

          注: Warning信息并非提示設(shè)置失敗,而是告訴大家密碼露出來了,當(dāng)心背后有人。

          7.項目和數(shù)據(jù)庫的上傳我們通過mysql -uroot -padmin命令來登錄數(shù)據(jù)庫,admin是密碼,如果你設(shè)置成了其他密碼在這里請更換為自己設(shè)置的,通過CREATE DATABASE xxx DEFAULT CHARACTER SET utf8;命令來創(chuàng)建數(shù)據(jù)庫,記得在進入數(shù)據(jù)庫后執(zhí)行的命令后要加分號,xxx為數(shù)據(jù)庫名,在創(chuàng)建時改為你要創(chuàng)建的數(shù)據(jù)庫名,創(chuàng)建后執(zhí)行show databases;,即可看到你所創(chuàng)建的數(shù)據(jù)庫。很多時候數(shù)據(jù)庫都是我們本地創(chuàng)建好后導(dǎo)入至服務(wù)器,我們首先需要使用Xftp將數(shù)據(jù)庫文件傳輸?shù)椒?wù)器上,我們可以通過mysql -u root -padmin --default-character-set=utf8 xxx < /home/xxx.sql命令來導(dǎo)入數(shù)據(jù)庫,xxx即為數(shù)據(jù)庫名,/home/xxx.sql為數(shù)據(jù)文件的路徑。導(dǎo)入操作完成后,我們再次通過mysql -uroot -padmin命令來登錄數(shù)據(jù)庫,執(zhí)行use xxx; ,然后show tables;,查看導(dǎo)入的數(shù)據(jù)庫。

          項目的上傳就較為簡單了,我們只需將項目直接放入tomcat的webapps目錄中即可,或者將項目打包成war文件后放入,重啟tomcat后war文件會被自動解析。關(guān)閉tomcat的命令為/opt/tomcat8.5/bin/shutdown.sh,關(guān)閉后再打開完成重啟。

          這時候你就可以在外網(wǎng)訪問到你的項目了,例如http://39.107.104.52:8080/shop/

          到這里服務(wù)器搭建就算完成了,如果你還想對你的服務(wù)器做進一步的優(yōu)化,提高網(wǎng)站的訪問速度和服務(wù)器的性能,請看第五部分——Nginx的使用,使用nginx還有一個好處就是可以在不備份的情況下去掉8080端口(正常情況下我們不備份網(wǎng)站是無法去掉端口號的去使用網(wǎng)站默認的80端口的),比如可以將http://39.107.104.52:8080/shop變?yōu)閔ttp://39.107.104.52/shop

          四.寶塔linux面板環(huán)境搭建

          1. 寶塔面板登錄
            寶塔面板的使用較為簡單,首先從控制臺進入服務(wù)器管理頁面,然后進入應(yīng)用詳情,點擊復(fù)制

          然后遠程連接,連接成功后右鍵將復(fù)制的內(nèi)容粘貼,回車運行,會顯示出寶塔面板的密碼,把它復(fù)制下來。

          退出遠程連接,點擊面板首頁地址。

          用戶名為admin,密碼為剛剛遠程連接后復(fù)制的密碼。

          1. 軟件安裝和配置
            登錄成功后在側(cè)邊欄找到軟件管理

          安裝tomcat和mysql,我安裝的tomcat版本為8.5,mysql版本為5.7。

          在等待安裝的這段時間里,我們先開放端口,點擊側(cè)邊欄中的安全,放行8080端口。

          安裝完成后,我們這時已經(jīng)可以從外網(wǎng)訪問到tomcat頁面。訪問如http://39.107.104.52:8080/,IP地址要換成你自己服務(wù)器的IP地址。

          上傳數(shù)據(jù)庫

          從側(cè)邊欄進入數(shù)據(jù)庫,點擊添加數(shù)據(jù)庫,密碼可以隨機生成,也可以自己設(shè)置。

          添加成功后點擊導(dǎo)入,即可將本地的sql數(shù)據(jù)庫文件上傳到服務(wù)器。

          上傳項目

          在軟件管理中點擊tomcat的文件位置,進入tomcat。

          打開tomcat的webapps文件夾,點擊左上角的上傳,將項目文件或者項目的war包放入后重啟tomcat即可。

          這時候你就可以在外網(wǎng)訪問到你的項目了,例如http://39.107.104.52:8080/shop/

          到這里服務(wù)器搭建就算完成了,如果你還想對你的服務(wù)器做進一步的優(yōu)化,提高網(wǎng)站的訪問速度和服務(wù)器的性能,請看第五部分——Nginx的使用,使用nginx還有一個好處就是可以在不備份的情況下去掉8080端口(正常情況下我們不備份網(wǎng)站是無法去掉端口號的去使用網(wǎng)站默認的80端口的),比如可以將http://39.107.104.52:8080/shop變?yōu)閔ttp://39.107.104.52/shop

          五 .服務(wù)器性能優(yōu)化(Nginx的使用)

          Nginx是一個反向代理服務(wù)器,使用nginx可以實現(xiàn)動靜分離和負載均衡,動靜分離是指在處理用戶請求時,由nginx處理靜態(tài)請求,tomcat處理動態(tài)請求,降低了tomcat的負載,讓tomcat可以專注處理動態(tài)請求。負載均衡是指nginx可以同時連接多個tomcat即tomcat集群,將用戶的動態(tài)請求均衡的轉(zhuǎn)發(fā)給各個tomcat。那么,Nginx該如何使用呢?

          1.使用寶塔面板安裝配置Nginx在軟件管理中找到Nginx點擊安裝,在這里我安裝的是1.14版本。

          安裝完成后需要對nginx進行配置,點擊nginx的設(shè)置,進入設(shè)置頁面,點擊配置修改,將原本的配置文件全部刪除,改成如下內(nèi)容:

          user  www www;
          worker_processes auto;
          error_log  /www/wwwlogs/nginx_error.log  crit;
          pid        /www/server/nginx/logs/nginx.pid;
          worker_rlimit_nofile 51200;

          events

          {
              use epoll;
              worker_connections 51200;
              multi_accept on;
          }

          http

          {
              include       mime.types;
              #include luawaf.conf;
          
              include proxy.conf;
          
              default_type  application/octet-stream;
          
              server_names_hash_bucket_size 512;
              client_header_buffer_size 32k;
              large_client_header_buffers 4 32k;
              client_max_body_size 50m;
          
              sendfile   on;
              tcp_nopush on;
          
              keepalive_timeout 60;
          
              tcp_nodelay on;
          
              fastcgi_connect_timeout 300;
              fastcgi_send_timeout 300;
              fastcgi_read_timeout 300;
              fastcgi_buffer_size 64k;
              fastcgi_buffers 4 64k;
              fastcgi_busy_buffers_size 128k;
              fastcgi_temp_file_write_size 256k;
              fastcgi_intercept_errors on;
          
              gzip on;
              gzip_min_length  1k;
              gzip_buffers     4 16k;
              gzip_http_version 1.1;
              gzip_comp_level 2;
              gzip_types     text/plain application/javascript application/x-javascript text/javascript text/css application/xml;
              gzip_vary on;
              gzip_proxied   expired no-cache no-store private auth;
              gzip_disable   "MSIE [1-6]\.";
          
              limit_conn_zone $binary_remote_addr zone=perip:10m;
              limit_conn_zone $server_name zone=perserver:10m;
          
              server_tokens off;
              access_log off;

          upstream tomcats{

          ip_hash;
          server 39.107.104.52:8080;
          server 39.107.104.52:8081;

          }

          server

          {
              listen 80;
              server_name localhost;
              index index.html index.htm index.jsp;
              root  /www/server/myadmin;
            
              
              #error_page   404   /404.html;
              include enable-php.conf;

          location / {

          proxy_pass http://tomcats;
            
          }

          location ~ .(gif|jpg|png)$ {

             expires 30d;
             access_log off;
              root /www/server/myadmin;
          }

          一鍵申請SSL證書驗證目錄相關(guān)設(shè)置

          location ~ \.well-known{
              allow all;
          }
              access_log  /www/wwwlogs/access.log;
          }

          include /www/server/panel/vhost/nginx/*.conf;}

          這個配置文件中,我們必須要了解的內(nèi)容有兩部分,文件中的 upstream tomcats中就是我們的tomcat地址,也就是nginx接收到動態(tài)請求后要轉(zhuǎn)發(fā)的地址,在這里我除了寶塔安裝的tomcat外,又手動安裝了一個tomcat,分別在8080和8081端口,手動安裝tomcat請參考第三部分中的tomcat安裝,如果你不想手動安裝,在這里可以只寫一個,將另一個刪掉,讓Nginx只做動靜分離,ip_hash是指綁定用戶IP,防止出現(xiàn)更換tomcat后session的問題,每個ip只能訪問到其中的一個tomcat,刪除掉這句話后刷新幾次頁面你會發(fā)現(xiàn)你會訪問不同的tomcat。server中的 root /www/server/myadmin 指的就是我們存放靜態(tài)文件的根目錄,當(dāng)有靜態(tài)請求時nginx將在這個目錄下尋找文件。 location ~ .(gif|jpg|png)$指的是當(dāng)請求以.gif|.jpg|.png結(jié)尾時判定其為靜態(tài)文件,直接去根目錄尋找,其他請求則轉(zhuǎn)發(fā)至tomcat,當(dāng)然你也可以把css,js等文件判定為靜態(tài)文件,只需將.js,.css加在里面即可。配置完畢后,就可以去訪問項目了,例如http://39.107.104.52:8080/shop/可以修改為http://39.107.104.52/shop/進行訪問了,這時你會發(fā)現(xiàn)項目中的圖片不見了,因為所有的以.gif|.jpg|.png結(jié)尾的文件請求都被nginx攔截了,我們需要將這些文件放在nginx的根目錄下,同時更改項目中的圖片路徑,例如路徑/picture/1.png指的就是/www/server/myadmin/picture/1.png。

          2.手動安裝Nginx因為我使用的是寶塔linux安裝的Nginx,并未親自操作手動安裝Nginx,所以推薦給大家另一篇博客https://www.cnblogs.com/taiyonghai/p/6728707.html,手動安裝Nginx較為復(fù)雜,有興趣的朋友們可以去看看。關(guān)于Nginx的配置,可以參考我上面寫的。

          博客到這里就結(jié)束啦,希望可以幫到大家,最后還要跟大家說的一件事就是在使用阿里云服務(wù)器時,出現(xiàn)任何問題都可以在控制臺提交工單,讓阿里的程序員們來幫你解決問題,但是工單的回復(fù)速度可能會比較慢。


          主站蜘蛛池模板: 农村乱人伦一区二区| 亚洲一区精品无码| 亚洲成a人一区二区三区| 一本岛一区在线观看不卡| 在线视频一区二区三区三区不卡| 亚洲夜夜欢A∨一区二区三区| 高清一区二区三区| 国产麻豆媒一区一区二区三区| 麻豆aⅴ精品无码一区二区| 国产一区二区三精品久久久无广告| 精品国产免费一区二区| 无码精品尤物一区二区三区| 无码免费一区二区三区免费播放| 无人码一区二区三区视频| 国产乱码伦精品一区二区三区麻豆| 日韩美一区二区三区| 午夜视频一区二区| 成人区人妻精品一区二区不卡| 亚洲综合一区二区三区四区五区| 精品国产乱子伦一区二区三区 | 在线|一区二区三区| 伊人色综合网一区二区三区 | 在线观看亚洲一区二区| 无码人妻精品一区二区三18禁 | 亚洲国产系列一区二区三区| 亚洲丰满熟女一区二区v| 无码国产伦一区二区三区视频| 中文字幕日本精品一区二区三区| 日韩十八禁一区二区久久| 日韩一区二区三区视频| 制服中文字幕一区二区| 久久精品岛国av一区二区无码| 高清一区二区三区免费视频| 日韩一区精品视频一区二区| 日韩一区二区超清视频| 国产综合精品一区二区| 国产精品区AV一区二区| 亚洲国产精品无码久久一区二区| tom影院亚洲国产一区二区| 成人在线观看一区| 真实国产乱子伦精品一区二区三区|