2016年1月31日 星期日

[ipython] jupyter 數學公式的寫法(還有顯示 $ 錢字號 dollar sign)

目前查到的有兩種方法。一種是用 ipython.display 的功能,一個是使用 mathjax。

使用 ipython.display
ipython.display 提供非常豐富的顯示方式,這種方式是靠 code cell 執行程式處理。
像是:
來源[1]

來源[1]





使用 mathjax
基本上 jupyter 已經是使用 mathjax 處理數學公式。而且它整合在 markdown cell 裡。
所以只要把建立一個 markdown cell,把 latex 的表示的前後加上 $ 這個符號,像這樣:
$c = \sqrt{a^2 + b^2}$

再按下 cell 的執行按鈕,就會畫出公式了。
來源[2]

因為錢字號現在被視為語言關鍵字,在文章中要顯示 $ 的方法,可以看以下文章:http://codebeta.blogspot.tw/2016/01/blogspot-blogger-latex.html


參考:
[1]http://nbviewer.jupyter.org/github/ipython/ipython/blob/1.x/examples/notebooks/Part%205%20-%20Rich%20Display%20System.ipynb

[2]http://jupyter-notebook.readthedocs.org/en/latest/notebook.html#markdown-cells

[mathjax]在 blogspot / blogger 網誌裡顯示 latex

要在網頁上顯示公式,現在查到的主流方法是用 latex 語法,函式庫是用 Mathjax。總之時代進步了,就這個樣子。

查到的方式是,在網頁範本裡的 head 區加入定義好的 script。有人已經好心處理好了。

blogspot 的範本是在這裡開啟:



按下去之後就是:



在 </head> 之上插入以下的程式碼:

<script type="text/javascript" src="http://cdn.mathjax.org/mathjax/latest/MathJax.js">
MathJax.Hub.Config({
 extensions: ["tex2jax.js","TeX/AMSmath.js","TeX/AMSsymbols.js"],
 jax: ["input/TeX", "output/HTML-CSS"],
 tex2jax: {
     inlineMath: [ ['$','$'], ["\\(","\\)"] ],
     displayMath: [ ['$$','$$'], ["\\[","\\]"] ],
 },
 "HTML-CSS": { availableFonts: ["TeX"] }
});
</script> 
存檔,然後寫個網誌來試試,像這樣:$$ \sum_a^b x^2 $$ $$ \sum_a^b x^2 $$

現在要顯示錢字號,就要包在 <span class="tex2jax_ignore">$</span> 裡面。有沒有更方便的方式,我暫時不知道。

參考:
http://tex.stackexchange.com/questions/13865/how-to-use-latex-on-blogspot

https://blogueun.wordpress.com/2014/01/04/escaping-in-mathjax/

[ipython] ipython notebook / jupyter 介紹--為什麼我要用

其實我的目的是,利用 ipython notebook / jupyter 當做多功能編輯器,取代 notepad++ 或是 word。

在安裝 anaconda 之後,不論在命令列是執行 ipython notebook,或是執行 jupyter notebook,都會成出現同一個畫面:
已經是 jupyter 了。所以原來的 ipython notebook 畫面,我現在用不出來。
圖片來自 http://ipython.org/notebook.html

但是,由以下的 demo 還是可以體會到 ipython notebook / jupyter notebook的魅力。


與 jupyter notebook 的畫面比較,似乎沒有太大差別。

要提一下的是,ipython 是一件事,ipython notebook 是另外一件事。ipython 是提升 python 的互動性的介面,所以叫 ipython (interactive python)。而 ipython notebook 則是一個 web app 讓使用 python介紹、呈現資料、計算更為活潑即時,而它的確建立在 ipython 之上。

jupyter 與 jupyter notebook 也差不多是兩件事,jupyter 有他偉大的計劃, 希望能讓其他的語言也能 ipython notebook 達到的效果。而 jupyter notebook 則是目前執行出這個 web app 的指令。

而目前,我剛好就只需要用到 ipython notebook 的功能,而現在它屬於 jupyter notebook 其中一個項目之中。為什麼還要換 ipython notebook 呢?因為網路上用 ipython notebook 當關鍵字搜尋到的非官方資源還是佔多數,若是要自己多學就還是要知道 ipython notebook 與 jupyter notebook 的關係。
例如:在 google 輸入 jupyter notebook latex,出來第一個還是:

連 google 都知道要用 ipython notebook 會是比較對的結果,當我們知道它們的關係,就不會直接跳過它,而會點進去看。

