Google+ Followers

2017年8月19日 星期六

[Python] 使用 sklearn.svm 筆記 - 簡易的數據分析、機器學習萬用框架 @ macOS 10.12, Python36

svm_report

幾年前有幸參加過數據分析的黑客松,但是太耍廢了 XD 當下只用統計硬幹。最近有些閒情想好好認識一下 SVM 了。目前使用它的方式很粗淺 XD 就是把一堆 feature 湊個成 array 餵進去跑,接著就有報表可以看了(當初還人工去計算 precision / recall),回想起來真是青春啊

回過頭來,程式架構如下:

import numpy as np
import pandas as pd # 假設 input 是 csv 格式

# 讀取資料中
raw = pd.read_csv("input.csv")
# 可以得知有多少欄位可以用
print(raw.columns)

# 假設所有屬性都是可以有一對一的對應,全部把他們取代成整數,此為 HASH table 用來轉換而已
LOOK_FIELD = {}

# 假設 raw 有一萬筆資料
USE_DATA_COUNT = 10000 # or raw.size

# 將 raw 資料建置成 numpy array 架構

data_input = None
data_output = None

for index, row in raw.iterrows():

data_per_row = np.empty([])

# 將有興趣的欄位(feature)抽出來使用
for field_name in [
"csv_fieldname1",
"csv_fieldname2",
]:
field_data = np.zeros(1, dtype=np.int)
if field_name not in LOOK_FIELD:
LOOK_FIELD[field_name] = {}
if row[field_name] in LOOK_FIELD[field_name]:
field_data[0] = LOOK_FIELD[field_name][row[field_name]]
else:
field_data[0] = len(LOOK_FIELD[field_name])
LOOK_FIELD[field_name][row[field_name]] = field_data[0]
data_per_row = np.append(data_per_row, field_data.reshape(1, -1))

if data_input is None:
data_input = np.zeros([USE_DATA_COUNT, data_per_row.reshape(1, -1).size], dtype=np.float)
data_input[index] = data_per_row.reshape(1, -1)


result = np.zeros([1], dtype=np.int)

output_field_name = "csv_fieldname3"

# 將 結果 的欄位轉換成數值
if output_field_name not in LOOK_FIELD:
LOOK_FIELD[output_field_name] = {}
if row[output_field_name] in LOOK_FIELD[output_field_name]:
result[0] = LOOK_FIELD[output_field_name][ row[output_field_name] ]
else:
result[0] = len(LOOK_FIELD[output_field_name])
LOOK_FIELD[output_field_name][ row[output_field_name] ] = result[0]

if data_output is None:
data_output = np.zeros([USE_DATA_COUNT, result.reshape(1, ).size], dtype=np.int)
data_output[index] = result.reshape(1, )

# 支援只使用 USE_DATA_COUNT 筆資料
if index >= USE_DATA_COUNT - 1:
break

print(data_input)
print(data_output)
print(data_input.shape)
print(data_output.shape)

from sklearn import svm, metrics

classifier = svm.SVC()

# 使用 1/5 的資料來訓練
number_of_data_to_learn = int(USE_DATA_COUNT / 5) # or int(data_output.size/5)

# start to learn
classifier.fit(data_input[:number_of_data_to_learn], data_output[:number_of_data_to_learn])

# get the result
expected = data_output[number_of_data_to_learn:]
predicted = classifier.predict(data_input[number_of_data_to_learn:])

# get the report
print("Classification report for classifier %s:\n%s\n" % (classifier, metrics.classification_report(expected, predicted)))
print("Confusion matrix:\n%s" % metrics.confusion_matrix(expected, predicted))


透過上述的程式架構,未來就只要把資料轉成 csv ,挑挑 feature (csv_fieldname1, csv_fieldname2) 跟 output (csv_fieldname3) 欄位就可以快速看到成果了 XD 要唬人也可以 3 分鐘就弄出點東西。

2017年8月16日 星期三

