天天看點

[轉]IPython Notebook簡介1

原文:http://hyry.dip.jp/tech/slice/slice.html/35

Python Notebook簡介1

作者 : RY    标簽: cython ipython-notebook

IPython notebook目前已經成為用Python做教學、計算、科研的一個重要工具。本文介紹IPython notebook的一些基本用法,以及如何使用它調試Cython程式。

IPython Notebook使用浏覽器作為界面,向背景的IPython伺服器發送請求,并顯示結果。在浏覽器的界面中使用單元(Cell)儲存各種資訊。Cell有多種類型,經常使用的有表示格式化文本的Markdown單元,和表示代碼的Code單元。

每個代碼單元都有一個輸出區域,在Code單元中輸入代碼,按 Shift-Enter 将運作此代碼,代碼中最後一個表達式的值将輸出區域顯示。如果希望屏蔽輸出,可以在最後一條語句之後添加一個分号:”;”。此外,代碼中還可以使用print語句在輸出區域中顯示資訊。

在Markdown單元中還可以直接使用Html和Javascript。

數學公式

在Markdown單元中可以使用LaTeX表示數學公式,例如。數學公式的顯示使用MathJax,預設情況下,MathJax從網絡上下載下傳,如果希望離線使用它,需要在IPython Notebook中輸入如下代碼,把MathJax安裝到本地磁盤中:

from IPython.external.mathjax import install_mathjax
install_mathjax()
      

Code單元的輸出也可以顯示為數學公式,例如在單元中輸入如下代碼,将顯示為數學公式:

from IPython.display import Latex
Latex(r"$\sqrt{x^2+y^2}$")
      

SymPy的表達式也可以顯示為LaTex,例如:

%load_ext sympyprinting
from sympy import *
x, y = symbols("x,y")
sqrt(x**2+y**2)
      

以%開頭的為IPython的指令(Magic Command),這裡通過%load_ext指令載入sympyprinting擴充插件,載入此插件之後,所有的SymPy表達式都顯示為數學公式。

各種顯示

IPython.display子產品中提供了許多顯示Python傳回值的類,例如下面的代碼用Image類顯示”python.png”圖檔,預設路徑為Notebook檔案所在的目錄:

from IPython.display import Image
Image(filename="python.png")
      

Image還可以用來顯示表示圖像的字元串。例如下面的代碼通過cv2的imencode()将NumPy數組轉換為一個表示PNG圖像資料的數組,然後将此數組轉換為字元串之後通過Image()将顯示為圖像:

import cv2
import numpy as np
from IPython.display import Image
img = np.random.randint(0,255,(250,250,3))
cv2.blur(img, (11,11), img)
r, dat = cv2.imencode(".png",img)
Image(dat.tostring())
      

此外,還可以通過HTML和Javascript将Python代碼的輸出顯示為Html,或者作為Javascript運作。

from IPython.display import Javascript
Javascript("alert('ok')")
      

将在浏覽器中運作Javascript代碼。

Magic指令

IPython中Magic指令有兩種執行方式,以%開始的指令被稱為行指令,它隻對單行有效,以%%開頭的為單元指令,它放在單元的第一行,對整個單元有效。例如timeit指令可以快速測試代碼的執行效率,它可以作為行指令或者單元指令。

%timeit 1 + 1
%timeit 1.0 + 1.0
%timeit "1" + "1"
      
10000000 loops, best of 3: 52 ns per loop
10000000 loops, best of 3: 53.4 ns per loop
10000000 loops, best of 3: 50.9 ns per loop
      
%%timeit
s = 0
for i in xrange(100):
    s += i
      
100000 loops, best of 3: 11 us per loop
      

每個Magic指令都可以指定參數,可以輸入timeit?檢視其幫助文檔。下面讓我們看看一些常用的Magic指令。

%pylab指令将載入numpy和pylab,并且将這兩個子產品中的名字載入到全局名字空間中。預設參數時,它使用matplotlib的預設界面庫顯示圖表,如果帶inline參數則将圖表作為圖像插入到Notebook中。使用界面庫顯示圖像時可以使用互動工具,而将圖表直接插入到Notebook中則有利于編寫文檔。