如果說想深一點了解我想做什麼的話,我用一個網頁來代表:http://hplgit.github.io/doconce/doc/pub/slides/scientific_writing-1.html
雖然文章主打不是 ipython notebook。

參考:
http://ipython.org/notebook.html

2016年1月29日 星期五

[ipython] anaconda 一個方便的 ipython notebook 安裝

有許多網誌教導,「安裝 ipython 會遇到許多麻煩,所以新手最簡單的就是下載 anaconda 來裝,一切沒煩惱。接下來我們來下載……。」於是,我就來試毒,看看有什麼麻煩,先從安裝 anaconda 開始。

首先從 https://www.continuum.io/downloads 選擇安裝器。我選的是紅框那個 windows python 2.7 32bit


下載完之後,點兩下就執行,一開始都按下一步,但很快遇到第一個選項要決定:

如果選了 Just Me,安裝目錄就會被選在使用者的家底下,例如 C:\User|xxx\Anaconda2。這個樣子我不太喜歡。所以我選了第二個,因為我希望它被放在 C 槽根目錄底下跟 C:\python27 這樣。

再來一些 Yes 與下一步之後,又遇到一個要決定的事情:

如果選擇上面的選項,在 Anaconda 環境上,就是靠 PATH 的設定來決定誰被先選到。如果不選,那就是只能用 anaconda 提供的命令列視窗使用 anaconda 的環境。

如果選擇下面的選項,那系統要求 python 的時候,就會去找 anaconda 提供的 python 環境。如果有混搭如他所說的 IDE,就要選擇這個會比較方便。

因為我本身已經安了一堆東西在 C:\Python27 底下,也習慣了,所以第二個選項就不勾了,只勾第一個選項。

按下 Install 之後,就是等待,然後就安裝完畢了。

因為我是 win10,我按下視窗鍵用眼睛要找 "Anaconda (32-bit)",找不到…。


看不到不代表沒有,反正東西就在那裡了。在命令列直接打 ipython。我原本沒裝的 ipython,現在有反應了。



我為什麼要用 anaconda 呢?是為了要裝 IPython Notebook,後來進級叫做 Jupyter。(官方說法是 ipython notebook 移到 jupyter。)改篇再說。

參考:
https://www.continuum.io/why-anaconda



2015年12月15日 星期二

[RPI]rpi-raspbian-設定網路

最近改用 raspbian,也就是 raspberry pi 的 debian 版本。
開機之後,發現不會設定無線網路,終於找到一個自己很熟悉的方法。

需要幾個指令:

ifconfig -- 用來開啟/關閉介面卡
iwconfig -- 用設定無線的 SSID, key
iwlist -- 用來搜尋周圍 AP
dhcpcd -- 經由 dhcp 得到 ip

首先,先找出你的無線網卡是哪個名字
ifconfig -a

找到介面的名字後,若是沒有打開,就把它打開
ifconfig wlan0 up

接著,設定無線網卡的 SSID (在 linux 世界都叫它 ESSID)
iwconfig wlan0 essid <essid>

還有設定無線網卡的金鑰
iwconfig wlan0 key <key>

最後,設定 ip,若是使用 dhcp,使用指令如下
dhcpcd wlan0

指定 ip 則是使用下例指令
ifconfig wlan0 192.168.1.2
網路匣道設定
route add default gw 192.168.1.1

我以前就會,現在真的忘光光了。
http://betaparticle.pixnet.net/blog/post/41609278

2015年12月6日 星期日

[超譯]bottle 非同步應用入門

#非同步應用入門

非同步的設計模式沒有辦法與 WSGI 的同步本性好好的融合。
這也就是為何多數非同步的架構(framework, ex:tornado, twisted)實作特殊的 API 才能使用他們的非同步特性。
Bottle 是一種 WSGI 架構,也就有 WSGI 的同步本性,所幸有超讚的 「gevent 專案」,bottle 仍有可能寫出非同步應用。
本文就在說明擁有非同步 WSGI 的 bottle 的使用。

#同步 WSGI 的限制
簡單來說,WSGI 規範(pep 3333) 定義一個 request/response 的循環,如後:
對於每個 request,應用程式可呼叫點被呼叫一次,就要「必須」回傳一個內容列舉。
有了那個列舉,server 就會用它來逐步取得內容,然後一次一次寫到 chunk 進 socket。
當該列舉到盡頭,client 連結就被關掉。

