<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 2.3 代碼除錯 **作者**:Ga?l Varoquaux 這篇教程探索了更好的理解代碼基礎、尋找并修復bug的工具。 這部分內容并不是特別針對于科學Python社區,但是我們將要采用的策略是專門針對科學計算量身定制的。 **先決條件** * Numpy * IPython * nosetests ([http://readthedocs.org/docs/nose/en/latest/](http://readthedocs.org/docs/nose/en/latest/)) * pyflakes ([http://pypi.python.org/pypi/pyflakes](http://pypi.python.org/pypi/pyflakes)) * gdb對C-debugging部分。 **章節內容** * 避免bugs * 避免麻煩的最佳代碼實踐 * pyflakes:快速靜態分析 * 在當前編輯的文件上運行pyflakes * 隨著打字進行的拼寫檢查器整合 * 查錯工作流 * 使用Python除錯器 * 激活除錯器 * 事后剖析 * 逐步執行 * 啟動除錯器的其他方式 * 除錯器命令與交互 * 在除錯器中獲得幫助 * 使用gdb排除代碼段的錯誤 ## 2.3.1 避免bugs ### 2.3.1.1 避免麻煩的最佳代碼實踐 **Brian Kernighan** “每個人都知道除錯比從零開始寫一個程序難兩倍。因此,如果當你寫程序時足夠聰明,為什么你不對它進行除錯呢?” * 我都會寫出有錯誤的代碼。接收這些代碼。處理這些代碼。 * 寫代碼時記得測試和除錯。 * 保持簡單和直接(KISS)。 * 能起作用的最簡單的事是什么? * 不要重復自身(DRY)。 * 每一個知識碎片都必須在系統中有一個清晰、權威的表征 * 變量、算法等等 * 試著限制代碼的依賴。(松耦合) * 給變量、函數和模塊有意義的名字(而不是數學名字) ### 2.3.1.2 pyflakes:快速靜態分析 在Python中有一些靜態分析;舉幾個例子: * [pylint](http://www.logilab.org/857) * [pychecker](http://pychecker.sourceforge.net/) * [pyflakes](http://pypi.python.org/pypi/pyflakes) * [pep8](http://pypi.python.org/pypi/pep8) * [flake8](http://pypi.python.org/pypi/flake8) 這里我們關注`pyflakes`,它是最簡單的工具。 * **快速**、**簡單** * 識別語法錯誤、沒有imports、名字打印打錯。 另一個好的推薦是`flake8`工具,是pyflakes和pep8。因此,除了pyflakes捕捉錯誤類型外,flake8也可以察覺對[PEP8](http://www.python.org/dev/peps/pep-0008/)風格指南建議的違背。 強烈推薦在你的編輯器或IDE整合pyflakes (或 flake8),**確實可以產出生產力的收益**。 #### 2.3.1.2.1 在當前編輯文件上運行pyflakes 你可以在當前緩存器中綁定一個鍵來運行pyflakes。 * **在kate中** * 菜單:設定 -&gt; 配置 kate * 在插件中啟用“外部” * 在外部工具,添加pyflakes: In?[?]: ``` kdialog --title "pyflakes %filename" --msgbox "$(pyflakes %filename)" ``` * **在TextMate中** * 菜單: TextMate -&gt; 偏好 -&gt; 高級 -&gt; Shell變量,添加shell變量: In?[?]: ``` TM_PYCHECKER=/Library/Frameworks/Python.framework/Versions/Current/bin/pyflakes ``` ``` - 然后 Ctrl-Shift-V 被綁定到pyflakes報告 ``` * **在vim中** * 在你的vimrc中 (將F5綁定到pyflakes): In?[?]: ``` autocmd FileType python let &mp = 'echo "*** running % ***" ; pyflakes %' autocmd FileType tex,mp,rst,python imap <Esc>[15~ <C-O>:make!^M autocmd FileType tex,mp,rst,python map <Esc>[15~ :make!^M autocmd FileType tex,mp,rst,python set autowrite ``` * **在emacs中** * 在你的emacs中 (將F5綁定到pyflakes): In?[?]: ``` (defun pyflakes-thisfile () (interactive) (compile (format "pyflakes %s" (buffer-file-name))) ) (define-minor-mode pyflakes-mode "Toggle pyflakes mode. With no argument, this command toggles the mode. Non-null prefix argument turns on the mode. Null prefix argument turns off the mode." ;; The initial value. nil ;; The indicator for the mode line. " Pyflakes" ;; The minor mode bindings. '( ([f5] . pyflakes-thisfile) ) ) (add-hook 'python-mode-hook (lambda () (pyflakes-mode t))) ``` #### 2.3.1.2.2 隨著打字進行的拼寫檢查器整合 * **在vim中** * 使用pyflakes.vim插件: 1. 從[http://www.vim.org/scripts/script.php?script_id=2441](http://www.vim.org/scripts/script.php?script_id=2441) 下載zip文件 2. 將文件提取到~/.vim/ftplugin/python 3. 確保你的vimrc的filetype插件的縮進是開啟的 ![](http://scipy-lectures.github.io/_images/vim_pyflakes.png) * 或者: 使用syntastic插件。這個插件也可以設置為使用flake8,處理實時檢查許多其他語言。 ![](http://scipy-lectures.github.io/_images/vim_syntastic.png) * **在emacs中** * 使用flymake模式以及pyflakes, 文檔在[http://www.plope.com/Members/chrism/flymake-mode](http://www.plope.com/Members/chrism/flymake-mode) : 在你的.emacs文件中添加下來代碼: In?[?]: ``` (when (load "flymake" t) (defun flymake-pyflakes-init () (let* ((temp-file (flymake-init-create-temp-buffer-copy 'flymake-create-temp-inplace)) (local-file (file-relative-name temp-file (file-name-directory buffer-file-name)))) (list "pyflakes" (list local-file)))) (add-to-list 'flymake-allowed-file-name-masks '("\\.py\\'" flymake-pyflakes-init))) (add-hook 'find-file-hook 'flymake-find-file-hook) ``` ## 2.3.2 除錯工作流 如果你確實有一個非無關緊要的bug,這個時候就是除錯策略該介入的時候。沒有銀子彈。但是,策略會有幫助: ``` 對于給定問題的除錯,最合適的情況是當問題被隔離在幾行代碼的時候,外面是框架或應用代碼,有較短的修改-運行-失敗循環。 ``` 1. 讓它可以可靠的失敗。找到一個測試案例,可以讓代碼每次都失敗。 2. 分而治之。一旦你有一個測試案例,隔離錯誤的代碼。 * 哪個模塊。 * 哪個函數。 * 哪行代碼。 =&gt;隔離小的可重復錯誤:測試案例 3. 每次只改變一個事情并且重新運行失敗的測試案例。 4. 使用除錯器來理解哪里出錯了。 5. 耐心的記筆記。可能會花一些時間。 **筆記**:一旦你遵從了這個流程:隔離一段可以重現bug的緊密代碼段,并且用這段代碼來修復bug,添加對應代碼到你的測試套裝。 ## 2.3.3 使用Python除錯器 python除錯器,pdb: [http://docs.python.org/library/pdb.html](http://docs.python.org/library/pdb.html), 允許你交互的檢查代碼。 具體來說,它允許你: * 查看源代碼。 * 在調用棧上下游走。 * 檢查變量值。 * 修改變量值。 * 設置斷點。 **print** 是的,print語句確實可以作為除錯工具。但是,要檢查運行時間,使用除錯器通常更加高效。 -- ### 2.3.3.1 激活除錯器 啟動除錯器的方式: 1. 事后剖析,在模塊錯誤后啟動除錯器。 2. 用除錯器啟動模塊。 3. 在模塊中調用除錯器。 #### 2.3.3.1.1 事后剖析 **情景**: 你在IPython中工作時,你的到了一個traceback。 這里我們除錯文件[index_error.py](http://scipy-lectures.github.io/_downloads/index_error.py)。當運行它時,拋出`IndexError`。輸入`%debug`進入除錯器。 In?[1]: ``` %run index_error.py ``` ``` --------------------------------------------------------------------------- IndexError Traceback (most recent call last) /Users/cloga/Documents/scipy-lecture-notes_cn/index_error.py in <module>() 6 7 if __name__ == '__main__': ----> 8 index_error() 9 /Users/cloga/Documents/scipy-lecture-notes_cn/index_error.py in index_error() 3 def index_error(): 4 lst = list('foobar') ----> 5 print lst[len(lst)] 6 7 if __name__ == '__main__': IndexError: list index out of range ``` In?[2]: ``` %debug ``` ``` > /Users/cloga/Documents/scipy-lecture-notes_cn/index_error.py(5)index_error() 4 lst = list('foobar') ----> 5 print lst[len(lst)] 6 ipdb> list 1 """Small snippet to raise an IndexError.""" 2 3 def index_error(): 4 lst = list('foobar') ----> 5 print lst[len(lst)] 6 7 if __name__ == '__main__': 8 index_error() 9 ipdb> len(lst) 6 ipdb> print lst[len(lst)-1] r ipdb> quit ``` **不用IPthon的事后剖析除錯** 在一些情況下,你不可以使用IPython,例如除錯一個想到從命令行調用的腳本。在這個情況下,你可以用`python -m pdb script.py`調用腳本: ``` $ python -m pdb index_error.py > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/index_error.py(1)<module>() -> """Small snippet to raise an IndexError.""" (Pdb) continue Traceback (most recent call last): File "/usr/lib/python2.6/pdb.py", line 1296, in main pdb._runscript(mainpyfile) File "/usr/lib/python2.6/pdb.py", line 1215, in _runscript self.run(statement) File "/usr/lib/python2.6/bdb.py", line 372, in run exec cmd in globals, locals File "<string>", line 1, in <module> File "index_error.py", line 8, in <module> index_error() File "index_error.py", line 5, in index_error print lst[len(lst)] IndexError: list index out of range Uncaught exception. Entering post mortem debugging Running 'cont' or 'step' will restart the program > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/index_error.py(5)index_error() -> print lst[len(lst)] (Pdb) ``` #### 2.3.3.1.2 逐步執行 **情景**:你相信模塊中存在bug,但是你不知道在哪。 例如我們想要除錯[wiener_filtering.py](http://scipy-lectures.github.io/_downloads/wiener_filtering.py)。代碼確實可以運行,但是,過濾不起作用。 * 在IPython用`%run -d wiener_filtering.p`來運行這個腳本: ``` In [1]: %run -d wiener_filtering.py *** Blank or comment *** Blank or comment *** Blank or comment Breakpoint 1 at /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py:4 NOTE: Enter 'c' at the ipdb> prompt to start your script. > <string>(1)<module>() ``` * 用`b 34`在34行設置一個斷點: ``` ipdb> n > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py(4)<module>() 3 1---> 4 import numpy as np 5 import scipy as sp ipdb> b 34 Breakpoint 2 at /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py:34 ``` * 用`c(ont(inue))`繼續運行到下一個斷點: ``` ipdb> c > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py(34)iterated_wiener() 33 """ 2--> 34 noisy_img = noisy_img 35 denoised_img = local_mean(noisy_img, size=size) ``` * 用`n(ext)`和`s(tep)`在代碼中步進:`next`在當前運行的背景下跳躍到下一個語句,而`step`將跨過執行的背景,即可以檢查內部函數調用: ``` ipdb> s > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py(35)iterated_wiener() 2 34 noisy_img = noisy_img ---> 35 denoised_img = local_mean(noisy_img, size=size) 36 l_var = local_var(noisy_img, size=size) ipdb> n > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py(36)iterated_wiener() 35 denoised_img = local_mean(noisy_img, size=size) ---> 36 l_var = local_var(noisy_img, size=size) 37 for i in range(3): ``` * 跨過一些行,并且檢查本地變量: ``` ipdb> n > /home/varoquau/dev/scipy-lecture-notes/advanced/debugging_optimizing/wiener_filtering.py(37)iterated_wiener() 36 l_var = local_var(noisy_img, size=size) ---> 37 for i in range(3): 38 res = noisy_img - denoised_img ipdb> print l_var [[5868 5379 5316 ..., 5071 4799 5149] [5013 363 437 ..., 346 262 4355] [5379 410 344 ..., 392 604 3377] ..., [ 435 362 308 ..., 275 198 1632] [ 548 392 290 ..., 248 263 1653] [ 466 789 736 ..., 1835 1725 1940]] ipdb> print l_var.min() 0 ``` 哦,天啊,只有整合和0的變體。這就是我們的Bug,我們正在做整數算術。 **在數字錯誤上拋出異常** 當我們運行`wiener_filtering.py`文件時,將拋出下列警告: In?[3]: ``` %run wiener_filtering.py ``` ``` wiener_filtering.py:40: RuntimeWarning: divide by zero encountered in divide noise_level = (1 - noise/l_var ) ``` ![](https://box.kancloud.cn/2016-03-21_56efdc0a1fff0.png) ![](https://box.kancloud.cn/2016-03-21_56efdc0a45380.png) ![](https://box.kancloud.cn/2016-03-21_56efdc0a45380.png) 我們可以將這些警告變成異常,這使我們可以做事后剖析對他們進行查錯,更快的找到我們的問題: In?[5]: ``` np.seterr(all='raise') ``` Out[5]: ``` {'divide': 'warn', 'invalid': 'warn', 'over': 'warn', 'under': 'ignore'} ``` In?[6]: ``` %run wiener_filtering.py ``` ``` --------------------------------------------------------------------------- FloatingPointError Traceback (most recent call last) /Users/cloga/Documents/scipy-lecture-notes_cn/wiener_filtering.py in <module>() 55 pl.matshow(noisy_lena[cut], cmap=pl.cm.gray) 56 ---> 57 denoised_lena = iterated_wiener(noisy_lena) 58 pl.matshow(denoised_lena[cut], cmap=pl.cm.gray) 59 /Users/cloga/Documents/scipy-lecture-notes_cn/wiener_filtering.py in iterated_wiener(noisy_img, size) 38 res = noisy_img - denoised_img 39 noise = (res**2).sum()/res.size ---> 40 noise_level = (1 - noise/l_var ) 41 noise_level[noise_level<0] = 0 42 denoised_img += noise_level*res FloatingPointError: divide by zero encountered in divide ``` #### 2.3.3.1.3 啟動除錯器的其他的方式 * 人為設置斷點拋出異常 如果你發現記錄行數設置斷點很枯燥,那么你也可以直接在你想要檢查的位置拋出異常然后使用IPython的`%debug`。注意這種情況下,你無法步進或繼續這個異常。 * 用nosetests除錯測試失敗 你可以運行`nosetests --pdb`來進入異常除錯的事后剖析,運行`nosetests --pdb-failure`來用除錯器檢查失敗的測試。 此外,你可以通過安裝nose插件[ipdbplugin](http://pypi.python.org/pypi/ipdbplugin)來在nose中為除錯器使用Ipython界面。然后為nosetest傳遞`--ipdb`和`--ipdb-failure`選項。 * 顯性的調用除錯器 在你想要進入除錯器的地方插入下列幾行: In?[?]: ``` import pdb; pdb.set_trace() ``` **警告**:當運行nosetests時, 會抓取輸出,因此會感覺除錯器沒起作用。只要運行nosetests用-s標記。 **圖形化除錯器和其他除錯器** * 對于在代碼中步進和檢查變量,你會發現用圖形化除錯器比如[winpdb](http://winpdb.org/), * 或者,[pudb](http://pypi.python.org/pypi/pudb)是優秀的半圖形除錯器,在控制臺帶有文字用戶界面。 * 同時,[pydbgr]項目可能也是值得一看的。 ### 2.3.3.2 除錯器命令和交互 | | | | --- | --- | | l(list) | 列出當前位置的代碼 | | u(p) | 在調用棧上向上走 | | d(own) | 在調用棧上向下走 | | n(ext) | 執行下一行代碼(并不會進入新函數) | | s(tep) | 執行下一個語句(并不會進入新函數) | | bt | 打印調用棧 | | a | 打印本地函數 | | !command | 執行給到的Python命令(與pdb命令相對) | **警告:除錯器命令不是Python代碼** 你不能以想要的方式命名變量。例如,如果你無法在當前的框架下用相同的名字覆蓋變量:**用不同的名字,然后在除錯器中輸入代碼時使用本地變量**。 #### 2.3.3.2.1 在除錯器中獲得幫助 輸入`h`或者`help`來進入交互幫助: In?[?]: ``` import pdb; pdb.set_trace() ``` ``` --Call-- > /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/IPython/core/displayhook.py(222)__call__() -> def __call__(self, result=None): (Pdb) help Documented commands (type help <topic>): ======================================== EOF bt cont enable jump pp run unt a c continue exit l q s until alias cl d h list quit step up args clear debug help n r tbreak w b commands disable ignore next restart u whatis break condition down j p return unalias where Miscellaneous help topics: ========================== exec pdb Undocumented commands: ====================== retval rv ``` ## 2.3.4 用gdb除錯段錯誤(segmentation faults) 如果有段錯誤,你不可以用pdb對它進行除錯,因為在進入除錯器之前,它會讓Python解釋器崩潰。同樣的,如果在嵌入Python的C代碼中有一個bug,pdb也是沒用的。對于這種情況,我們可以轉用gnu除錯器,[gdb](http://www.gnu.org/s/gdb/),在Linux可用。 在我們開始使用gdb之前,讓我們為它添加一些Python專有的工具。對于這個情況我們可以添加一些宏到我們的`~/.gbdinit`。宏的最優的選擇取決于你的Python版本和gdb版本。我在[gdbint](http://scipy-lectures.github.io/_downloads/gdbinit)添加了一個簡單的版本,但是別客氣讀一下[DebuggingWithGdb](http://wiki.python.org/moin/DebuggingWithGdb)。 要用gdb來除錯Python腳本[segfault.py](http://scipy-lectures.github.io/_downloads/segfault.py), 我們可以想如下這樣在gdb中運行這個腳本 ``` $ gdb python ... (gdb) run segfault.py Starting program: /usr/bin/python segfault.py [Thread debugging using libthread_db enabled] Program received signal SIGSEGV, Segmentation fault. _strided_byte_copy (dst=0x8537478 "\360\343G", outstrides=4, src= 0x86c0690 <Address 0x86c0690 out of bounds>, instrides=32, N=3, elsize=4) at numpy/core/src/multiarray/ctors.c:365 365 _FAST_MOVE(Int32); (gdb) ``` 我們得到了一個segfault, gdb捕捉到它在C級棧(并不是Python調用棧)中進行事后剖析除錯。我們可以用gdb的命令來對C調用棧進行除錯: ``` (gdb) up #1 0x004af4f5 in _copy_from_same_shape (dest=<value optimized out>, src=<value optimized out>, myfunc=0x496780 <_strided_byte_copy>, swap=0) at numpy/core/src/multiarray/ctors.c:748 748 myfunc(dit->dataptr, dest->strides[maxaxis], ``` 如你所見,現在,我們numpy的C代碼中。我們想要知道哪個Python代碼觸發了這個segfault,因此,在棧上向上搜尋,直到我們達到Python執行循環: ``` (gdb) up #8 0x080ddd23 in call_function (f= Frame 0x85371ec, for file /home/varoquau/usr/lib/python2.6/site-packages/numpy/core/arrayprint.py, line 156, in _leading_trailing (a=<numpy.ndarray at remote 0x85371b0>, _nc=<module at remote 0xb7f93a64>), throwflag=0) at ../Python/ceval.c:3750 3750 ../Python/ceval.c: No such file or directory. in ../Python/ceval.c (gdb) up #9 PyEval_EvalFrameEx (f= Frame 0x85371ec, for file /home/varoquau/usr/lib/python2.6/site-packages/numpy/core/arrayprint.py, line 156, in _leading_trailing (a=<numpy.ndarray at remote 0x85371b0>, _nc=<module at remote 0xb7f93a64>), throwflag=0) at ../Python/ceval.c:2412 2412 in ../Python/ceval.c (gdb) ``` 一旦我們進入了Python執行循環,我們可以使用特殊的Python幫助函數。例如我們可以找到對應的Python代碼: ``` (gdb) pyframe /home/varoquau/usr/lib/python2.6/site-packages/numpy/core/arrayprint.py (158): _leading_trailing (gdb) ``` 這是numpy代碼,我們需要向上走直到找到我們寫的代碼: ``` (gdb) up ... (gdb) up #34 0x080dc97a in PyEval_EvalFrameEx (f= Frame 0x82f064c, for file segfault.py, line 11, in print_big_array (small_array=<numpy.ndarray at remote 0x853ecf0>, big_array=<numpy.ndarray at remote 0x853ed20>), throwflag=0) at ../Python/ceval.c:1630 1630 ../Python/ceval.c: No such file or directory. in ../Python/ceval.c (gdb) pyframe segfault.py (12): print_big_array ``` 對應代碼是: In?[1]: ``` def make_big_array(small_array): big_array = stride_tricks.as_strided(small_array, shape=(2e6, 2e6), strides=(32, 32)) return big_array def print_big_array(small_array): big_array = make_big_array(small_array) ``` 這樣segfault在打印`big_array[-10:]`時發生。原因非常簡單,`big_array`被分配到程序內存以外。 **筆記:**對于在`gdbinit`中定義的Python特有命令,讀一下這個文件的源代碼。 **總結練習** 下面的腳本是詳細而清晰的。它想要回答一個實際的有趣數值計算,但是,它并不起作用...你可以為它除錯嗎? Python源代碼:[to_debug.py](http://scipy-lectures.github.io/_downloads/to_debug.py) In?[?]: ``` """ A script to compare different root-finding algorithms. This version of the script is buggy and does not execute. It is your task to find an fix these bugs. The output of the script sould look like: Benching 1D root-finder optimizers from scipy.optimize: brenth: 604678 total function calls brentq: 594454 total function calls ridder: 778394 total function calls bisect: 2148380 total function calls """ from itertools import product import numpy as np from scipy import optimize FUNCTIONS = (np.tan, # Dilating map np.tanh, # Contracting map lambda x: x**3 + 1e-4*x, # Almost null gradient at the root lambda x: x+np.sin(2*x), # Non monotonous function lambda x: 1.1*x+np.sin(4*x), # Fonction with several local maxima ) OPTIMIZERS = (optimize.brenth, optimize.brentq, optimize.ridder, optimize.bisect) def apply_optimizer(optimizer, func, a, b): """ Return the number of function calls given an root-finding optimizer, a function and upper and lower bounds. """ return optimizer(func, a, b, full_output=True)[1].function_calls, def bench_optimizer(optimizer, param_grid): """ Find roots for all the functions, and upper and lower bounds given and return the total number of function calls. """ return sum(apply_optimizer(optimizer, func, a, b) for func, a, b in param_grid) def compare_optimizers(optimizers): """ Compare all the optimizers given on a grid of a few different functions all admitting a signle root in zero and a upper and lower bounds. """ random_a = -1.3 + np.random.random(size=100) random_b = .3 + np.random.random(size=100) param_grid = product(FUNCTIONS, random_a, random_b) print "Benching 1D root-finder optimizers from scipy.optimize:" for optimizer in OPTIMIZERS: print '% 20s: % 8i total function calls' % ( optimizer.__name__, bench_optimizer(optimizer, param_grid) ) if __name__ == '__main__': compare_optimizers(OPTIMIZERS) ``` In?[1]: ``` %matplotlib inline import numpy as np ```
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看