下面的例子,plot和random是從pylab和numpy中載入的。

%pylab inline
plot(random.randn(100));
      
Welcome to pylab, a matplotlib-based Python environment [backend: module://IPython.zmq.pylab.backend_inline].
For more information, type 'help(pylab)'.
      

%load可以從檔案或者網址載入代碼到一個新的單元中,例如下面載入某個matplotlib的示例程式,并執行:

%load http://matplotlib.org/mpl_examples/pylab_examples/histogram_demo.py
      
#!/usr/bin/env python
import numpy as np
import matplotlib.mlab as mlab
import matplotlib.pyplot as plt

mu, sigma = 100, 15
x = mu + sigma*np.random.randn(10000)

# the histogram of the data
n, bins, patches = plt.hist(x, 50, normed=1, facecolor='green', alpha=0.75)

# add a 'best fit' line
y = mlab.normpdf( bins, mu, sigma)
l = plt.plot(bins, y, 'r--', linewidth=1)

plt.xlabel('Smarts')
plt.ylabel('Probability')
plt.title(r'$\mathrm{Histogram\ of\ IQ:}\ \mu=100,\ \sigma=15$')
plt.axis([40, 160, 0, 0.03])
plt.grid(True)

plt.show()
      

%prun用于代碼的執行性能分析,可以作為行指令和單元指令使用。下面的程式分析numpy.linalg.det()的性能:

%%prun
for i in xrange(100):
    linalg.det(random.rand(10,10))
      

其輸出如下:

3402 function calls in 0.096 seconds

Ordered by: internal time

ncalls  tottime  percall  cumtime  percall filename:lineno(function)
   100    0.032    0.000    0.091    0.001 linalg.py:1560(slogdet)
   300    0.022    0.000    0.022    0.000 {method 'reduce' of 'numpy.ufunc' objects}
   200    0.011    0.000    0.012    0.000 numeric.py:167(asarray)
   100    0.006    0.000    0.006    0.000 linalg.py:84(_realType)
   100    0.005    0.000    0.005    0.000 linalg.py:151(_assertRank2)
   ...
      

%load_ext載入IPython的擴充子產品,通過它可以載入更多的Magic指令。下面我們載入cythonmagic子產品,并使用%%cython指令編譯一個高效的頻率統計函數count()。

%load_ext cythonmagic
      

測試Cython代碼

Cython的代碼基本和Python的代碼類似,但是可以使用類型聲明,Cython可以使用這些類型聲明産生更高效的C語言代碼,并編譯成Python的擴充子產品。使用%%cython指令簡化了編譯擴充子產品的過程,它會自動建立C語言程式,編譯并載入。由于擴充子產品無法解除安裝,是以IPython采用的政策是每次編譯不同的代碼都會産生一個全新的擴充子產品。友善我們不退出Python環境即可運作新的代碼。

%%cython
def count(list data):
    cdef:
        dict result = {}
        int i, length = len(data)
        object item

    for i in range(length):
        item = data[i]
        if item in result:
            (<list> result[item]).append(i)
        else:
            result[item] = [i]
    return result
      

下面是count()的Python版本。

from collections import defaultdict
def countpy(data):
    result = defaultdict(list)
    for i,item in enumerate(data):
        result[item].append(i)
    return result
      

先測試二者的結果是否相同:

import random
data = [random.randint(0,100) for _ in xrange(10000)]
count(data) == countpy(data)
      
True
      

然後測試它們的執行速度,可以看出Cython版本比Python的要快2倍多。在這個測試中,Cython程式也同樣使用清單和字典等對象,但是由于可以直接調用Python的C API,是以Cython版本的效率能提高幾倍。如果隻是單純的數值運算,Cython能将程式提升到與C語言相近的速度。

%timeit countpy(data)
%timeit count(data)
      
100 loops, best of 3: 4.52 ms per loop
1000 loops, best of 3: 1.8 ms per loop