足夠簡單,但有個小問題,這就是所謂的同步呼叫。如果你的應用需要等待一些資料(IO, sockets, databases,...),這就只有兩個選擇,要嘛先 yeild 一個空字串(empty string),再不就卡住當前的執行緒(thread)。以上兩選擇,都將佔住處理的執行緒,造成無法回應新的 request。這就造成一個執行緒同一時間只能處理一個 request。

多數 server 會限制執行緒數目避免太多的負荷,一個執行緒池(pools)大多是設定執行緒數目在 20 以下。只要所有的執行緒都有事做,任何新的連線都會卡住。此時對其他人而言跟死掉沒兩樣。如果,你打算實作一個聊天室,採用 long-polling ajax request 以取得即時的更新,你很容易就碰到 20 個同時連線的限制。這只是個非常小的聊天室而已。

#救援投手上場 greenlet
多數 server 限制 worker pools 擁有的執行緒數目在一個相對低檔的數字,是因為執行緒切換與產生新執行緒的代價頗高。與fork 行程(process)相比,執行緒比較便宜沒錯,但為每個連線建一個新的執行緒還是滿貴的。

gevent 模組加入 greenlet 這個東西。Greenlet 與傳統的執行緒行為一樣,但建立 greenlet 很便宜。一個採用 gevent 的 server,可以產生出數千個 greenlet,一對一處理每個連線,而且幾乎沒有額外代價。任何一個 greenlet 卡住,不會影響 server 接受新 request 的能力。可同時間處理的連結數幾乎是無限制。

這讓建立一個非同步應用不可思議的簡單,因為他看起來就跟同步的應用一樣。一個 gevent 的 server,實際上不是非同步,它行為像是超多執行緒。以下是範例:

    from gevent import monkey; monkey.patch_all()
   
    from time import sleep
    from bottle import route, run
   
    @route('/stream')
    def stream():
        yield 'START'
        sleep(3)
        yield 'MIDDLE'
        sleep(5)
        yield 'END'
   
    run(host='0.0.0.0', port=8080, server='gevent')

第一行,超重要。它讓 gevent 把 python 多數的阻塞式 API 變成不會阻塞現用執行緒,而是讓 CPU 去處理下一個 greenlet。它實際上是用 gevent 的 pseudo-thread 取代 python 的 threading 模組。因此,你仍可以用 time.sleep() 來卡住整個執行緒。如果你對於取代 python 內建模組不舒服,那可以使用對應的 gevent 函式(在此範例是 gevent.sleep())

如果,你執行這個腳本,然後用瀏覽器指到 http://localhost:8080/stream,你應該可以看到 START, MIDDLE, END 一個接一個的出現(而不是等 8 秒後一次看見它們)。這行為與使用一般執行緒是一樣的,但是你的 server 可以同時處理數千個 request 也不會有問題。

    note: 有些瀏覽器會暫存一些資料再開始畫頁面。這情況發生時可以 yield 多點資料看看是否有改善。另外,多數瀏覽器自身就會有限制一個 URL 只開一個連線。若是遇到這問題,你可使用第二個瀏覽器或是效能評估工具(例如 ab 或 httperf)來量測效能。
   
#事件 callback
非同步架構中(包含 tornado, twisted, node.js),一種常見的設計模式是使用非阻塞 API,綁一個 callback 到非同步事件。像是 sccket 物件是持續開啟,直到明確被關閉,也允許稍後有資料時呼叫 callback 寫入到 socket。這裡有個 tornado library 的範例:

    class MainHandler(tornado.web.RequestHandler):
        @tornado.web.asynchronous
        def get(self):
            worker = SomeAsyncWorker()
            worker.on_data(lambda chunk: self.write(chunk))
            worker.on_finish(lambda: self.finish())
   
主要的好處是,request 的 handler 可早點被結束掉。該執行緒就有空可處理新 request,當 callback 被呼叫時依然能把前一個 request 的資料寫到 socket 去。這些架構就能以小量作業系統的執行緒同時處理許大量 request。

使用 gevent + WSGI 的時候,事情就不是這樣了。首先,提早結束這件事沒有益處,因為我們擁有無限制的(pseudo)執行緒池可以接收新的 request。第二,我們也不能提早結束,因為這會讓 socket 被關掉(這是被 WSGI 要求的)。第三,我們必須回傳一個列舉以符合 WSGI。