[Python] matplotlib.pyplot 筆記 - 快速上手繪圖方式 @ macOS 10.11, 10.12 / Python36

最近想嘗試分析資料,看了一堆教學文都會看到繪圖的函式,如 plt.subplot, plt.plot, plt.show 等等,花了一點時間看看別人的範例,終於看懂了 XD 其實也沒有太複雜。

畫一個正弦波:

x=0-5,y=sin(x)

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.plot(x, y)
plt.show()


其中 np.arange 的參數是 x 介於 0 ~ 5 ,並且以 0.1 間隔產生,所以真正產生的數字序列為:

[ 0.   0.1  0.2  0.3  0.4  0.5  0.6  0.7  0.8  0.9  1.   1.1  1.2  1.3  1.4
  1.5  1.6  1.7  1.8  1.9  2.   2.1  2.2  2.3  2.4  2.5  2.6  2.7  2.8  2.9
  3.   3.1  3.2  3.3  3.4  3.5  3.6  3.7  3.8  3.9  4.   4.1  4.2  4.3  4.4
  4.5  4.6  4.7  4.8  4.9]


接著,在定義 y 的數值是怎樣產生,就用 plt.plot 把它畫出跟展現出來。

同理,簡單畫出個 y = 2x + 3, -2 <= x <= 10

x=-2-10,y=2x+3

import numpy as np
import matplotlib.pyplot as plt

x = np.arange(-2, 10, 0.1);
y = x * 2 + 3
plt.plot(x, y)

plt.show()


以上就快速明瞭畫圖的方式了,接著談談一張圖多個小圖,或是一口氣產生多個圖的方式。

對於一張圖有多個小圖的部分,會使用到 plt.subplot ,他吃的參數有 3 欄,也有人喜歡給一個三個位數的整數給他:

plt.subplot( x, y, z ) 或 plt.subplot(xyz)

其中 x 代表 row,y 代表 column 而 z 代表 location (顯示位置)

例如,想要做出一張有三個小圖的圖表,就可以用 row=1, column=3,接著開始作畫:

draw3

import numpy as np
import matplotlib.pyplot as plt

# draw 1 picture
plt.subplot(1,3,1)

x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.plot(x, y)

# draw 2 picture
plt.subplot(1,3,2)

x = np.arange(-2, 10, 0.1);
y = x * 2 + 3
plt.plot(x, y)

# draw 3 picture
plt.subplot(1,3,3)

x = np.arange(-5, 5, 0.1)
y = np.tan(x)
plt.plot(x, y)

plt.show()


如何在程式內一次畫多張畫布,就是用 plt.figure 來處理了

import numpy as np
import matplotlib.pyplot as plt

# draw 1 picture
plt.figure(1)

x = np.arange(0, 5, 0.1);
y = np.sin(x)
plt.plot(x, y)

# draw 2 picture
plt.figure(2)

x = np.arange(-2, 10, 0.1);
y = x * 2 + 3
plt.plot(x, y)

# draw 3 picture
plt.figure(3)

x = np.arange(-5, 5, 0.1)
y = np.tan(x)
plt.plot(x, y)

plt.show()


結果就會產出三張圖。

最後,談談環境架設的部分,這次分別在 macOS 10.11 跟 macOS 10.12 嘗試過,兩邊都分別用 MacPorts 安裝 python 3.6 和 pip 套件,並從 XQuartz 網站下載視窗軟體。

連續動作:

1. 安裝 https://dl.bintray.com/xquartz/downloads/XQuartz-2.7.11.dmg 後重開機(很重要 XD)
2. 安裝 py36-pip py36-virtualenv 和 matplotlib 繪圖需要的函式庫 py36-tkinter
3. 使用 virtualenv 建置環境,並把缺的 py36-tkinter library 移入使用
4. 安裝 matplotlib、numpy 等常用工具
5. 收工,可以把玩繪圖了

