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 亚洲国产成人精彩精品,国产一级在线,国产精品网站在线观看

          整合營銷服務(wù)商

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

          免費(fèi)咨詢熱線:

          學(xué)前端怎能不知css系列-css初識

          人熟悉前端(html,css,js,vue等),后端(python),小程序,老板有需求聯(lián)系我。

          1.CSS初識

          • 概念: CSS(Cascading Style Sheets) ,通常稱為CSS樣式表或?qū)盈B樣式表(級聯(lián)樣式表)
          • 作用:主要用于設(shè)置 HTML頁面中的文本內(nèi)容(字體、大小、對齊方式等)、圖片的外形(寬高、邊框樣式、邊距等)以及版面的布局和外觀顯示樣式。CSS以HTML為基礎(chǔ),提供了豐富的功能,如字體、顏色、背景的控制及整體排版等,而且還可以針對不同的瀏覽器設(shè)置不同的樣式。

          2. 引入CSS樣式表(書寫位置)

          2.1 行內(nèi)式(內(nèi)聯(lián)樣式)

          • 概念: 稱行內(nèi)樣式、行間樣式. 是通過標(biāo)簽的style屬性來設(shè)置元素的樣式
          • 其基本語法格式如下:
          <標(biāo)簽名 style="屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3;"> 內(nèi)容 </標(biāo)簽名>

          實際上任何HTML標(biāo)簽都擁有style屬性,用來設(shè)置行內(nèi)式。

          • 案例:
          <div style="color: red; font-size: 12px;">青春不常在,抓緊談戀愛</div>
          • 注意:style其實就是標(biāo)簽的屬性樣式屬性和值中間是:多組屬性值之間用;隔開。只能控制當(dāng)前的標(biāo)簽和以及嵌套在其中的字標(biāo)簽,造成代碼冗余
          • 缺點:沒有實現(xiàn)樣式和結(jié)構(gòu)相分離

          2.2 內(nèi)部樣式表(內(nèi)嵌樣式表)

          • 概念: 稱內(nèi)嵌式 是將CSS代碼集中寫在HTML文檔的head頭部標(biāo)簽中,并且用style標(biāo)簽定義
          • 其基本語法格式如下:
          <head>
          <style type="text/CSS">
              選擇器(選擇的標(biāo)簽) { 
                屬性1: 屬性值1;
                屬性2: 屬性值2; 
                屬性3: 屬性值3;
              }
          </style>
          </head>
          <style>
               div {
                  color: red;
                  font-size: 12px;
               }
          </style>
          • 注意:style標(biāo)簽一般位于head標(biāo)簽中,當(dāng)然理論上他可以放在HTML文檔的任何地方。type="text/css" 在html5中可以省略。只能控制當(dāng)前的頁面
          • 缺點:沒有徹底分離

          綜合案例

          <style>
             /*選擇器{屬性:值;}*/
             p {
                color:#06C; 
                font-size:14px;  
              }  /*文字的顏色是 藍(lán)色*/
             h4 {
               color:#900;
             }
             h1 {
               color:#090; 
               font-size:16px; 
              }
             body { 
               background:url(bg2.jpg);
             }
          </style>

          2.3 外部樣式表(外鏈?zhǔn)剑?/h1>
          • 概念: 稱鏈入式 是將所有的樣式放在一個或多個以.CSS為擴(kuò)展名的外部樣式表文件中, 通過link標(biāo)簽將外部樣式表文件鏈接到HTML文檔中
          • 其基本語法格式如下:
          <head>
            <link rel="stylesheet" type="text/css" href="css文件路徑">
          </head>
          • 注意: link 是個單標(biāo)簽link標(biāo)簽需要放在head頭部標(biāo)簽中,并且指定link標(biāo)簽的三個屬性

          屬性

          作用

          rel

          定義當(dāng)前文檔與被鏈接文檔之間的關(guān)系,在這里需要指定為“stylesheet”,表示被鏈接的文檔是一個樣式表文件。

          type

          定義所鏈接文檔的類型,在這里需要指定為“text/CSS”,表示鏈接的外部文件為CSS樣式表。我們都可以省略

          href

          定義所鏈接外部樣式表文件的URL,可以是相對路徑,也可以是絕對路徑。

          2.4 三種樣式表總結(jié)(位置)

          樣式表

          優(yōu)點

          缺點

          使用情況

          控制范圍

          行內(nèi)樣式表

          書寫方便,權(quán)重高

          沒有實現(xiàn)樣式和結(jié)構(gòu)相分離

          較少

          控制一個標(biāo)簽(少)

          內(nèi)部樣式表

          部分結(jié)構(gòu)和樣式相分離

          沒有徹底分離

          較多

          控制一個頁面(中)

          外部樣式表

          完全實現(xiàn)結(jié)構(gòu)和樣式相分離

          需要引入

          最多,強(qiáng)烈推薦

          控制整個站點(多)

          CSS選擇器(重點)

          2. CSS基礎(chǔ)選擇器

          2.1 標(biāo)簽選擇器

          • 概念:標(biāo)簽選擇器(元素選擇器)是指用HTML標(biāo)簽名稱作為選擇器,按標(biāo)簽名稱分類,為頁面中某一類標(biāo)簽指定統(tǒng)一的CSS樣式。
          • 語法:
          標(biāo)簽名{屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3; } 
          • 作用:標(biāo)簽選擇器 可以把某一類標(biāo)簽全部選擇出來 比如所有的div標(biāo)簽 和 所有的 span標(biāo)簽
          • 優(yōu)點:是能快速為頁面中同類型的標(biāo)簽統(tǒng)一樣式
          • 缺點:不能設(shè)計差異化樣式。

          2.2 類選擇器

          類選擇器使用“.”(英文點號)進(jìn)行標(biāo)識,后面緊跟類名.

          • 語法:類名選擇器.類名 {
            屬性1:屬性值1;
            屬性2:屬性值2;
            屬性3:屬性值3;
            }
            標(biāo)簽<p class='類名'></p>
          • 優(yōu)點:可以為元素對象定義單獨(dú)或相同的樣式。 可以選擇一個或者多個標(biāo)簽
          • 注意類選擇器使用“.”(英文點號)進(jìn)行標(biāo)識,后面緊跟類名(自定義,我們自己命名的)長名稱或詞組可以使用中橫線來為選擇器命名。不要純數(shù)字、中文等命名, 盡量使用英文字母來表示。

          命名規(guī)范: 見附件(Web前端開發(fā)規(guī)范手冊.doc)

          命名是我們通俗約定的,但是沒有規(guī)定必須用這些常用的命名。

          課堂案例:

          <head>
                  <meta charset="utf-8">
                  <style>
              
                  .blue {
                      color: blue;
                      font-size: 100px;
                  }
                  .red {
                      color: red;
                      font-size: 100px;
                  }
                  .orange {
                      color: orange;
                      font-size: 100px;
                  }
                  .green {
                      color: green;
                      font-size: 100px;
                  }
                  </style>
              </head>
              <body>
                  <span class="blue">G</span>
                  <span class="red">o</span>
                  <span class="orange">o</span>
                  <span class="blue">g</span>
                  <span class="green">l</span>
                  <span class="red">e</span>
              </body>

          2.3 類選擇器特殊用法- 多類名

          我們可以給標(biāo)簽指定多個類名,從而達(dá)到更多的選擇目的。

          注意:

          • 各個類名中間用空格隔開。
          • 多類名選擇器在后期布局比較復(fù)雜的情況下,還是較多使用的。
          <div class="pink fontWeight font20">亞瑟</div>
          <div class="font20">劉備</div>
          <div class="font14 pink">安其拉</div>
          <div class="font14">貂蟬</div>

          2.4 id選擇器

          id選擇器使用#進(jìn)行標(biāo)識,后面緊跟id名

          • 其基本語法格式如下:id選擇器#id名 {屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3; }標(biāo)簽<p id="id名"></p>
          • 元素的id值是唯一的,只能對應(yīng)于文檔中某一個具體的元素。
          • 用法基本和類選擇器相同。

          id選擇器和類選擇器區(qū)別

          • W3C標(biāo)準(zhǔn)規(guī)定,在同一個頁面內(nèi),不允許有相同名字的id對象出現(xiàn),但是允許相同名字的class。

          id選擇器和類選擇器最大的不同在于 使用次數(shù)上。

          總結(jié)他們**

          • 類選擇器我們在修改樣式中,用的最多。
          • id選擇器一般用于頁面唯一性的元素身上,經(jīng)常和我們后面學(xué)習(xí)的javascript 搭配使用。

          2.6 通配符選擇器

          • 概念通配符選擇器用*號表示, * 就是 選擇所有的標(biāo)簽 他是所有選擇器中作用范圍最廣的,能匹配頁面中所有的元素。
          • 其基本語法格式如下:
          * { 屬性1:屬性值1; 屬性2:屬性值2; 屬性3:屬性值3; }

          例如下面的代碼,使用通配符選擇器定義CSS樣式,清除所有HTML標(biāo)記的默認(rèn)邊距。

          * {
            margin: 0;                    /* 定義外邊距*/
            padding: 0;                   /* 定義內(nèi)邊距*/
          }
          • 注意:會匹配頁面所有的元素,降低頁面響應(yīng)速度,不建議隨便使用

          2.7 基礎(chǔ)選擇器總結(jié)

          選擇器

          作用

          缺點

          使用情況

          用法

          標(biāo)簽選擇器

          可以選出所有相同的標(biāo)簽,比如p

          不能差異化選擇

          較多

          p { color:red;}

          類選擇器

          可以選出1個或者多個標(biāo)簽

          可以根據(jù)需求選擇

          非常多

          .nav { color: red; }

          id選擇器

          一次只能選擇器1個標(biāo)簽

          只能使用一次

          不推薦使用

          #nav {color: red;}

          通配符選擇器

          選擇所有的標(biāo)簽

          選擇的太多,有部分不需要

          不推薦使用

          * {color: red;}

          2.8 團(tuán)隊約定

          選擇器

          • 盡量少用通用選擇器 *
          • 盡量少用 ID 選擇器
          • 不使用無具體語義定義的標(biāo)簽選擇器 div span

          CSS字體樣式屬性調(diào)試工具

          1.font字體

          1.1 font-size:大小

          • 作用:font-size屬性用于設(shè)置字號
          p {  
              font-size:20px; 
          }
          • 單位:可以使用相對長度單位,也可以使用絕對長度單位。相對長度單位比較常用,推薦使用像素單位px,絕對長度單位使用較少。

          注意:

          • 我們文字大小以后,基本就用px了,其他單位很少使用
          • 谷歌瀏覽器默認(rèn)的文字大小為16px
          • 但是不同瀏覽器可能默認(rèn)顯示的字號大小不一致,我們盡量給一個明確值大小,不要默認(rèn)大小。一般給body指定整個頁面文字的大小

          1.2 font-family:字體

          • 作用:font-family屬性用于設(shè)置哪一種字體。
          p{ font-family:"微軟雅黑";}
          • 網(wǎng)頁中常用的字體有宋體、微軟雅黑、黑體等,例如將網(wǎng)頁中所有段落文本的字體設(shè)置為微軟雅黑
          • 可以同時指定多個字體,中間以逗號隔開,表示如果瀏覽器不支持第一個字體,則會嘗試下一個,直到找到合適的字體, 如果都沒有,則以我們電腦默認(rèn)的字體為準(zhǔn)。
          p{font-family: Arial,"Microsoft Yahei", "微軟雅黑";}

          常用技巧:

          1. 各種字體之間必須使用英文狀態(tài)下的逗號隔開。
          2. 中文字體需要加英文狀態(tài)下的引號,英文字體一般不需要加引號。當(dāng)需要設(shè)置英文字體時,英文字體名必須位于中文字體名之前。
          3. 如果字體名中包含空格、#、$等符號,則該字體必須加英文狀態(tài)下的單引號或雙引號,例如font-family: "Times New Roman";。
          4. 盡量使用系統(tǒng)默認(rèn)字體,保證在任何用戶的瀏覽器中都能正確顯示。

          CSS Unicode字體

          • 為什么使用 Unicode字體在 CSS 中設(shè)置字體名稱,直接寫中文是可以的。但是在文件編碼(GB2312、UTF-8 等)不匹配時會產(chǎn)生亂碼的錯誤。xp 系統(tǒng)不支持 類似微軟雅黑的中文。
          • 解決:方案一: 你可以使用英文來替代。 比如font-family:"Microsoft Yahei"。方案二: 在 CSS 直接使用 Unicode 編碼來寫字體名稱可以避免這些錯誤。使用 Unicode 寫中文字體名稱,瀏覽器是可以正確的解析的。font-family: "FAEF6FC5ED1"; 表示設(shè)置字體為“微軟雅黑”。

          字體名稱

          英文名稱

          Unicode 編碼

          宋體

          SimSun

          B8BF53

          新宋體

          NSimSun

          B0B8BF53

          黑體

          SimHei

          ED1F53

          微軟雅黑

          Microsoft YaHei

          FAEF6FC5ED1

          楷體_GB2312

          KaiTi_GB2312

          77F53_GB2312

          隸書

          LiSu

          B6E66

          幼園

          YouYuan

          E7C06

          華文細(xì)黑

          STXihei

          4E87EC6ED1

          細(xì)明體

          MingLiU

          EC60EF53

          新細(xì)明體

          PMingLiU

          B0EC60EF53

          1.3 font-weight:字體粗細(xì)

          • 在html中如何將字體加粗我們可以用標(biāo)簽來實現(xiàn)使用 b 和 strong 標(biāo)簽是文本加粗。
          • 可以使用CSS 來實現(xiàn),但是CSS 是沒有語義的。

          屬性值

          描述

          normal

          默認(rèn)值(不加粗的)

          bold

          定義粗體(加粗的)

          100~900

          400 等同于 normal,而 700 等同于 bold 我們重點記住這句話

          提倡:

          我們平時更喜歡用數(shù)字來表示加粗和不加粗。

          1.4 font-style:字體風(fēng)格

          • 在html中如何將字體傾斜我們可以用標(biāo)簽來實現(xiàn)字體傾斜除了用 i 和 em 標(biāo)簽,
          • 可以使用CSS 來實現(xiàn),但是CSS 是沒有語義的

          font-style屬性用于定義字體風(fēng)格,如設(shè)置斜體、傾斜或正常字體,其可用屬性值如下:

          屬性

          作用

          normal

          默認(rèn)值,瀏覽器會顯示標(biāo)準(zhǔn)的字體樣式 font-style: normal;

          italic

          瀏覽器會顯示斜體的字體樣式。

          小技巧:

          平時我們很少給文字加斜體,反而喜歡給斜體標(biāo)簽(em,i)改為普通模式。

          1.5 font:綜合設(shè)置字體樣式 (重點)

          font屬性用于對字體樣式進(jìn)行綜合設(shè)置

          • 基本語法格式如下:
          選擇器 { font: font-style  font-weight  font-size/line-height  font-family;}
          • 注意:使用font屬性時,必須按上面語法格式中的順序書寫,不能更換順序,各個屬性以空格隔開。其中不需要設(shè)置的屬性可以省略(取默認(rèn)值),但必須保留font-size和font-family屬性,否則font屬性將不起作用。

          1.6 font總結(jié)

          屬性

          表示

          注意點

          font-size

          字號

          我們通常用的單位是px 像素,一定要跟上單位

          font-family

          字體

          實際工作中按照團(tuán)隊約定來寫字體

          font-weight

          字體粗細(xì)

          記住加粗是 700 或者 bold 不加粗 是 normal 或者 400 記住數(shù)字不要跟單位

          font-style

          字體樣式

          記住傾斜是 italic 不傾斜 是 normal 工作中我們最常用 normal

          font

          字體連寫

          1. 字體連寫是有順序的 不能隨意換位置 2. 其中字號 和 字體 必須同時出現(xiàn)

          2. CSS外觀屬性

          2.1 color:文本顏色

          • 作用:color屬性用于定義文本的顏色,
          • 其取值方式有如下3種:

          表示表示

          屬性值

          預(yù)定義的顏色值

          red,green,blue,還有我們的御用色 pink

          十六進(jìn)制

          #FF0000,#FF6600,#29D794

          RGB代碼

          rgb(255,0,0)或rgb(100%,0%,0%)

          • 注意我們實際工作中, 用 16進(jìn)制的寫法是最多的,而且我們更喜歡簡寫方式比如 #f00 代表紅色

          2.2 text-align:文本水平對齊方式

          • 作用:text-align屬性用于設(shè)置文本內(nèi)容的水平對齊,相當(dāng)于html中的align對齊屬性
          • 其可用屬性值如下:

          屬性

          解釋

          left

          左對齊(默認(rèn)值)

          right

          右對齊

          center

          居中對齊

          • 注意:是讓盒子里面的內(nèi)容水平居中, 而不是讓盒子居中對齊

          2.3 line-height:行間距

          • 作用:line-height屬性用于設(shè)置行間距,就是行與行之間的距離,即字符的垂直間距,一般稱為行高。
          • 單位:line-height常用的屬性值單位有三種,分別為像素px,相對值em和百分比%,實際工作中使用最多的是像素px
          • 技巧:
          一般情況下,行距比字號大7.8像素左右就可以了。
          line-height: 24px;

          2.4 text-indent:首行縮進(jìn)

          • 作用:text-indent屬性用于設(shè)置首行文本的縮進(jìn),
          • 屬性值其屬性值可為不同單位的數(shù)值、em字符寬度的倍數(shù)、或相對于瀏覽器窗口寬度的百分比%,允許使用負(fù)值,建議使用em作為設(shè)置單位。

          1em 就是一個字的寬度 如果是漢字的段落, 1em 就是一個漢字的寬度

          p {
                /*行間距*/
                line-height: 25px;
                /*首行縮進(jìn)2個字  em  1個em 就是1個字的大小*/
                text-indent: 2em;  
           }

          2.5 text-decoration 文本的裝飾

          text-decoration 通常我們用于給鏈接修改裝飾效果

          描述

          none

          默認(rèn)。定義標(biāo)準(zhǔn)的文本。 取消下劃線(最常用)

          underline

          定義文本下的一條線。下劃線 也是我們鏈接自帶的(常用)

          overline

          定義文本上的一條線。(不用)

          line-through

          定義穿過文本下的一條線。(不常用)

          2.6 CSS外觀屬性總結(jié)

          屬性

          表示

          注意點

          color

          顏色

          我們通常用 十六進(jìn)制 比如 而且是簡寫形式 #fff

          line-height

          行高

          控制行與行之間的距離

          text-align

          水平對齊

          可以設(shè)定文字水平的對齊方式

          text-indent

          首行縮進(jìn)

          通常我們用于段落首行縮進(jìn)2個字的距離 text-indent: 2em;

          text-decoration

          文本修飾

          記住 添加 下劃線 underline 取消下劃線 none

          3. sublime快捷操作emmet語法

          Emmet的前身是Zen coding,它使用縮寫,來提高h(yuǎn)tml/css的編寫速度。

          1. 生成標(biāo)簽 直接輸入標(biāo)簽名 按tab鍵即可 比如 div 然后tab 鍵, 就可以生成 <div></div>
          2. 如果想要生成多個相同標(biāo)簽 加上 * 就可以了 比如 div*3 就可以快速生成3個div
          3. 如果有父子級關(guān)系的標(biāo)簽,可以用 > 比如 ul > li就可以了
          4. 如果有兄弟關(guān)系的標(biāo)簽,用 + 就可以了 比如 div+p
          5. 如果生成帶有類名或者id名字的, 直接寫 .demo 或者 #two tab 鍵就可以了
          6. 如果生成的div 類名是有順序的, 可以用 自增符號 $ .demo$*3
            <div class="demo1"></div>
            <div class="demo2"></div>
            <div class="demo3"></div>

          4. 拓展閱讀@

          emment語法

          近每天都帶一個蘋果加餐,有次吃到一個十分漂亮的紅蘋果,突然覺得,可以試著畫一個蘋果看看。

          之前確實無法想象,可以使用CSS能畫出一個蘋果。


          先看效果:

          你沒有看錯,這個不是真蘋果。僅僅一百多行代碼就可以實現(xiàn)的CSS的紅蘋果。我自己看到最終效果都驚呆了。


          第一步畫出蘋果的輪廓:

          
          .apple {
            position: relative;
            width: 300px;
            height: 270px;
            background-color: #bf2934;
            border-radius: 160px 150px 145px 150px/160px 140px 210px 190px;
          }


          第二步:將蘋果變得更加立體

          1)右上角使用亮色內(nèi)陰影,畫出高光效果

          2)左下角使用兩層暗色內(nèi)陰影,畫出背光的暗色效果

          3)左上角增加一個亮色高光

          4)整體增加徑向漸變的背景,將重心高光,四周暗色

          
          .apple {
            position: relative;
            width: 300px;
            height: 270px;
            background: radial-gradient(#0000, rgba(0, 0, 0, .1)),
              radial-gradient(rgba(239, 156, 109, .2), #0000);
            background-color: #bf2934;
            border-radius: 160px 150px 145px 150px/160px 140px 210px 190px;
            box-shadow: inset 30px -20px 30px 20px rgba(0, 0, 0, .15),
              inset 10px -10px 15px 0 rgba(0, 0, 0, .15),
              inset 10px 10px 5px 0 rgba(255, 255, 255, .05),
              inset -10px 10px 30px 10px rgba(237, 115, 84, .3);
          }


          第三步:增加光源反光的高亮效果

          使用before偽元素,畫一個亮色的橢圓。橘色的陰影。然后整體模糊一下

          .apple::before {
            position: absolute;
            left: 135px;
            top: 50px;
            content: '';
            width: 80px;
            height: 30px;
            transform: skew(-20deg) rotate(10deg);
            border-radius: 45%;
            background: rgba(255, 255, 255, .65);
            box-shadow: 2px 10px 30px 22px rgba(239, 156, 109, 1);
            filter: blur(5px);
          }


          哇,一不小心,畫出來了一個西紅柿

          好吧,這個時候, 我其實可以停下來,先發(fā)一篇畫西紅柿的文章了。


          第四步:準(zhǔn)備一下頂部葉柄的凹陷

          這個凹陷效果使用after偽元素,畫一個黑色透明色漸變的橢圓,然后使用clip-path,截取頂部扇形部分。

          .apple::after {
            position: absolute;
            left: 90px;
            top: 2px;
            width: 120px;
            background: radial-gradient(rgba(0, 0, 0, .3), rgba(239, 156, 109, .2));
            height: 30px;
            content: '';
            border-radius: 50%;
            filter: blur(2px);
            clip-path: polygon(50% 55%, 150% 0, -50% 0);
            filter: blur(1px);
          }


          真是一個漂亮的西紅柿。。。。。。。


          蘋果和西紅柿的區(qū)別,主要是,蘋果沒有那么的光滑,顏色沒有這么完美。我們需要一些雜色。

          第五步:增加雜色條紋

          好吃的蘋果,都有縱向的條紋雜色。這里我們是模糊后的border來模擬。由于需要很多雜色,這里使用js添加,稍微做點隨機(jī)。

          
          .stripe {
            position: absolute;
            width: 300px;
            height: 270px;
            border-radius: 160px 150px 145px 150px/160px 140px 210px 190px;
            border-right: solid 2px rgba(239, 156, 109, .2);
            transform: scaleX(.9);
            filter: blur(4px);
          }
          function addStripe() {
            var fragment = document.createDocumentFragment()
            var count = 15
            for (var i = -count; i < count; i++) {
              var stripe = document.createElement('div')
              stripe.className = 'stripe'
              stripe.style.opacity = Math.max(1, 0.5 + Math.random())
              stripe.style.transform = `scaleX(${(i / count + Math.random() * 0.2).toFixed(2)})`
              fragment.appendChild(stripe)
            }
            document.querySelector('.apple').appendChild(fragment)
          }


          是不是突然就像蘋果了


          第六步:增加噪點

          好吃的蘋果,會有很多小小的斑點。這里,我們使用js增加一些隨機(jī)的斑點。

          .spot {
            position: absolute;
            width: 4px;
            height: 4px;
            border-radius: 50%;
            background: rgba(239, 156, 109, .6);
            filter: blur(1px);
          }
          function addSpot() {
            var count = 60
            var fragment = document.createDocumentFragment()
            for (var i = 0; i < count; i++) {
              var spot = document.createElement('div')
              spot.className = 'spot'
              spot.style.left = 5 + ~~(Math.random() * 90) + '%'
              spot.style.top = 5 + ~~(Math.random() * 90) + '%'
              spot.style.opacity = 0.2 + Math.random() * 0.4
              spot.style.transform = `scaleX(${Math.random() * 0.8 + 0.2}) scaleY(${Math.random() * 0.8 + 0.2}) rotate(${~~(360 * Math.random())}deg)`
              fragment.appendChild(spot)
            }
            document.querySelector('.apple').appendChild(fragment)
          }


          蘋果變得更加誘人了。


          再做一些細(xì)節(jié)優(yōu)化。

          第七部:給蘋果加個葉柄。

          買過西瓜的都知道,葉柄是證明西瓜新鮮與否的標(biāo)志。蘋果亦然。

          .petiole {
            position: absolute;
            transform: translate(155px, -48px) rotate(35deg);
            width: 20px;
            height: 60px;
            border-top: solid 15px transparent;
            border-left: solid 10px rgb(162, 76, 9);
            border-bottom: solid 8px transparent;
            border-radius: 50%;
          }
          .petiole.left {
            transform: translate(154px, -49px) rotate(35deg);
            border-left-color: rgb(123, 48, 24);
          }
          <div class="apple">
            <div class="petiole left"></div>
            <div class="petiole"></div>
          </div>


          是不是新鮮很多。


          最后,我們給蘋果加個陰影,看著更加立體一點。

          .shadow {
            position: absolute;
            width: 300px;
            height: 270px;
            background-color: rgba(0, 0, 0, .15);
            transform-origin: 50% 100%;
            transform: translate(5px, 5px) skew(60deg) scaleY(.25);
            border-radius: 160px 150px 145px 150px/160px 140px 210px 190px;
            box-shadow: 0 0 20px rgba(0, 0, 0, .15);
            filter: blur(4px);
          }


          嬌艷欲滴的大蘋果,完成!!!!


          代碼倉庫地址:

          https://github.com/shb190802/html5

          演示地址:

          http://suohb.com/demo/win/apple.html

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

          選自Floydhub

          作者:Emil Wallner

          機(jī)器之心編譯

          如何用前端頁面原型生成對應(yīng)的代碼一直是我們關(guān)注的問題,本文作者根據(jù) pix2code 等論文構(gòu)建了一個強(qiáng)大的前端代碼生成模型,并詳細(xì)解釋了如何利用 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 標(biāo)記語言

          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 完成。

          核心邏輯

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

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

          這里是一個簡單的訓(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ò)的輸入和輸出。

          我們先來看前面的標(biāo)記(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ù)測下一個標(biāo)記構(gòu)建知識。把訓(xùn)練好的模型應(yīng)用到真實世界中和模型訓(xùn)練過程差不多。

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

          Hello World 版

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

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

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

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

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

          #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 遇到幾個問題后,最終用上了強(qiáng)大的遠(yuǎn)程服務(wù)器。我預(yù)計租用 8 個現(xiàn)代 CPU 和 1 GPS 內(nèi)部鏈接以運(yùn)行我的工作流。
          • 在理解輸入與輸出數(shù)據(jù)之前,其它部分都似懂非懂。輸入 X 是屏幕的截圖和以前標(biāo)記的標(biāo)簽,輸出 Y 是下一個標(biāo)記的標(biāo)簽。當(dāng)我理解這一點時,其它問題都更加容易弄清了。此外,嘗試其它不同的架構(gòu)也將更加容易。
          • 圖片到代碼的網(wǎng)絡(luò)其實就是自動描述圖像的模型。即使我意識到了這一點,但仍然錯過了很多自動圖像摘要方面的論文,因為它們看起來不夠炫酷。一旦我意識到了這一點,我對問題空間的理解就變得更加深刻了。

          在 FloydHub 上運(yùn)行代碼

          FloydHub 是一個深度學(xué)習(xí)訓(xùn)練平臺,我自從開始學(xué)習(xí)深度學(xué)習(xí)時就對它有所了解,我也常用它訓(xùn)練和管理深度學(xué)習(xí)試驗。我們能安裝它并在 10 分鐘內(nèi)運(yùn)行第一個模型,它是在云 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 機(jī)器上運(yùn)行 Jupyter notebook:

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

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

          HTML 版本

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

          概覽

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

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

          設(shè)計原型的特征

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

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

          標(biāo)記特征

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

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

          編碼器

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

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

          標(biāo)記特征

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

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

          圖像特征

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

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

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

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

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

          解碼器

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

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

          最后的預(yù)測

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

          # 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…

          我走過的坑:

          • 我認(rèn)為理解 LSTM 比 CNN 要難一些。當(dāng)我展開 LSTM 后,它們會變得容易理解一些。此外,我們在嘗試?yán)斫?LSTM 前,可以先關(guān)注輸入與輸出特征。
          • 從頭構(gòu)建一個詞匯表要比壓縮一個巨大的詞匯表容易得多。這樣的構(gòu)建包括字體、div 標(biāo)簽大小、變量名的 hex 顏色和一般單詞。
          • 大多數(shù)庫是為解析文本文檔而構(gòu)建。在庫的使用文檔中,它們會告訴我們?nèi)绾瓮ㄟ^空格進(jìn)行分割,而不是代碼,我們需要自定義解析的方式。
          • 我們可以從 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ī)模。

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

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

          我們稍微修改一下 pix2code 論文中的模型,使之預(yù)測網(wǎng)絡(luò)組件的準(zhǔn)確率達(dá)到 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 單元追蹤標(biāo)簽行信息的可視化,它是我們用來訓(xùn)練 bootstrap 模型的簡單標(biāo)記語言。

          每一個 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ù)制代碼
          

          測試準(zhǔn)確率

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

          我使用的是 BLEU 分值,它在機(jī)器翻譯和圖像描述模型實踐上都是最好的。它把句子分解成 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…)

          我走過的坑:

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

          下一步

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

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

          實驗

          開始

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

          進(jìn)一步實驗

          • 使用相應(yīng)的語法創(chuàng)建一個穩(wěn)定的隨機(jī)應(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…

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


          主站蜘蛛池模板: 精品天海翼一区二区| 88国产精品视频一区二区三区| 久久国产高清一区二区三区| 亚洲综合无码一区二区| 高清在线一区二区| 中文字幕日韩欧美一区二区三区| 国产一区二区三区乱码| 一区二区三区精品高清视频免费在线播放| 精品无码日韩一区二区三区不卡| 国产综合无码一区二区三区| 国产人妖视频一区二区破除| 一区二区三区无码被窝影院| 久久精品一区二区东京热| 久久久无码精品国产一区| 变态拳头交视频一区二区| 国产激情一区二区三区成人91| 国产日韩精品一区二区在线观看播放 | 国产一区二区视频在线观看| 精品人妻一区二区三区四区| 无码av中文一区二区三区桃花岛 | 在线观看国产区亚洲一区成人| 日韩色视频一区二区三区亚洲| 亚洲熟妇成人精品一区| 亚洲综合av一区二区三区| 精品国产一区二区三区色欲| 精品视频无码一区二区三区| 无码人妻一区二区三区免费看| 久久精品一区二区三区日韩| 亚洲AV无码一区二区二三区软件| 在线视频一区二区三区三区不卡| 国产丝袜无码一区二区三区视频| 色老板在线视频一区二区| 激情内射日本一区二区三区| 日本高清不卡一区| 亚洲国产成人久久综合一区 | 呦系列视频一区二区三区| 五十路熟女人妻一区二区| 国产成人av一区二区三区不卡| 综合激情区视频一区视频二区| 精品国产一区二区三区在线观看| 精品久久一区二区|