為了要符合 WSGI 標準,我們能做的,就是回傳內容的列舉,而該列舉是可以非同步的寫入。有了 gevent.queue 的幫助,我們能「模擬」一個斷開的 socket,然後把前面的範例改寫如下:

    @route('/fetch')
    def fetch():
        body = gevent.queue.Queue()
        worker = SomeAsyncWorker()
        worker.on_data(body.put)
        worker.on_finish(lambda: body.put(StopIteration))
        worker.start()
        return body
   
從 server 的角度來看,這個 queue 物件是可列舉的。它會阻塞住,如果它沒有內容,而當他遇到 StopIteration 的時候會馬上停止。這符合 WSGI。在應用程式這邊,queue 物件表現就跟個非阻塞的 socket 一樣。你可以在任何時候寫入它,傳遞它,甚至開一個 pseudo 執行緒以非同步方式寫入它。這就是多數 long-polling 的實作方法。

#最後一招 websocket
讓我們暫時忘記底層的細節,來談談 WebSocket。既然你在讀這文章,或許你知道 websocket 是什麼。它是一個雙向溝通的通道,存在於瀏覽器(client)與網路應用程式(server)之間。感謝 gevent-websocket 套件,已經把難的工作都做完了。這裡有個簡單的 websocket 端點,它可以接受訊息然後傳回去給 client:

    from bottle import request, Bottle, abort
    app = Bottle()
   
    @app.route('/websocket')
    def handle_websocket():
        wsock = request.environ.get('wsgi.websocket')
        if not wsock:
            abort(400, 'Expected WebSocket request.')
   
        while True:
            try:
                message = wsock.receive()
                wsock.send("Your message was: %r" % message)
            except WebSocketError:
                break
   
    from gevent.pywsgi import WSGIServer
    from geventwebsocket import WebSocketError
    from geventwebsocket.handler import WebSocketHandler
    server = WSGIServer(("0.0.0.0", 8080), app,
                        handler_class=WebSocketHandler)
    server.serve_forever()

while-loop 一直執行到 client 關掉連線。你知道的 :)

client 端的 javascript API 也很直接:
    <!DOCTYPE html>
    <html>
    <head>
      <script type="text/javascript">
        var ws = new WebSocket("ws://example.com:8080/websocket");
        ws.onopen = function() {
            ws.send("Hello, world");
        };
        ws.onmessage = function (evt) {
            alert(evt.data);
        };
      </script>
    </head>
    </html>
   
   
原文:
http://bottlepy.org/docs/dev/async.html

2015年11月29日 星期日

[讀書心得]改變世界的九大演算法

«改變世界的九大演算法»裡面,九大演算法其實是講九大類的演算法。也可以說是九個應用方面的演算法。作者在每一類演算法會試著講解一個到數個演算法的名字,然後挑一個容易用文字說明的演算法,仔細描述它是如何發生作用的,並說明它所帶來的影響。

當然作者的九個應用方面也不是隨便挑的,還是符合現代社會的主題「網路」、「連結」,由這兩個主題所要解決的問題有:網頁搜尋、網頁排名、 資料傳輸、資料儲存、資料分類(人工智慧)。於是,這些問題的解決方法,就很自然地展開為第二章到第九章。對,第二章到第九章。腦筋有在轉的朋友應該會算一下,從二數到九,只有八個。那第九個到哪兒去了?

我看完之後,也找了一下,到底是我有問題還是作者有問題?於是我翻來翻去,終於在封底找到了一句可證明第十章說的就是那個第九個演算法。那個「如果存在的話,將會很了不起的偉大演算法」,就放在第十章落落長的數學反證法的描述裡,非常值得一生細讀一次。第十章裡面還有哲學性的思考,人類的創造物,電腦,是否會因為人腦的極限而有極限?

過往的世界,很多光芒都從電腦這個學科裡爆發,作者也在第十一章說明一個淺顯的道理,因為電腦是前所未有的新領域,隨手撿來都是寶石。跟前期的物理爆發、更前期的化學爆發一樣。然而,接下來的時代,進入穩定成長期的演算法研究,想發現新的偉大演算法,就像在滿是繁星的夜空中,想要發現一顆沒被發現又耀眼奪目的星星。

我覺得最重要的是第十一章,建議大家從第十一章開始讀再回頭讀第一章。想要了解演算法不用知道任何電腦語言。書裡所說的演算法都是概念,語言是一個表達概念的工具,所以用任何語言都可以表達。重要的是知道,我們既習以為常、以為萬能的電腦,它能做什麼,又不能做什麼。才不會自尋煩惱。