$ sudo port install py36-pip py36-virtualenv py36-tkinter
$ virtualenv study
$ source study/bin/activate
$ cd study/lib/python3.6/site-packages
$ ln -s /opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/_tkinter.cpython-36m-darwin.so  .
$ cd -
$ vim ~/.matplotlib/matplotlibrc
backend: Tkagg
(study) $ pip install matplotlib
(study) $ python draw.py


錯誤處理:

import _tkinter # If this fails your Python may not be configured for Tk
ModuleNotFoundError: No module named '_tkinter'

$ sudo port install py36-tkinter
$ cd path-virtual-env-project/lib/python3.6/site-packages
$ ln -s /opt/local/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/site-packages/_tkinter.cpython-36m-darwin.so  .


參考資料:

1. https://matplotlib.org/users/pyplot_tutorial.html
2. https://matplotlib.org/users/customizing.html

2017年7月17日 星期一

[Book] 你要如何衡量你的人生

之前被強者大大的塗鴉牆吸引到,仔細找了書來翻。有興趣的可以參考以下影片:




這些影片都提到了書中內容,有興趣可以看看(甚至快轉兩倍速節省時間也行),我覺得比較好玩的是這是以“企業管理”的角度去思索人生規劃,當我跟其他強者大大哈拉時,他們立馬就說:有沒有用“軟工”衡量人生 XD 接著就蹦出一堆搞笑的話題,例如可以 waterfall 嗎、可以 CI/CD 嗎?

回過頭來,每個人在不一樣的心境,看著一樣的文字,的確還是會有不一樣的想法跟心得,有人覺得囧星人已經總結了很多關鍵概念,不需在翻書,我自己看完書的心得,大概就像知道 QuickSort 跟實際在寫一次還是很不一樣的,可能碰到 bug 而多想了很事多練了一些經驗值。這次閱讀有不少共鳴是從工作上來的,包含企業經營的策略,卻又有一大卡車的領悟是跟小孩互動學習。

例如提到小時候要多跟小孩講話(字彙),雖然小孩不是很懂,但長期下來接受到的字彙刺激會很驚人的,讓人想起 Deep learning 的相關用詞:神經元連結。永遠都不要小看那一點點的刺激,就可能讓小孩 Machine Learning 系統有了更新穎的連結。

不知是不是年紀已到?累積一些工作經驗後,覺得這本書很對味,適合閒暇時翻翻,回顧一下工作上的營運策略,並想想人生在意的事,並付出行動去改變吧!

2017年6月30日 星期五

[BOOK] 创新工场CEO训练营教材:创业就是要细分垄断

创业就是要细分垄断

很久沒翻書了,一年可能翻不超過 3 本吧?! 這本書在五月中就看到的,那也沒特別有興趣,直到前陣子重感冒後,人厭厭的,只好找點東西刺激一下,開始亂找書來翻,於是乎就從天貓下單了,買了本實體書,不貴,才賣 25 RMB,貴反而在於台灣的快遞(22 RMB),結果在中國境內就等了 5 天在運輸,拿到書都 7 天了,早知道慢是慢在中國境內,就都改用集運了(11 RMB),整本書才 163 頁。

這本書的封面最大咖的是 李开复 ,在台灣的社群網站上褒貶不一,我以為會講很多,但只有一個章節,才 30頁(還有幾頁後記)。但開頭第一章說得不錯,提提人才的重要,也鼓勵老闆要分享股份,你是想當個 1000萬美元等級持有 60% 股份呢,還是 10億美金等級持有 20% 股份?所以介紹這本書給自己的老闆,可能也有點暗示要多給點股份吧 *誤*

接著則是 汪华(谷歌中国商务发展总部) 和 傅盛(360/可牛/金山/獵豹移動) 交錯的分享,講得自己的臉好像打了好幾次 XD 這本書醒腦的地方就是這兩位分享的論點,也代表身在台灣很難看清中國市場,更別說台灣幾乎進入已開發中的國家,各行各業的領頭羊早已建制公會築起堡壘,更別說巷弄超商已涵蓋了九成以上的生活必需服務。

