整合營銷服務(wù)商

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

          免費咨詢熱線:

          「UI設(shè)計必備」隨機產(chǎn)生顏色或漸層色組合顯示CSS3

          「UI設(shè)計必備」隨機產(chǎn)生顏色或漸層色組合顯示CSS3代碼快速復(fù)制

          次要選擇顏色的時候,我總是會從眾多配色工具找一兩個自己喜歡的,無論從中尋找靈感或挑選合適的顏色都很好用,例如:Coolors快速選色器,后來改版后界面稍微有變得復(fù)雜一些;另外還有Colordot更人性化的選色工具服務(wù),在移動鼠標(biāo)搖標(biāo)時輕松找出配色靈感;我也喜歡NIPPON COLORS代表日本的250種顏色,這是找尋日本傳統(tǒng)色系配色的絕佳網(wǎng)站。

          越簡單的工具越深得我心,至少可快速解決問題而不用花太多時間摸索,本文要推薦的「ColorSpark」是一款非常易用的選色器,開啟網(wǎng)站按下「生成」按鈕,每次都會隨機出現(xiàn)一種顏色,同時也會顯示十六進(jìn)制顏色代碼可快速復(fù)制。

          除此之外,ColorSpark還提供漸層色(梯度)產(chǎn)生器,之前在WebGradients和CoolHue有介紹過收錄漸層背景免費下載的網(wǎng)站,現(xiàn)在你也可以在這項服務(wù)上隨機產(chǎn)生漸層色,一鍵快速復(fù)制CSS3語法,將它加入你的網(wǎng)站設(shè)計。

          站點名稱:ColorSpark

          網(wǎng)站連接:HTTPS://colorspark.app/

          使用教學(xué)

          步驟1

          開啟ColorSpark會隨機出現(xiàn)一個顏色,下方會有十六進(jìn)制色碼,點選「生成」重新產(chǎn)生一個顏色,每個顏色之間沒什么關(guān)連,可以多按幾次看看有沒有讓自己賞心悅目的顏色。

          STEP 2

          點選上方的「漸變」切換成漸層色模式,會顯示兩種顏色及偏移角度。

          點擊右下角的「復(fù)制CSS」可快速復(fù)制CSS3代碼,將它放進(jìn)CSS檔就能成為背景顏色使用。當(dāng)然還有其他使用方法,可以自己研究一下語法,總之ColorSpark主要用途就是讓使用者找到配色靈感。

          STEP 3

          此外,ColorSpark還提供夜間模式,從右上角點選月亮圖標(biāo)切換,夜間模式底色會變深色,但功能一樣沒變,蠻有趣的功能。

          依照ColorSpark說明表示這項服務(wù)是為了讓設(shè)計師找到獨特的顏色和漸層組合,通過這個可產(chǎn)生隨機顏色和漸變顏色的工具,可以找到一些原本不知道的顏色,這是一個有趣的實驗,或許可以為你的下一個設(shè)計項目激發(fā)出靈感。

          67運營推薦值得一試的三個理由:

          1、可隨機產(chǎn)生顏色或漸層色組合

          2、 一鍵復(fù)制十六進(jìn)制色碼或CSS3代碼

          3、 界面簡單易用,內(nèi)置夜間模式降低亮度

          約11000字,建議閱讀15+分鐘

          本文詳細(xì)對比了各種超參數(shù)對CNN模型性能的影響。


          針對CNN優(yōu)化的總結(jié)

          Systematic evaluation of CNN advances on the ImageNet

          使用沒有 batchnorm 的 ELU 非線性或者有 batchnorm 的 ReLU。


          用類似1*1的網(wǎng)絡(luò)結(jié)構(gòu)預(yù)訓(xùn)練RGB數(shù)據(jù),能得到更好的效果。


          使用線性學(xué)習(xí)率衰退策略。


          使用平均和最大池化層的和。


          使用大約 128(0.005) 到 256 (0.01)的 mini-batch 大小。如果這對你的 GPU 而言太大,將學(xué)習(xí)率按比例降到這個大小就行。


          使用卷積層代替之前的MLP中的線性層,并用平均池化層預(yù)測。


          當(dāng)研究增加訓(xùn)練集大小的時候,需要確定數(shù)據(jù)集對性能提升的平衡點。


          數(shù)據(jù)的質(zhì)量要比數(shù)據(jù)大小更重要。


          如果你不能增加輸入圖像的大小,在隨后的層上減少步幅(stride),這樣做有同樣的效果。


          如果你的網(wǎng)絡(luò)有復(fù)雜和高度優(yōu)化的架構(gòu),像是 GoogLeNet,那修改一定要謹(jǐn)慎。


          其他可以詳細(xì)看看論文,作者很辛苦的對比了各種超參數(shù)對CNN模型性能的影響,非常值得一看。


          下面轉(zhuǎn)自:

          https://nmarkou.blogspot.com.cy/2017/02/the-black-magic-of-deep-learning-tips.html



          有助于充分利用 DNN 的小技巧


          • 記得要 shuffle。不要讓你的網(wǎng)絡(luò)通過完全相同的 minibatch,如果框架允許,在每個 epoch 都 shuffle 一次。
          • 擴展數(shù)據(jù)集。DNN 需要大量的數(shù)據(jù),而且模型在小的數(shù)據(jù)集上很容易過擬合。我強烈建議你要擴展原始的數(shù)據(jù)集。如果你的是一個視覺任務(wù),可以增加噪點、增白,減少像素,旋轉(zhuǎn)或色移,模糊,等等可以擴展的一切。有一點不好的是,假如你擴展得太大,可能訓(xùn)練的數(shù)據(jù)大多數(shù)是相同的。我創(chuàng)建了一個應(yīng)用隨機變換的層來解決這個問題,這樣就不會有相同的樣本。若果你用的是語音數(shù)據(jù),可以進(jìn)行移位和失真處理。
          • 在整個數(shù)據(jù)集上訓(xùn)練之前,先在非常小的子數(shù)據(jù)集上訓(xùn)練進(jìn)行過擬合,這樣你會知道你的網(wǎng)絡(luò)可以收斂。這個 tip 來自 Karpathy。
          • 始終使用 dropout 將過擬合的幾率最小化。在大小 > 256 (完全連接層或卷積層)之后就應(yīng)該使用 dropout。關(guān)于這一點有一篇很好的論文:Dropout as a Bayesian Approximation: Representing Model Uncertainty in Deep Learning [Gal Yarin & Zoubin Ghahramani,2015].
          • 避免 LRN 池化,MAX 池化會更快。
          • 避免 Sigmoid/TanH 的門,它們代價昂貴,容易飽和,而且可能會停止反向傳播。實際上,你的網(wǎng)絡(luò)越深,就越應(yīng)該避免使用 Sigmoid 和 TanH。可以使用更便宜而且更有效的 ReLU 和 PreLU 的門,正如在 Yoshua Bengio 等人的論文 Deep Sparse Rectifier Neural Networks 中所提到的,這兩者能夠促進(jìn)稀疏性,而且它們的反向傳播更加魯棒。
          • 在最大池化之前不要使用 ReLU 或 PreLU ,而是在保存計算之后使用它。
          • 不要使用 ReLU ,它們太舊了。雖然他們是非常有用的非線性函數(shù),可以解決很多問題。但是,你可以試試用它微調(diào)一個新模型,由于 ReLU 阻礙反向傳播,初始化不好,你沒法得到任何微調(diào)效果。但是你應(yīng)該用 PreLU 以及一個非常小的乘數(shù),通常是0.1。使用 PreLU 的話收斂更快,而且不會像 ReLU 那樣在初始階段被卡住。ELU 也很好,但成本高。
          • 經(jīng)常使用批標(biāo)準(zhǔn)化。參考論文:Batch Normalization: Accelerating Deep Network Training by Reducing Internal Covariate Shift [Sergey Ioffe & Christian Szegedy,2015]。這會很有效。批標(biāo)準(zhǔn)化允許更快的收斂(非常快)以及更小的數(shù)據(jù)集。這樣你能夠節(jié)省時間和資源。
          • 雖然大多數(shù)人喜歡刪除平均值,不過我不喜歡。我喜歡壓縮輸入數(shù)據(jù)為[-1,+1]。這可以說是訓(xùn)練和部署方面的技巧,而不是針對提升性能的技巧。
          • 要能適用更小的模型。假如你是像我這樣部署深度學(xué)習(xí)模型,你很快就會體會到把千兆字節(jié)規(guī)模的模型推給用戶或地球另一端的服務(wù)器的痛苦。哪怕要犧牲一些準(zhǔn)確度,也應(yīng)該小型化。
          • 假如你使用比較小的模型,可以試試 ensemble。通常 ensemble 5個網(wǎng)絡(luò)能夠提升準(zhǔn)確度約3%。
          • 盡可能使用 xavier 初始化。你可以只在大的完全連接層上使用它,然后避免在 CNN 層上使用。有關(guān)這點的解釋可以閱讀這篇文章:An Explanation of Xavier Initialization(by Andy Jones)
          • 如果你的輸入數(shù)據(jù)有空間參數(shù),可以試試端到端的 CNN。可以閱讀這篇論文:SqueezeNet: AlexNet-level accuracy with 50x fewer parameters and <0.5MB model size [Forrest N. Iandola et. al. 2016],它介紹了一種新的方法,而且性能非常好,你可以嘗試應(yīng)用上面提到的tips。
          • 修改你的模型,只要可能就使用 1x1 的 CNN 層,它的位置對提高性能很有幫助。
          • 假如沒有高端的 GPU,就不要嘗試訓(xùn)練任何東西了。
          • 假如你要利用模型或你自己的層來制作模板,記得把所有東西參數(shù)化,否則你得重建所有二進(jìn)制文件。
          • 最后,要明白你在做什么。深度學(xué)習(xí)就像是機器學(xué)習(xí)里的中子彈,它不是任何任務(wù)、任何時候都有效的。了解你正在使用的結(jié)構(gòu)以及你試圖達(dá)成的目的,才不至于盲目地復(fù)制模型。


          提升算法性能思路


          這個列表里提到的思路并完全,但是一個好的開始。


          我的目的是給出很多可以嘗試的思路,希望其中的一或兩個你之前沒有想到。你經(jīng)常只需要一個好的想法就能得到性能提升。


          如果你能從其中一個思路中得到結(jié)果,請在評論區(qū)告訴我。我很高興能得知這些好消息。


          如果你有更多的想法,或者是所列思路的拓展,也請告訴我,我和其他讀者都將受益!


          有時候僅僅是一個想法或許就能使他人得到突破。


          我將此博文分為四個部分:


          1. 通過數(shù)據(jù)提升性能

          2. 通過算法提升性能

          3. 通過算法調(diào)參提升性能

          4. 通過嵌套模型提升性能


          通常來講,隨著列表自上而下,性能的提升也將變小。例如,對問題進(jìn)行新的架構(gòu)或者獲取更多的數(shù)據(jù),通常比調(diào)整最優(yōu)算法的參數(shù)能帶來更好的效果。雖然并不總是這樣,但是通常來講是的。


          我已經(jīng)把相應(yīng)的鏈接加入了博客的教程中,相應(yīng)網(wǎng)站的問題中,以及經(jīng)典的Neural Net FAQ中。


          部分思路只適用于人工神經(jīng)網(wǎng)絡(luò),但是大部分是通用的。通用到足夠你用來配合其他技術(shù)來碰撞出提升模型性能的方法。


          OK,現(xiàn)在讓我們開始吧。


          1. 通過數(shù)據(jù)提升性能


          對你的訓(xùn)練數(shù)據(jù)和問題定義進(jìn)行適當(dāng)改變,你能得到很大的性能提升。或許是最大的性能提升。


          以下是我將要提到的思路:

          1. 獲取更多數(shù)據(jù)
          2. 創(chuàng)造更多數(shù)據(jù)
          3. 重放縮你的數(shù)據(jù)
          4. 轉(zhuǎn)換你的數(shù)據(jù)
          5. 特征選取
          6. 重架構(gòu)你的問題


          1) 獲取更多數(shù)據(jù)

          你能獲取更多訓(xùn)練數(shù)據(jù)嗎?


          你的模型的質(zhì)量通常受到你的訓(xùn)練數(shù)據(jù)質(zhì)量的限制。為了得到最好的模型,你首先應(yīng)該想辦法獲得最好的數(shù)據(jù)。你也想盡可能多的獲得那些最好的數(shù)據(jù)。


          有更多的數(shù)據(jù),深度學(xué)習(xí)和其他現(xiàn)代的非線性機器學(xué)習(xí)技術(shù)有更全的學(xué)習(xí)源,能學(xué)得更好,深度學(xué)習(xí)尤為如此。這也是機器學(xué)習(xí)對大家充滿吸引力的很大一個原因(世界到處都是數(shù)據(jù))。

          更多的數(shù)據(jù)并不是總是有用,但是確實有幫助。于我而言,如果可以,我會選擇獲取更多的數(shù)據(jù)。


          可以參見以下相關(guān)閱讀:


          Datasets Over Algorithms

          (www.edge.org/response-detail/26587)


          2) 創(chuàng)造更多數(shù)據(jù)


          上一小節(jié)說到了有了更多數(shù)據(jù),深度學(xué)習(xí)算法通常會變的更好。有些時候你可能無法合理地獲取更多數(shù)據(jù),那你可以試試創(chuàng)造更多數(shù)據(jù)。


          • 如果你的數(shù)據(jù)是數(shù)值型向量,可以隨機構(gòu)造已有向量的修改版本。
          • 如果你的數(shù)據(jù)是圖片,可以隨機構(gòu)造已有圖片的修改版本(平移、截取、旋轉(zhuǎn)等)。
          • 如果你的數(shù)據(jù)是文本,類似的操作……


          這通常被稱作數(shù)據(jù)擴增(data augmentation)或者數(shù)據(jù)生成(data generation)。

          你可以利用一個生成模型。你也可以用一些簡單的技巧。例如,針對圖片數(shù)據(jù),你可以通過隨機地平移或旋轉(zhuǎn)已有圖片獲取性能的提升。如果新數(shù)據(jù)中包含了這種轉(zhuǎn)換,則提升了模型的泛化能力。


          這也與增加噪聲是相關(guān)的,我們習(xí)慣稱之為增加擾動。它起到了與正則化方法類似的作用,即抑制訓(xùn)練數(shù)據(jù)的過擬合。


          以下是相關(guān)閱讀:


          • Image Augmentation for Deep Learning With Keras
          • http://machinelearningmastery.com/image-augmentation-deep-learning-keras/

          • What is jitter? (Training with noise)
          • ftp://ftp.sas.com/pub/neural/FAQ3.html#A_jitter


          3) 重縮放(rescale)你的數(shù)據(jù)


          這是一個快速獲得性能提升的方法。


          當(dāng)應(yīng)用神經(jīng)網(wǎng)絡(luò)時,一個傳統(tǒng)的經(jīng)驗法則是:重縮放(rescale)你的數(shù)據(jù)至激活函數(shù)的邊界。


          如果你在使用sigmoid激活函數(shù),重縮放你的數(shù)據(jù)到0和1的區(qū)間里。如果你在使用雙曲正切(tanh)激活函數(shù),重縮放數(shù)據(jù)到-1和1的區(qū)間里。


          這種方法可以被應(yīng)用到輸入數(shù)據(jù)(x)和輸出數(shù)據(jù)(y)。例如,如果你在輸出層使用sigmoid函數(shù)去預(yù)測二元分類的結(jié)果,應(yīng)當(dāng)標(biāo)準(zhǔn)化y值,使之成為二元的。如果你在使用softmax函數(shù),你依舊可以通過標(biāo)準(zhǔn)化y值來獲益。


          這依舊是一個好的經(jīng)驗法則,但是我想更深入一點。我建議你可以參考下述方法來創(chuàng)造一些訓(xùn)練數(shù)據(jù)的不同的版本:


          • 歸一化到0和1的區(qū)間。
          • 重放縮到-1和1的區(qū)間
          • 標(biāo)準(zhǔn)化(譯者注:標(biāo)準(zhǔn)化數(shù)據(jù)使之成為零均值,單位標(biāo)準(zhǔn)差)


          然后對每一種方法,評估你的模型的性能,選取最好的進(jìn)行使用。如果你改變了你的激活函數(shù),重復(fù)這一過程。


          在神經(jīng)網(wǎng)絡(luò)中,大的數(shù)值累積效應(yīng)(疊加疊乘)并不是好事,除上述方法之外,還有其他的方法來控制你的神經(jīng)網(wǎng)絡(luò)中數(shù)據(jù)的數(shù)值大小,譬如歸一化激活函數(shù)和權(quán)重,我們會在以后討論這些技術(shù)。


          以下為相關(guān)閱讀:


          • Should I standardize the input variables (column vectors)?
          • ftp://ftp.sas.com/pub/neural/FAQ2.html#A_std
          • How To Prepare Your Data For Machine Learning in Python with Scikit-Learn
          • http://machinelearningmastery.com/prepare-data-machine-learning-python-scikit-learn/


          4) 數(shù)據(jù)變換


          這里的數(shù)據(jù)變換與上述的重縮放方法類似,但需要更多工作。


          你必須非常熟悉你的數(shù)據(jù)。通過可視化來考察離群點。


          猜測每一列數(shù)據(jù)的單變量分布。


          • 列數(shù)據(jù)看起來像偏斜的高斯分布嗎?考慮用Box-Cox變換調(diào)整偏態(tài)。
          • 列數(shù)據(jù)看起來像指數(shù)分布嗎?考慮用對數(shù)變換。
          • 列數(shù)據(jù)看起來有一些特征,但是它們被一些明顯的東西遮蓋了,嘗試取平方或者開平方根來轉(zhuǎn)換數(shù)據(jù)
          • 你能離散化一個特征或者以某種方式組合特征,來更好地突出一些特征嗎?


          依靠你的直覺,嘗試以下方法。


          • 你能利用類似PCA的投影方法來預(yù)處理數(shù)據(jù)嗎?
          • 你能綜合多維特征至一個單一數(shù)值(特征)嗎?
          • 你能用一個新的布爾標(biāo)簽去發(fā)現(xiàn)問題中存在一些有趣的方面嗎?
          • 你能用其他方法探索出目前場景下的其他特殊結(jié)構(gòu)嗎?


          神經(jīng)網(wǎng)層擅長特征學(xué)習(xí)(feature engineering)。它(自己)可以做到這件事。但是如果你能更好的發(fā)現(xiàn)問題到網(wǎng)絡(luò)中的結(jié)構(gòu),神經(jīng)網(wǎng)層會學(xué)習(xí)地更快。你可以對你的數(shù)據(jù)就不同的轉(zhuǎn)換方式進(jìn)行抽樣調(diào)查,或者嘗試特定的性質(zhì),來看哪些有用,哪些沒用。


          以下是相關(guān)閱讀:


          • How to Define Your Machine Learning Problem
          • http://machinelearningmastery.com/how-to-define-your-machine-learning-problem/
          • Discover Feature Engineering, How to Engineer Features and How to Get Good at It
          • http://machinelearningmastery.com/discover-feature-engineering-how-to-engineer-features-and-how-to-get-good-at-it/
          • How To Prepare Your Data For Machine Learning in Python with Scikit-Learn
          • http://machinelearningmastery.com/prepare-data-machine-learning-python-scikit-learn/


          5) 特征選擇


          一般說來,神經(jīng)網(wǎng)絡(luò)對不相關(guān)的特征是具有魯棒的(校對注:即不相關(guān)的特征不會很大影響神經(jīng)網(wǎng)絡(luò)的訓(xùn)練和效果)。它們會用近似于0的權(quán)重來弱化那些沒有預(yù)測能力的特征的貢獻(xiàn)。


          盡管如此,這些無關(guān)的數(shù)據(jù)特征,在訓(xùn)練周期依舊要耗費大量的資源。所以你能去除數(shù)據(jù)里的一些特征嗎?


          有許多特征選擇的方法和特征重要性的方法,這些方法能夠給你提供思路,哪些特征該保留,哪些特征該剔除。最簡單的方式就是對比所有特征和部分特征的效果。


          同樣的,如果你有時間,我建議在同一個網(wǎng)絡(luò)中嘗試選擇不同的視角來看待你的問題,評估它們,來看看分別有怎樣的性能。


          • 或許你利用更少的特征就能達(dá)到同等甚至更好的性能。而且,這將使模型變得更快!
          • 或許所有的特征選擇方法都剔除了同樣的特征子集。很好,這些方法在沒用的特征上達(dá)成了一致。
          • 或許篩選過后的特征子集,能帶給特征工程的新思路。


          以下是相關(guān)閱讀:


          • An Introduction to Feature Selection
          • http://machinelearningmastery.com/an-introduction-to-feature-selection/
          • Feature Selection For Machine Learning in Python
          • http://machinelearningmastery.com/feature-selection-machine-learning-python/


          6) 重新架構(gòu)你的問題


          有時候要試試從你當(dāng)前定義的問題中跳出來,想想你所收集到的觀察值是定義你問題的唯一方式嗎?或許存在其他方法。或許其他構(gòu)建問題的方式能夠更好地揭示待學(xué)習(xí)問題的結(jié)構(gòu)。


          我真的很喜歡這個嘗試,因為它迫使你打開自己的思路。這確實很難,尤其是當(dāng)你已經(jīng)對當(dāng)前的方法投入了大量的時間和金錢時。


          但是咱們這么想想,即使你列出了3-5個可供替代的建構(gòu)方案,而且最終還是放棄了它們,但這至少說明你對當(dāng)前的方案更加自信了。


          • 看看能夠在一個時間窗(時間周期)內(nèi)對已有的特征/數(shù)據(jù)做一個合并。
          • 或許你的分類問題可以成為一個回歸問題(有時候是回歸到分類)。
          • 或許你的二元輸出可以變成softmax輸出?
          • 或許你可以轉(zhuǎn)而對子問題進(jìn)行建模。


          仔細(xì)思考你的問題,最好在你選定工具之前就考慮用不同方法構(gòu)建你的問題,因為此時你對解決方案并沒有花費太多的投入。除此之外,如果你在某個問題上卡住了,這樣一個簡單的嘗試能釋放更多新的想法。


          而且,這并不代表你之前的工作白干了,關(guān)于這點你可以看看后續(xù)的模型嵌套部分。


          以下為相關(guān)閱讀:


          • How to Define Your Machine Learning Problem
          • http://machinelearningmastery.com/how-to-define-your-machine-learning-problem/


          通過算法提升性能


          機器學(xué)習(xí)當(dāng)然是用算法解決問題。


          所有的理論和數(shù)學(xué)都是描繪了應(yīng)用不同的方法從數(shù)據(jù)中學(xué)習(xí)一個決策過程(如果我們這里只討論預(yù)測模型)。


          你已經(jīng)選擇了深度學(xué)習(xí)來解釋你的問題。但是這真的是最好的選擇嗎?在這一節(jié)中,我們會在深入到如何最大地發(fā)掘你所選擇的深度學(xué)習(xí)方法之前,接觸一些算法選擇上的思路。


          下面是一個簡要列表:


          1. 對算法進(jìn)行抽樣調(diào)查
          2. 借鑒已有文獻(xiàn)
          3. 重采樣方法


          下面我解釋下上面提到的幾個方法。


          1) 對算法進(jìn)行抽樣調(diào)查

          其實你事先無法知道,針對你的問題哪個算法是最優(yōu)的。如果你知道,你可能就不需要機器學(xué)習(xí)了。那有沒有什么數(shù)據(jù)(辦法)可以證明你選擇的方法是正確的?


          讓我們來解決這個難題。當(dāng)從所有可能的問題中平均來看各算法的性能時,沒有哪個算法能夠永遠(yuǎn)勝過其他算法。所有的算法都是平等的,下面是在no free lunch theorem中的一個總結(jié)。


          或許你選擇的算法不是針對你的問題最優(yōu)的那個


          我們不是在嘗試解決所有問題,算法世界中有很多新熱的方法,可是它們可能并不是針對你數(shù)據(jù)集的最優(yōu)算法。


          我的建議是收集(證據(jù))數(shù)據(jù)指標(biāo)。接受更好的算法或許存在這一觀點,并且給予其他算法在解決你的問題上“公平競爭”的機會。


          抽樣調(diào)查一系列可行的方法,來看看哪些還不錯,哪些不理想。


          • 首先嘗試評估一些線性方法,例如邏輯回歸(logistic regression)和線性判別分析(linear discriminate analysis)。
          • 評估一些樹類模型,例如CART, 隨機森林(Random Forest)和Gradient Boosting。
          • 評估一些實例方法,例如支持向量機(SVM)和K-近鄰(kNN)。
          • 評估一些其他的神經(jīng)網(wǎng)絡(luò)方法,例如LVQ, MLP, CNN, LSTM, hybrids等


          選取性能最好的算法,然后通過進(jìn)一步的調(diào)參和數(shù)據(jù)準(zhǔn)備來提升。尤其注意對比一下深度學(xué)習(xí)和其他常規(guī)機器學(xué)習(xí)方法,對上述結(jié)果進(jìn)行排名,比較他們的優(yōu)劣。


          很多時候你會發(fā)現(xiàn)在你的問題上可以不用深度學(xué)習(xí),而是使用一些更簡單,訓(xùn)練速度更快,甚至是更容易理解的算法。


          以下為相關(guān)閱讀:


          • A Data-Driven Approach to Machine Learning
          • http://machinelearningmastery.com/a-data-driven-approach-to-machine-learning/
          • Why you should be Spot-Checking Algorithms on your Machine Learning Problems
          • http://machinelearningmastery.com/why-you-should-be-spot-checking-algorithms-on-your-machine-learning-problems/
          • Spot-Check Classification Machine Learning Algorithms in Python with scikit-learn
          • http://machinelearningmastery.com/spot-check-classification-machine-learning-algorithms-python-scikit-learn/


          2) 借鑒已有文獻(xiàn)


          方法選擇的一個捷徑是借鑒已有的文獻(xiàn)資料。可能有人已經(jīng)研究過與你的問題相關(guān)的問題,你可以看看他們用的什么方法。


          你可以閱讀論文,書籍,博客,問答網(wǎng)站,教程,以及任何能在谷歌搜索到的東西。


          寫下所有的想法,然后用你的方式把他們研究一遍。


          這不是復(fù)制別人的研究,而是啟發(fā)你想出新的想法,一些你從沒想到但是卻有可能帶來性能提升的想法。


          發(fā)表的研究通常都是非常贊的。世界上有非常多聰明的人,寫了很多有趣的東西。你應(yīng)當(dāng)好好挖掘這個“圖書館”,找到你想要的東西。


          以下為相關(guān)閱讀:


          • How to Research a Machine Learning Algorithm
          • http://machinelearningmastery.com/how-to-research-a-machine-learning-algorithm/
          • Google Scholar
          • http://scholar.google.com/


          3) 重采樣方法


          你必須知道你的模型效果如何。你對模型性能的估計可靠嗎?


          深度學(xué)習(xí)模型在訓(xùn)練階段非常緩慢。這通常意味著,我們無法用一些常用的方法,例如k層交叉驗證,去估計模型的性能。


          • 或許你在使用一個簡單的訓(xùn)練集/測試集分割,這是常規(guī)套路。如果是這樣,你需要確保這種分割針對你的問題具有代表性。單變量統(tǒng)計和可視化是一個好的開始。
          • 或許你能利用硬件來加速估計的過程。例如,如果你有集群或者AWS云端服務(wù)(Amazon Web Services)賬號,你可以并行地訓(xùn)練n個模型,然后獲取結(jié)果的均值和標(biāo)準(zhǔn)差來得到更魯棒的估計。
          • 或許你可以利用hold-out驗證方法來了解模型在訓(xùn)練后的性能(這在早停法(early stopping)中很有用,后面會講到)。
          • 或許你可以先隱藏一個完全沒用過的驗證集,等到你已經(jīng)完成模型選擇之后再使用它。


          而有時候另外的方式,或許你能夠讓數(shù)據(jù)集變得更小,以及使用更強的重采樣方法。


          • 有些情況下你會發(fā)現(xiàn)在訓(xùn)練集的一部分樣本上訓(xùn)練得到的模型的性能,和在整個數(shù)據(jù)集上訓(xùn)練得到的模型的性能有很強的相關(guān)性。也許你可以先在小數(shù)據(jù)集上完成模型選擇和參數(shù)調(diào)優(yōu),然后再將最終的方法擴展到全部數(shù)據(jù)集上。
          • 或許你可以用某些方式限制數(shù)據(jù)集,只取一部分樣本,然后用它進(jìn)行全部的建模過程。


          以下為相關(guān)閱讀:


          • Evaluate the Performance Of Deep Learning Models in Keras
          • http://machinelearningmastery.com/evaluate-performance-deep-learning-models-keras/
          • Evaluate the Performance of Machine Learning Algorithms in Python using Resampling
          • http://machinelearningmastery.com/evaluate-performance-machine-learning-algorithms-python-using-resampling/


          通過算法調(diào)參提升性能


          這通常是工作的關(guān)鍵所在。你經(jīng)常可以通過抽樣調(diào)查快速地發(fā)現(xiàn)一個或兩個性能優(yōu)秀的算法。但是如果想得到最優(yōu)的算法可能需要幾天,幾周,甚至幾個月。


          為了獲得更優(yōu)的模型,以下是對神經(jīng)網(wǎng)絡(luò)算法進(jìn)行參數(shù)調(diào)優(yōu)的幾點思路:


          1. 診斷(Diagnostics)
          2. 權(quán)重初始化(Weight Initialization)
          3. 學(xué)習(xí)速率(Learning Rate)
          4. 激活函數(shù)
          5. 網(wǎng)絡(luò)拓?fù)洌∟etwork Topology)
          6. 批次和周期(Batches and Epochs)
          7. 正則化
          8. 優(yōu)化和損失
          9. 早停法


          你可能需要訓(xùn)練一個給定“參數(shù)配置”的神經(jīng)網(wǎng)絡(luò)模型很多次(3-10次甚至更多),才能得到一個估計性能不錯的參數(shù)配置。這一點幾乎適用于這一節(jié)中你能夠調(diào)參的所有方面。


          關(guān)于超參數(shù)優(yōu)化請參閱博文:


          • How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras
          • http://machinelearningmastery.com/grid-search-hyperparameters-deep-learning-models-python-keras/


          1) 診斷


          如果你能知道為什么你的模型性能不再提高了,你就能獲得擁有更好性能的模型。


          你的模型是過擬合還是欠擬合?永遠(yuǎn)牢記這個問題。永遠(yuǎn)。


          模型總是會遇到過擬合或者欠擬合,只是程度不同罷了。一個快速了解模型學(xué)習(xí)行為的方法是,在每個周期,評估模型在訓(xùn)練集和驗證集上的表現(xiàn),并作出圖表。


          • 如果訓(xùn)練集上的模型總是優(yōu)于驗證集上的模型,你可能遇到了過擬合,你可以使用諸如正則化的方法。
          • 如果訓(xùn)練集和驗證集上的模型都很差,你可能遇到了欠擬合,你可以提升網(wǎng)絡(luò)的容量,以及訓(xùn)練更多或者更久。
          • 如果有一個拐點存在,在那之后訓(xùn)練集上的模型開始優(yōu)于驗證集上的模型,你可能需要使用早停法。


          經(jīng)常畫一畫這些圖表,學(xué)習(xí)它們來了解不同的方法,你能夠提升模型的性能。這些圖表可能是你能創(chuàng)造的最有價值的(模型狀態(tài))診斷信息。


          另一個有用的診斷是網(wǎng)絡(luò)模型判定對和判定錯的觀察值。


          • 對于難以訓(xùn)練的樣本,或許你需要更多的數(shù)據(jù)。
          • 或許你應(yīng)該剔除訓(xùn)練集中易于建模的多余的樣本。
          • 也許可以嘗試對訓(xùn)練集劃分不同的區(qū)域,在特定區(qū)域中用更專長的模型。


          以下為相關(guān)閱讀:


          • Display Deep Learning Model Training History in Keras
          • http://machinelearningmastery.com/display-deep-learning-model-training-history-in-keras/
          • Overfitting and Underfitting With Machine Learning Algorithms
          • http://machinelearningmastery.com/overfitting-and-underfitting-with-machine-learning-algorithms/


          2) 權(quán)重初始化


          經(jīng)驗法則通常是:用小的隨機數(shù)進(jìn)行初始化。


          在實踐中,這可能依舊效果不錯,但是對于你的網(wǎng)絡(luò)來說是最佳的嗎?對于不同的激活函數(shù)也有一些啟發(fā)式的初始化方法,但是在實踐應(yīng)用中并沒有太多不同。


          固定你的網(wǎng)絡(luò),然后嘗試多種初始化方式。


          記住,權(quán)重是你的模型真正的參數(shù),你需要找到他們。有很多組權(quán)重都能有不錯的性能表現(xiàn),但我們要盡量找到最好的。


          • 嘗試所有不同的初始化方法,考察是否有一種方法在其他情況不變的情況下(效果)更優(yōu)。
          • 嘗試用無監(jiān)督的方法,例如自動編碼(autoencoder),來進(jìn)行預(yù)先學(xué)習(xí)。
          • 嘗試使用一個已經(jīng)存在的模型,只是針對你的問題重新訓(xùn)練輸入層和輸出層(遷移學(xué)習(xí)(transfer learning))


          需要提醒的一點是,改變權(quán)重初始化方法和激活函數(shù),甚至優(yōu)化函數(shù)/損失函數(shù)緊密相關(guān)。


          以下為相關(guān)閱讀:


          • Initialization of deep networks
          • http://deepdish.io/2015/02/24/network-initialization/


          3) 學(xué)習(xí)率


          調(diào)整學(xué)習(xí)率很多時候也是行之有效的時段。


          以下是可供探索的一些想法:


          • 實驗很大和很小的學(xué)習(xí)率
          • 格點搜索文獻(xiàn)里常見的學(xué)習(xí)速率值,考察你能學(xué)習(xí)多深的網(wǎng)絡(luò)。
          • 嘗試隨周期遞減的學(xué)習(xí)率
          • 嘗試經(jīng)過固定周期數(shù)后按比例減小的學(xué)習(xí)率。
          • 嘗試增加一個動量項(momentum term),然后對學(xué)習(xí)速率和動量同時進(jìn)行格點搜索。


          越大的網(wǎng)絡(luò)需要越多的訓(xùn)練,反之亦然。如果你添加了太多的神經(jīng)元和層數(shù),適當(dāng)提升你的學(xué)習(xí)速率。同時學(xué)習(xí)率需要和訓(xùn)練周期,batch size大小以及優(yōu)化方法聯(lián)系在一起考慮。


          以下為相關(guān)閱讀:


          • Using Learning Rate Schedules for Deep Learning Models in Python with Keras
          • http://machinelearningmastery.com/using-learning-rate-schedules-deep-learning-models-python-keras/
          • What learning rate should be used for backprop?
          • ftp://ftp.sas.com/pub/neural/FAQ2.html#A_learn_rate





          4) 激活函數(shù)


          你或許應(yīng)該使用修正激活函數(shù)(rectifier activation functions)。他們也許能提供更好的性能。


          在這之前,最早的激活函數(shù)是sigmoid和tanh,之后是softmax, 線性激活函數(shù),或者輸出層上的sigmoid函數(shù)。我不建議嘗試更多的激活函數(shù),除非你知道你自己在干什么。


          嘗試全部三種激活函數(shù),并且重縮放你的數(shù)據(jù)以滿足激活函數(shù)的邊界。


          顯然,你想要為輸出的形式選擇正確的傳遞函數(shù),但是可以考慮一下探索不同表示。例如,把在二元分類問題上使用的sigmoid函數(shù)切換到回歸問題上使用的線性函數(shù),然后后置處理你的輸出。這可能需要改變損失函數(shù)使之更合適。詳情參閱數(shù)據(jù)轉(zhuǎn)換那一節(jié)。


          以下為相關(guān)閱讀:


          • Why use activation functions?
          • ftp://ftp.sas.com/pub/neural/FAQ2.html#A_act


          5) 網(wǎng)絡(luò)拓?fù)?/h1>


          網(wǎng)絡(luò)結(jié)構(gòu)的改變能帶來好處。


          你需要多少層以及多少個神經(jīng)元?抱歉沒有人知道。不要問這種問題…


          那怎么找到適用你的問題的配置呢?去實驗吧。


          • 嘗試一個隱藏層和許多神經(jīng)元(廣度模型)。
          • 嘗試一個深的網(wǎng)絡(luò),但是每層只有很少的神經(jīng)元(深度模型)。
          • 嘗試上述兩種方法的組合。
          • 借鑒研究問題與你的類似的論文里面的結(jié)構(gòu)。
          • 嘗試拓?fù)淠J剑ㄉ瘸觯╢an out)然后扇入(fan in))和書籍論文里的經(jīng)驗法則(下有鏈接)


          選擇總是很困難的。通常說來越大的網(wǎng)絡(luò)有越強的代表能力,或許你需要它。越多的層數(shù)可以提供更強的從數(shù)據(jù)中學(xué)到的抽象特征的能力。或許需要它。


          深層的神經(jīng)網(wǎng)絡(luò)需要更多的訓(xùn)練,無論是訓(xùn)練周期還是學(xué)習(xí)率,都應(yīng)該相應(yīng)地進(jìn)行調(diào)整。


          以下為相關(guān)閱讀:


          這些鏈接會給你很多啟發(fā)該嘗試哪些事情,至少對我來說是的。


          • How many hidden layers should I use?
          • ftp://ftp.sas.com/pub/neural/FAQ3.html#A_hl
          • How many hidden units should I use?
          • ftp://ftp.sas.com/pub/neural/FAQ3.html#A_hu


          6) Batches和周期


          batch size大小會決定最后的梯度,以及更新權(quán)重的頻度。一個周期(epoch)指的是神經(jīng)網(wǎng)絡(luò)看一遍全部訓(xùn)練數(shù)據(jù)的過程。


          你是否已經(jīng)試驗了不同的批次batch size和周期數(shù)?


          之前,我們已經(jīng)討論了學(xué)習(xí)率,網(wǎng)絡(luò)大小和周期之間的關(guān)系。


          在很深的網(wǎng)絡(luò)結(jié)構(gòu)里你會經(jīng)常看到:小的batch size配以大的訓(xùn)練周期。


          下面這些或許能有助于你的問題,也或許不能。你要在自己的數(shù)據(jù)上嘗試和觀察。


          • 嘗試選取與訓(xùn)練數(shù)據(jù)同大小的batch size,但注意一下內(nèi)存(批次學(xué)習(xí)(batch learning))
          • 嘗試選取1作為batch size(在線學(xué)習(xí)(online learning))
          • 嘗試用格點搜索不同的小的batch size(8,16,32,…)
          • 分別嘗試訓(xùn)練少量周期和大量周期。


          考慮一個接近無窮的周期值(持續(xù)訓(xùn)練),去記錄到目前為止能得到的最佳的模型。


          一些網(wǎng)絡(luò)結(jié)構(gòu)對batch size更敏感。我知道多層感知器(Multilayer Perceptrons)通常對batch size是魯棒的,而LSTM和CNNs比較敏感,但是這只是一個說法(僅供參考)。


          以下為相關(guān)閱讀:


          • What are batch, incremental, on-line … learning?
          • ftp://ftp.sas.com/pub/neural/FAQ2.html#A_styles
          • Intuitively, how does mini-batch size affect the performance of (stochastic) gradient descent?
          • https://www.quora.com/Intuitively-how-does-mini-batch-size-affect-the-performance-of-stochastic-gradient-descent


          7) 正則化


          正則化是一個避免模型在訓(xùn)練集上過擬合的好方法。


          神經(jīng)網(wǎng)絡(luò)里最新最熱的正則化技術(shù)是dropout方法,你是否試過?dropout方法在訓(xùn)練階段隨機地跳過一些神經(jīng)元,驅(qū)動這一層其他的神經(jīng)元去捕捉松弛。簡單而有效。你可以從dropout方法開始。


          • 格點搜索不同的丟失比例。
          • 分別在輸入,隱藏層和輸出層中試驗dropout方法
          • dropout方法也有一些拓展,比如你也可以嘗試drop connect方法。


          也可以嘗試其他更傳統(tǒng)的神經(jīng)網(wǎng)絡(luò)正則化方法,例如:


          • 權(quán)重衰減(Weight decay)去懲罰大的權(quán)重
          • 激活約束(Activation constraint)去懲罰大的激活值


          你也可以試驗懲罰不同的方面,或者使用不同種類的懲罰/正則化(L1, L2, 或者二者同時)


          以下是相關(guān)閱讀:


          • Dropout Regularization in Deep Learning Models With Keras
          • http://machinelearningmastery.com/dropout-regularization-deep-learning-models-keras/
          • What is Weight Decay?
          • ftp://ftp.sas.com/pub/neural/FAQ3.html#A_decay


          8) 優(yōu)化和損失


          最常見是應(yīng)用隨機梯度下降法(stochastic gradient descent),但是現(xiàn)在有非常多的優(yōu)化器。你試驗過不同的優(yōu)化(方法)過程嗎?


          隨機梯度下降法是默認(rèn)的選擇。先好好利用它,配以不同的學(xué)習(xí)率和動量。


          許多更高級的優(yōu)化方法有更多的參數(shù),更復(fù)雜,也有更快的收斂速度。好與壞,是不是需要用,取決于你的問題。


          為了更好的利用好一個給定的(優(yōu)化)方法,你真的需要弄明白每個參數(shù)的意義,然后針對你的問題通過格點搜索不同的的取值。困難,消耗時間,但是值得。


          我發(fā)現(xiàn)了一些更新更流行的方法,它們可以收斂的更快,并且針對一個給定網(wǎng)絡(luò)的容量提供了一個快速了解的方式,例如:


          • ADAM
          • RMSprop


          你還可以探索其他優(yōu)化算法,例如,更傳統(tǒng)的(Levenberg-Marquardt)和不那么傳統(tǒng)的(genetic algorithms)。其他方法能夠為隨機梯度下降法和其他類似方法提供好的出發(fā)點去改進(jìn)。


          要被優(yōu)化的損失函數(shù)與你要解決的問題高度相關(guān)。然而,你通常還是有一些余地(可以做一些微調(diào),例如回歸問題中的均方誤(MSE)和平均絕對誤差(MAE)等),有時候變換損失函數(shù)還有可能獲得小的性能提升,這取決于你輸出數(shù)據(jù)的規(guī)模和使用的激活函數(shù)。


          以下是相關(guān)閱讀:


          • An overview of gradient descent optimization algorithms
          • http://sebastianruder.com/optimizing-gradient-descent/
          • What are conjugate gradients, Levenberg-Marquardt, etc.?
          • ftp://ftp.sas.com/pub/neural/FAQ2.html#A_numanal
          • On Optimization Methods for Deep Learning, 2011 PDF
          • http://ai.stanford.edu/~ang/papers/icml11-OptimizationForDeepLearning.pdf


          9) Early Stopping/早停法


          一旦訓(xùn)練過程中出現(xiàn)(驗證集)性能開始下降,你可以停止訓(xùn)練與學(xué)習(xí)。這可以節(jié)省很多時間,而且甚至可以讓你使用更詳盡的重采樣方法來評估你的模型的性能。


          早停法是一種用來避免模型在訓(xùn)練數(shù)據(jù)上的過擬合的正則化方式,它需要你監(jiān)測模型在訓(xùn)練集以及驗證集上每一輪的效果。一旦驗證集上的模型性能開始下降,訓(xùn)練就可以停止。


          如果某個條件滿足(衡量準(zhǔn)確率的損失),你還可以設(shè)置檢查點(Checkpointing)來儲存模型,使得模型能夠繼續(xù)學(xué)習(xí)。檢查點使你能夠早停而非真正的停止訓(xùn)練,因此在最后,你將有一些模型可供選擇。


          以下是相關(guān)閱讀:

          • How to Check-Point Deep Learning Models in Keras
          • http://machinelearningmastery.com/check-point-deep-learning-models-keras/
          • What is early stopping?
          • ftp://ftp.sas.com/pub/neural/FAQ3.html#A_stop


          通過嵌套模型提升性能


          你可以組合多個模型的預(yù)測能力。剛才提到了算法調(diào)參可以提高最后的性能,調(diào)參之后這是下一個可以提升的大領(lǐng)域。


          事實上,你可以經(jīng)常通過組合多個“足夠好的”模型來得到優(yōu)秀的預(yù)測能力,而不是通過組合多個高度調(diào)參的(脆弱的)模型。


          你可以考慮以下三個方面的嵌套方式:


          1. 組合模型
          2. 組合視角
          3. 堆疊(Stacking)


          1) 組合模型


          有時候我們干脆不做模型選擇,而是直接組合它們。


          如果你有多個不同的深度學(xué)習(xí)模型,在你的研究問題上每一個都表現(xiàn)的還不錯,你可以通過取它們預(yù)測的平均值來進(jìn)行組合。


          模型差異越大,最終效果越好。例如,你可以應(yīng)用非常不同的網(wǎng)絡(luò)拓?fù)浠蛘卟煌募夹g(shù)。


          如果每個模型都效果不錯但是不同的方法/方式,嵌套后的預(yù)測能力將更加魯棒。


          每一次你訓(xùn)練網(wǎng)絡(luò),你初始化不同的權(quán)重,然后它會收斂到不同的最終權(quán)重。你可以多次重復(fù)這一過程去得到很多網(wǎng)絡(luò),然后把這些網(wǎng)絡(luò)的預(yù)測值組合在一起。


          它們的預(yù)測將會高度相關(guān),但是在那些難以預(yù)測的特征上,它會給你一個意外的小提升。


          以下是相關(guān)閱讀:


          • Ensemble Machine Learning Algorithms in Python with scikit-learn
          • http://machinelearningmastery.com/ensemble-machine-learning-algorithms-python-scikit-learn/
          • How to Improve Machine Learning Results
          • http://machinelearningmastery.com/how-to-improve-machine-learning-results/


          2) 組合視角


          同上述類似,但是從不同視角重構(gòu)你的問題,訓(xùn)練你的模型。


          同樣,目標(biāo)得到的是效果不錯但是不同的模型(例如,不相關(guān)的預(yù)測)。得到不同的模型的方法,你可以依賴我們在數(shù)據(jù)那一小節(jié)中羅列的那些非常不同的放縮和轉(zhuǎn)換方法。


          你用來訓(xùn)練模型的轉(zhuǎn)換方法越不同,你構(gòu)建問題的方式越不同,你的結(jié)果被提升的程度就越高。


          簡單使用預(yù)測的均值將會是一個好的開始。


          3) stacking/堆疊


          你還可以學(xué)習(xí)如何最佳地組合多個模型的預(yù)測。這稱作堆疊泛化(stacked generalization),或者簡短來說就叫堆疊。


          通常上,你使用簡單線性回歸方法就可以得到比取預(yù)測平均更好的結(jié)果,像正則化的回歸(regularized regression),就會學(xué)習(xí)如何給不同的預(yù)測模型賦權(quán)重。基線模型是通過取子模型的預(yù)測均值得到的,但是應(yīng)用學(xué)習(xí)了權(quán)重的模型會提升性能。


          • Stacked Generalization (Stacking)
          • http://machine-learning.martinsewell.com/ensembles/stacking/


          其余的可參考資源


          別的地方有很多很好的資源,但是幾乎沒有能將所有想法串聯(lián)在一起的。如果你想深入研究,我列出了如下資源和相應(yīng)的博客,你能發(fā)現(xiàn)很多有趣的東西。


          • Neural Network FAQ
          • ftp://ftp.sas.com/pub/neural/FAQ.html
          • How to Grid Search Hyperparameters for Deep Learning Models in Python With Keras
          • http://machinelearningmastery.com/grid-search-hyperparameters-deep-learning-models-python-keras/
          • Must Know Tips/Tricks in Deep Neural Networks
          • http://lamda.nju.edu.cn/weixs/project/CNNTricks/CNNTricks.html
          • How to increase validation accuracy with deep neural net?
          • http://stackoverflow.com/questions/37020754/how-to-increase-validation-accuracy-with-deep-neural-net

          JavaScript 畫一棵樹?

          產(chǎn)品說要讓前端用 JavaScript 畫一棵樹出來,但是這難道不能直接讓 UI 給一張圖片嗎?

          后來一問才知道,產(chǎn)品要的是一顆 隨機樹,也就是樹的茂盛程度、長度、枝干粗細(xì)都是隨機的,那這確實沒辦法叫 UI 給圖,畢竟 UI 不可能給我 10000 張樹的圖片吧?

          所以第一時間想到的就是 Canvas,用它來畫這棵隨機樹(文末有完整代碼)

          Canvas 畫一顆隨機樹

          接下來使用 Canvas 去畫這棵隨機樹

          基礎(chǔ)頁面

          我們需要在頁面上寫一個 canvas 標(biāo)簽,并設(shè)置好寬高,同時需要獲取它的 Dom 節(jié)點、繪制上下文,以便后續(xù)的繪制

          坐標(biāo)調(diào)整

          默認(rèn)的 Canvas 坐標(biāo)系是這樣的

          但是我們現(xiàn)在需要從中間去向上去畫一棵樹,所以坐標(biāo)得調(diào)整成這樣:

          • X 軸從最上面移動到最下面
          • Y 軸的方向由往下調(diào)整成往上,并且從最左邊移動到畫布中間

          這些操作可以使用 Canvas 的方法

          • ctx.translate: 坐標(biāo)系移動
          • ctx.scale: 坐標(biāo)系縮放

          繪制一棵樹的要素

          繪制一棵樹的要素是什么呢?其實就是樹枝果實,但是其實樹枝才是第一要素,那么樹枝又有哪些要素呢?無非就這幾個點

          • 起始點
          • 樹枝長度、樹枝粗細(xì)
          • 生長角度
          • 終點

          開始繪制

          所以我們可以寫一個 drawBranch 來進(jìn)行繪制,并且初始調(diào)用肯定是繪制樹干,樹干的參數(shù)如下:

          • 起始點:(0, 0)
          • 樹枝長度、樹枝粗細(xì):這些可以自己自定義
          • 生長角度:90度
          • 終點:需要算

          這個終點應(yīng)該怎么算呢?其實很簡單,根據(jù)樹枝長度、生長角度就可以算出來了,這是初高中的知識

          于是我們可以使用 Canvas 的繪制方法,去繪制線段,其實樹枝就是一個一個的線段

          到現(xiàn)在我繪制出了一個樹干 出來

          但是我們是想讓這棵樹開枝散葉,所以需要繼續(xù)遞歸繼續(xù)去繪制更多的樹枝出來~

          遞歸繪制

          其實往哪開枝散葉呢?無非就是往左或者往右

          所以需要遞歸畫左邊和右邊的樹枝,并且子樹枝肯定要比父樹枝更短、比父樹枝更細(xì),比如我們可以定義一個比例

          • 子樹枝是父樹枝長度的 0.8
          • 子樹枝是父樹枝粗細(xì)的 0.75

          而子樹枝的生長角度,其實可以隨機,我們可以在 0° - 30° 之間隨機選一個角度,于是增加了遞歸調(diào)用的代碼

          但是這個時候會發(fā)現(xiàn),報錯了,爆棧了,因為我們只遞歸開始,但卻沒有在某個時刻遞歸停止

          我們可以自己定義一個停止規(guī)則(規(guī)則可以自己定義,這會決定你這棵樹的茂盛程度):

          • 粗細(xì)小于 2 時馬上停止
          • (粗細(xì)小于 10 時 + 隨機數(shù))決定是否停止

          現(xiàn)在可以看到我們已經(jīng)大致繪制出一棵樹了

          不過還少了樹的果實

          繪制果實

          繪制果實很簡單,只需要在繪制樹枝結(jié)束的時候,去把果實繪制出來就行,其實果實就是一個個的白色實心圓

          至此這棵樹完整繪制完畢

          繪制部分的代碼如下

          完整代碼


          主站蜘蛛池模板: 天天爽夜夜爽人人爽一区二区 | 日本精品一区二区三区在线视频 | 久久精品一区二区| 欧亚精品一区三区免费| 日日摸夜夜添一区| 国产一区二区精品久久岳√| 亚洲AV无码一区二区三区DV| 麻豆国产一区二区在线观看| 亚洲一区动漫卡通在线播放| 国产亚洲一区二区精品| 久久久99精品一区二区| 精品国产一区二区三区麻豆 | 国产精品一区二区av不卡| 日韩人妻不卡一区二区三区| 亲子乱av一区二区三区| 成人国产一区二区三区| 久久久精品人妻一区二区三区| 五月婷婷一区二区| 秋霞鲁丝片一区二区三区| 亚洲高清偷拍一区二区三区| 色欲AV蜜臀一区二区三区| 中文字幕精品一区二区2021年| 久久精品无码一区二区日韩AV| 国产一区二区影院| 色狠狠色狠狠综合一区| 国产视频福利一区| 国产精品区AV一区二区| 天堂成人一区二区三区| 99国产精品一区二区| 无码人妻一区二区三区一| 亚洲av成人一区二区三区观看在线 | 精品深夜AV无码一区二区| 中文字幕一区二区三区精彩视频 | 国产成人一区二区三区高清| 一区二区三区在线观看视频| 国产成人精品一区二区秒拍| 成人欧美一区二区三区在线视频| 国产一区二区内射最近更新| 一区二区三区精品高清视频免费在线播放| 精品一区二区三区东京热| 夜夜嗨AV一区二区三区|