我認為比較重要的是提及在一個想做的事業上,要選擇一個長遠有大需求市場的紅海,但起步是一個夠小夠養活自己的藍海,類似寫專利時,要有個 domain 足以讓專利申請通過 XDD 接著面對既有市場時,則是要想想自己提供的改善是否有五倍、十倍的效益,例如比既有產業多 5 倍的效率,單純一兩倍的效益可能不足以撼動原產業,當事業在 A 輪尾聲發現成長無法持續時,就該軸轉了,也代表很多公司無法募到 B 輪,實在是成長停滯了,未來越來越不光明。

這些思維很不錯,的確是要做大事的方向,透過這本書了解 VC 的思維,也間接讓自己的策略改觀,除此之外,這些思維站在找工作上也很受用的,也可用在評鑑公司的健康情況。

例如A輪尾之前,要確認事業營運是否持續高成長,像是營業額或是服務使用人數等,用這個概念去看台灣相關的新創,大概可以找到 cloudmosa 是很健康的,整個團隊人數不大(<30人),用戶數年年翻倍,更別說在 remote browser 的領域上也堪稱第一,而公司的大戰場就是更廣域的 mobile browser 領域,一堆科技文在評比 mobile browser 時,肯定都會提提 Puffin Web Browser。

整本書我都在享受 汪华 和 傅盛 提到的策略,雖然越看越有動力,但那些策略就像企業管理一樣,沒那個環境,就沒使出的機會,只能先醒腦一下,在看看 side project 可以在找哪些來試試了。此外,這本書尾聲還提及台灣人創業習慣(還用中國台灣這字眼)跟趨勢科技營運策略(當作傳產)打臉一下 XD 或許,這大概這本書沒翻成繁體進入台灣市場的主因吧?!

有興趣可以翻 Amazon CN 電子書 或是試試 天貓 吧,另外,百度閱讀 也可以線上試讀第一章。

2017年6月15日 星期四

透過 Nginx proxy_pass 架構,進行 Service migration

有一個舊網站已活了數年,改造的方向不外乎提升 SEO、移除不需要的檔案、增加系統安全、架構拆分,或是基本的 Web Framework 的抽換使用等等。對於一個 IoT 產業來說,包袱多多,像是 device 不見得會更新到新版,更別說會跟隨 HTTP 301/302 去取得新資源,甚至新網站的開發還沒辦法一步到位全部切換,只好透過 Nginx proxy_pass 架構去處理相容並扛流量了。

在此使用 upstream 管理舊機器們,並且添加新的 log format 多紀錄 $upstream_addr 資訊以便後續維護:

log_format add_proxy_pass '$remote_addr - $remote_user [$time_local] [=$upstream_addr=] "$request" ' '$status $body_bytes_sent "$http_referer" ' '"$http_user_agent" "$http_x_forwarded_for"';

resolver 8.8.8.8;
upstream oldserver {
hostname1;
hostname2;
hostname3;
}


後續,都是在 nginx server {} 定義範圍下。

更改 log 記錄格式:

access_log  /var/log/nginx/access.log add_proxy_pass;

預期 http client 能處理 HTTP 301/302 的服務位置,給予更佳的 SEO URL:

location ~ old_page\.php$ {
return 301 $scheme://$host/new/page/;
}


對於不能用 HTTP 301/302 的,則改用 proxy_pass 機制:

location ~ ^/old/resource {
proxy_pass http://oldserver$uri;
}


對於,有些文件很清楚要更改內文關鍵字的,可以善用 ngx_http_sub_module:

location /old/resource/file\.json {
proxy_pass http://oldserver$uri;
sub_filter_types *;
sub_filter_once off;
sub_filter '//old.hostname/' '//cdn.hostname/';
}


也可以順順換成 CDN 架構囉。