2019年12月22日 星期日

messenger API 快速回覆

在messenger中,如果只想讓使用者回覆制式的回答,可以用快速回覆的泡泡按鈕,JSON指令如下:

-------------------------------------------------------------------------------------------

{
  "recipient":{
    "id":"<收件人ID>"
  },
  "message":{
    "text": "Here is a quick reply!",
    "quick_replies":[
      {
        "content_type":"text",
        "title":"tag1",
        "payload":"tag1",
      },
      {
        "content_type":"text",
        "title":"tag2",
        "payload":"tag2",
      },
    ]
  }
}
-------------------------------------------------------------------------------------------

https://graph.facebook.com/v2.6/me/messages?access_token=<你的TOKEN>
-------------------------------------------------------------------------------------------









messenger API 開始按鈕

對話要開始前,需要使用者任一句子觸發,機器人才知道要開始工作,但一開始沒有什麼提示訊息,使用者也不知道要講什麼。

在messenger,我們可以設定 開始使用 按鈕,給第一次使用的使用者觸發歡迎句。
LINUX指令:
-----------------------------------------------------------------------------------------------------------------------
curl -H "Content-Type: application/json" --data @get_started.json https://graph.facebook.com/v2.6/me/messenger_profile?access_token=<自己的TOKEN>
------------------------------------------------------------------------------------------------------------------------------
get_started.json檔
------
{
  "get_started":{
    "payload":"開始使用"
  }
}
-----------------------------------------------------------------------------------------------------------------------

晨興第二週週一12/23

西1:12 Giving thanks to the Father, who has qualified you for a share of the allotted portion of the saints in the light;

西2:7 As therefore you have received the Christ, Jesus the Lord, walk in Him, Having been rooted and being built up in Him, and being established in the faith even as you were taught, abounding in thanksgiving.

2019年12月20日 星期五

地球表面距離計算公式

要透過兩組經緯度座標找到地表兩點的距離,必須要用地球表面距離公式計算距離。以下是PHP計算範例:



function getDistance($lat1,$lng1,$lat2,$lng2)
{
$earthRadius = 6367000;//approximate radius of earth in meters

/*
Convert these degrees to radians
to work with the formula
*/

$lat1 = deg2rad($lat1);
$lng1 = deg2rad($lng1);

$lat2 = deg2rad($lat2);
$lng2 = deg2rad($lng2);

/*
Using the
Haversine formula
http://en.wikipedia.org/wiki/Haversine_formula
calculate the distance
*/
$calcLongitude = $lng2 - $lng1;
$calcLatitude = $lat2 - $lat1;
$stepOne = pow( sin( $calcLatitude / 2), 2) + cos($lat1) * cos($lat2) * pow(sin($calcLongitude/2),2);
$stepTwo = 2 * asin(min(1, sqrt($stepOne)));
$calculatedDistance = $earthRadius * $stepTwo;
return round($calculatedDistance);
}

Flask使用心得

直接pip install flask就可以,執行python yourProgram.py,就會開一個server在port 5000,在瀏覽器打網址http://127.0.0.1:5000/yourPath/?gerVar=HelloWorld,就能連到你的程式。



------------------------------------  yourProgram.py  -------------------------------------

from flask import Flask
from flask import request

app = Flask(__name__)

@app.route("/yourPath/") #網址後面的路徑

def yourPath(): #名稱和app.route裡的參數一樣

        return request.args.get('getVar','') # 抓取GET進來的參數,網頁會顯示return的內容

if __name__ == "__main__":
  app.run(debug=True) #若要在網頁上顯示錯誤訊息,則加這一行debug=True

軟體與商業模式專利申請與實務介紹 - 上課心得

軟體專利重點:
  1. 軟體及演算法本身不能申請專利,專利內容需強調在硬體上面執行。
  2. 需有應用說明,實際應用在什麼上面,達到實際的效果,例如使影像畫面更清楚,而不是加快距陣運算的速度。
商業方法重點:
  1. 有關於金融與財務、訂購運送貿易、商務交易之概念,此技術(專利)協助處理商業經濟交易及企業管理之方法。
  2. 商業方法的概念與實施之組合方可申請專利。
  3. 商業方法不能申請專利的情形:
    1. 先佔該方法阻礙市場發展。
    2. 進步性不足(一般人可輕易做到),例如:
      1. 將執行一般工作整理成SOP。
      2. 硬體技術軟體化
      3. 無技術性: 標會、增加鑑賞期、純粹經濟貢獻 
  4. 商業方法可跨足軟體發明,使具備適格性發明。
 台灣軟體專利重點:
  1. 有技術性,解決問題的手段是用到該應用領域的顯著創意。
  2. 例如,將檔案內的資料顯示出來不算發明,但加上關鍵字檢索就算(發明人是第一個想到)。

NAB異常偵測實驗平台的計分程式說明


WiFi人體特徵生物辨識



1.WiFi新技術:探測人體生命特徵
  • MIT開發出Wi-Vi,可以利用WiFi信號追踪在牆另一邊的移動的人體。
  • 利用WiFi信號隔牆測心跳準確率99%
  • 辨識人體輪廓、呼吸
    • 利用心跳和呼吸判斷情緒

2.WiFi辨識生物特徵有關的重要名詞
  • Channel State Information (CSI)
    • 關鍵技術
    • CSI包含WiFi訊號的反射、散佈、衰減等資訊
    • 「WiFi辨識生物特徵」的突破來自CSI可以從消費性WiFi產品上取得
  • through-the-wall (TTW) human detection
    • 隔牆人體偵測
    • WiFi有可以穿透牆壁的優點
  • device-free human detection
    • 不需穿載裝置的人體偵測
    • 例如腦波儀
3.Human Detection
  • 此研究隔牆偵測房間有沒有人(而且可以走動不需靜止),平均準確度高達99%。
  • Zhu, H., Xiao, F., Sun, L., Wang, R., & Yang, P. (2017). R-TTWD: Robust device-free through-the-wall detection of moving human with WiFi. IEEE Journal on Selected Areas in Communications35(5), 1090-1103.

4.偵測睡眠
  • 偵測睡眠姿勢變換
  • 也可以進一步偵測打瞌睡的點頭行為、抖手、抖腳
  • Gu, Y., Zhang, Y., Li, J., Ji, Y., An, X., & Ren, F. (2018). Sleepy: Wireless Channel Data Driven Sleep Monitoring via Commodity WiFi Devices. IEEE Transactions on Big Data.



5. To detect human activity
  • CARM, CSI based human Activity Recognition and Monitoring system
  • youtu.be/FnK4QHj00nk
  • 平均94.8% Accuracy
  • 辨識動作: Running, walking, sitting down, Opening refrigerator, Falling, Boxing, Pushing one hand, Brushing teeth, No activity.
  • Wang, W., Liu, A. X., Shahzad, M., Ling, K., & Lu, S. (2015, September). Understanding and modeling of wifi signal based human activity recognition. In Proceedings of the 21st annual international conference on mobile computing and networking(pp. 65-76). ACM.



6. 搭配Deep Learning的室內定位應用
  • WiFi電波應用在室內定位
  • 此研究加入Deep Learning來加強辨識正確性(但沒有具體寫出準確度)
  • Wang, X., Gao, L., Mao, S., & Pandey, S. (2017). CSI-based fingerprinting for indoor localization: A deep learning approach. IEEE Transactions on Vehicular Technology66(1), 763-776.

























NAB實驗平台使用方法


github.com/numenta/NAB
即時串流資料分析演算法實驗平台


當要加入新的演算法進NAB平台測試時,你的程式必需改成下列格式:

class MyDetector(AnomalyDetector):
 def __init__(self, *args, **kwargs): 
   super(MyDetector, self).__init__(*args, **kwargs)
   ....


 def handleRecord(self, inputData):
   #inputData['timestamp']
   #inputData['value']
   self.recordCount = self.recordCount + 1
   ....
   return (anomalyScore,)



自己原本演算法主程式是放進handleRecord函數裡,但是要改成可以一筆記錄一筆記錄收,handleRecord會被外部
的程式呼叫多次,但每次呼叫只傳一筆記錄,故inputData只有一筆資料的timestamp及value(實際資料簡化成單
一值,兩筆記錄的值越接近則記錄越一樣),而且handleRecord要直接回傳此筆記錄的anomalyScore(異常機率),
但在class裡可以自己設定陣列變數存之前傳進來的記錄。


檔案放在,如同其它detectors:
nab/detectors/MyDetector/MyDetector.py

nab/detectors/MyDetector/_init_.py


/run.py程式碼最下面的地方要加入下列程式,如同其它detectors一樣:

if "MyDetector" in args.detectors:
 from nab.detectors.MyDetector.MyDetector import (MyDetector)


在檔案config/thresholds.json要加入下列的參數,threshold是指anomalyScore大於多少就算異常,此參數會被
--optimize調整(在Command Line執行run.py的參數)

"MyDetector": {
"reward_low_FN_rate": {
"score": 0,
"threshold": 0.9
},
"reward_low_FP_rate": {
"score": 0,
"threshold": 0.9
},
"standard": {
"score": 0,
"threshold": 0.9
}
},



Anomaly Detection Model(異常偵測模型)

此篇是介紹我的Anomaly Detection Model(異常偵測模型)的資料結構,用來計算新的資料的正常值(越大越正常),資料結構主要是用Table,這樣就不需要每次都從原始資料抓取相關資料來計算正常值,加快計算速度。



模型的Table如下表所示,第一欄是時間塊,將資料的時間以區塊的方式aggregate(去除日期,只保留一天的哪個時間區塊),下表是1分鐘一個區塊,例00:05:23 歸類在5。

第二欄是資料值區塊,值相同的越多越正常,但通常會有點差距,我們實驗的時候,值是浮點數,故將其整數相同的aggregate在一起。通常有很多不同的資料屬性(身高、體重、顏色 等),這裡簡化到一個值。

第三欄Count是發生次數,同Time Block及同Value Block出現幾次。

Time BlockValue BlockCount
0
5222
5253
1440



計算時,依以下公式,將表中每列,根據和新資料的差距,加權Count值再合併,成為Normal Score(正常程度),v0和t0是新資料的值區塊和時間區塊,Reduce是一個自訂陣列,依t0-t的差距,給序衰減值,差距越大,衰減越多。




Reduce陣列的內容通常像,1, 0.9, 0.8, 0.7, 0, ...., 0, 0.7, 0.8, 0.9,以上表的例子,Reduce陣列長度是1440,同時間區塊的數量。如此的內容,也代表遇到Reduce[t0-t]==0的情況不用計算。





















Hierarchical Temporal Memory (HTM) for anomaly detection

HTM 是一種理論架構,適用於神經網路皮層(等同 腦皮層)的循序學習,也是一種real time技術,已經被證明成功運用在預測任務上。HTM網路會持續學習並model輸入資料的時間與空間特徵。



下圖秀出如何例用HTM來偵測異常: 輸入資料向量xt (t表第幾個時間點),HTM會輸出兩個值a(xt)及pi(xt),Prediction error模組會輸出預測誤差值st,Anomaly likelihood模組輸出此筆資料是異常的可能性。


下圖秀出上圖的HTM模組的細部內容,輸入的xt送到Encoder模組裡1 ,然後再送去作稀疏空間池化(Spatial pooler模組),結果產生一稀疏二元向量a(xt)來代表目前輸入xt。Sequence memory模組是整個HTM的重點,它是用來model a(xt)的時序規則,所以pi(xt)代表預測下一個輸入,也就是猜測a(x(t+1))的值。
 [1] S. Purdy, Encoding Data for HTM Systems, arXiv. (2016) arXiv: 1602.05925 [cs.NE].

HTM sequence memory 是由一層HTM神經元群組成,並以columns集合的方式呈現,如下圖,它model高階序列(有長期關係的序列),它由兩個稀疏象徵物呈現(下第三張圖)。目前輸入xt和之前的輸入....,xt-3,...xt-1,被同時以"隨時更新的稀疏象徵物"方式 encode,此網路就用此象徵物預測未來的sparse vector。



下圖秀出用稀疏象徵物來表示時序規則及弄清楚有長期關係的序列。當網路收到下個輸入,它利用預測的輸入和真實輸入的差異來更新神經元模型。






























初步實驗 進出時間異常演算法 的正確性

我在下面這篇paper找到測試 "異常資料偵測演算法" 的Benchmark,用其中一個檔案來測自己的演算法,結果完美找出異常的部份。

參考文獻1

資料檔是下面這個,上一層目錄還有很多資料集

參考文獻2

異常答案:

參考文獻3

 "artificialWithAnomaly/art_daily_jumpsup.csv":
    [
        "2014-04-11 09:00:00.000000"
    ],

將此檔的Value畫成plot後,可以清楚的看到有一部份異常,這部份是4/11 09:00開始,到同天17:55,是一非常明顯的異常:



計算出來的結果,排序在最前面的,都是最異常的資料:



另外有一波次異常,在同天4/11 18:00~18:55,areaTimeWeight從9.x開始,僅次於主異常:
除了次異常,上圖也有找出一些areaTimeWeight偏低的資料,這些較4/11的資料,異常程度比較不明顯,但也可以研究是否有異常。  

初步實驗成功!



















The Numenta Anomaly Benchmark(NAB)

NAB軟體包含了實驗用串流Dataset及實驗平台,Dataset包含58個有時序的Data files,有些是人工做出來的Data files,裡面包含異常值。Real Data的files包含AWS server metrics、Twitter volume、廣告點擊量測、交通 等等,



 實驗平台可以給各種方法分數,如下表,除了標準評分方式,還對False Positive(FP)及False Negative(FN)另外評分。

DetectorStandard ProfileReward Low FPReward Low FN
Perfect100.0100.0100.0
Numenta HTM70.5-69.762.6-61.775.2-74.2
CAD OSE69.967.073.2
KNN CAD58.043.464.8
Relative Entropy54.647.658.8
Twitter ADVec v1.0.047.133.653.5
Windowed Gaussian39.620.947.4
Etsy Skyline35.727.144.5
Bayesian Changepoint17.73.232.2
EXPoSE16.43.226.9
Random11.01.219.5
Null0.00.00.0

NAB framework可在Github上找到













H2O - autoencoder

H2O是一個支援python的資料分析平台,提供python  import套件,有機器學習及平行計算的API。我參考"Zocca, V., 「Python深度學習」, 2017年12月"的書,以H2O作異常偵測,以下解釋如何用H2O的autoencoder作:

安裝H2O時,需要有JAVA 8.0 JDK,太新的版本不行(例如10)。

需以下pip install套件:
grip
colorama
future
tabulate
requests
wheel
書中的範例是用來偵測MNIST異常數字辨識,程式碼如下:

import h2o
h2o.init()
%matplotlib inline
import pandas as pd
from matplotlib import cm
import matplotlib.pyplot as plt
import numpy as np
from pylab import rcParams
rcParams['figure.figsize'] = 20, 12
from six.moves import range
train_with_label = h2o.import_file("http://h2o-public-test-data.s3.amazonaws.com/bigdata/laptop/mnist/train.csv.gz")
test_with_label = h2o.import_file("http://h2o-public-test-data.s3.amazonaws.com/bigdata/laptop/mnist/test.csv.gz")
predictors = list(range(0,784))
train = train_with_label[predictors]
test = test_with_label[predictors]
from h2o.estimators.deeplearning import H2OAutoEncoderEstimator
model = H2OAutoEncoderEstimator(activation="Tanh", hidden=[20], ignore_const_cols = False, epochs=1)
model.train(x=predictors, training_frame=train)
test_rec_error = model.anomaly(test)
test_rec_error.describe()
test_rec_error_df = test_rec_error.as_data_frame()
test_rec_error_df['id'] = test_rec_error_df.index
test_rec_error_df.plot(kind='scatter', x='id',y='Reconstruction.MSE')

最後輸出如下的圖,秀出異常的資料。



如何增進聽說讀寫能力

此篇是在線上課程的心得,課名"如何增進聽說讀寫能力"。
  1. 讀有興趣的英文書
  2. 找好用的英英字典(有例句、同義字、反義字、用法、是正面或負面字,APP)
  3. 嚐試用同意不同字
  4. 台灣人的英文文法,對美國人來說是意思。
  5. 養成每天背3個單字的習慣,不會的單字查用法例句,記在筆記本上。
  6. 自言自語說英文,或聽MP3
  7. 英文速讀,用手幫助,眼球跟著手走
  8. 看出關鍵字,不需整篇文章都看清楚
  9. 利用轉接詞預測內容
  10. 描述事實後舉例說明For instance
  11. 轉接詞描述順序: first, third, next, still, afterward, subsequently, finally, previously, simultaneously, concurrently, consequently.
  12. 轉接詞加述: besides, moreover, further, more, in addition, also, equally important.
  13. 轉接詞因果: because, as a result, consequently, thus, therefore, so, then, since, for the reason of.
  14. 轉接詞相對: but, yet, on the one hand, on the other hand, however, nevertheless, on the contrary, by comparison, compared to, although, in contrast, while, meanwhile, as opposed to, in spite, despite.
  15. 轉接詞強調: definitely, extremely, obviously, in fact, indeed, in any case, positively, absolutely, unquestionably, certainly, without a doubt, perennially, eternally, emphatically, naturally.
  16. 轉接詞舉例: for example, for instance, in this case, in another case, in this situation, take the case of, take...for an example, such as.
  17. 轉接詞總結: in brief, on the whole, summing up, in conclusion, hence, therefore, consequently, overall.
  18. 從轉接詞前後文猜出後文或前文不認識的字
  19. 六個文章寫作步驟:
    1. understand topic. what to write.
    2. Brainstorming: write down ideas in simple english
    3. select ideas. organize. plan. first paragraph, second paragraph
    4. make simple sentences with your idea.
    5. relations between two sentences. transition words.
    6. check
  20. 常見動詞(查到完全會): be, do, come, go, get, have, give, carry, carch, keep, male, take.
  21. TOEIC有on line作文課,可以幫你改作文
  22. 常reading,看到好的寫作手法,學起來。

fastText - Word representation

fastText可以將Word轉成Vector,供機器學習輸入使用。轉成Vector 也還能保留類推性及語意關係。

fastText的轉換指令如下(使用skipgram model):

./fasttext skipgram -input data/fil9 -output result/fil9


轉換過程花了很久時間,機器是用Devbox10,文本檔案是681MB,感覺效率不是很好。

輸出的 fil9.vec檔案包含每個字的向量,如下範例:


the 0.052022 -0.062025 -0.0061274 0.10942 ....

-------------------------------------------------

除了skipgram,還有CBOW (Continuous-Bag-Of-Words) model。skipgram在預測時,是隨機選一個靠近的字來看目標字的機率; 而CBOW預測時是用固定範圍內、週圍的字來預測目標。如下圖:














fastText - text classification

因為VCA有用到fasttext的方法,所以就去fasttext.cc下載來玩看看,先嚐試照Tutorial練習。

第一個練習是Text classification,訓練出可以分類句子屬於哪一個Label的分類器。

資料集是15404筆有Label的句子,範例資料如下:

__label__sauce __label__cheese How much does potato starch affect a cheese sauce recipe?

Label標記的方式是,__label__標記,上例有兩個Label。

訓練指令如下,訓練資料cooking.train,指定model主檔名model_cooking:

./fasttext supervised -input cooking.train -output model_cooking

使用model時用下列指令,model_cooking.bin是分類器,"-" 代表由鍵盤輸入測試句:

./fasttext predict model_cooking.bin -

測試時,我輸入:

Which baking dish is best to bake a banana bread ?

它會回傳"__label__baking"

以測試資料集測試model,輸入下列的指令:
./fasttext test model_cooking.bin cooking.valid

回傳結果:

N 3000                                    <--- p="">P@1 0.539                              <--- p="" precision="">R@1 0.233                              <--- p="" recall="">Number of examples: 3000    <--- p="">



Python DataFrame轉成list 比生成式更快的方法

DataFrame要轉成輸出格式,可以用apply及list一次產生, 比用生成式[ row['...'] for i,row in df.iterrows()]快很多。



    df_no_match_io['desc'] = ''
    df_no_match_io['desc'] = df_no_match_io.apply( \
            lambda row: [ {'date':row['showDate'] \
                           , 'card_no':row['cardno'] \
                           , 'dept':row['dep'] \
                           , 'inspect':getDesc2(row)}] \
            ,axis=1) 
    returnResult = list(df_no_match_io['desc'])

Python C如何觸發Exception

使用C寫Python的API時,若想用Exception的方式回傳錯誤,可以在C的程式裡加入



PyErr_SetString(PyExc_StandardError,"ERROR: Unknown Feature ID.");

Py_RETURN_NONE;



PyExc_StandardError是觸發StandardError,其後是錯誤訊息。

Python的程式



try:

  Capi();

except StandardError as e:

  print(str(e));



python就可以捕抓到Exception,並讀出錯誤訊息。

Master Tree for Active Learning

最近在看Active Learning的paper,標題是Active Learning through density clustering,此篇利用Master Tree來挑選請人label的樣本,以下是研究build Master Tree演算法的心得:



此演算法的內容如Algorithm 2,輸入的U及C所組成的S如Table 1,d_c是群空間距離的門檻值,要自訂。輸出包含Ro陣列,Delta陣列,Master Tree陣列; Ro是每個樣本的鄰居數,鄰居的距離要小於d_c才算; Delta是每個樣本的最短距離,從該樣本的鄰居中,且Ro比該樣本大,但距離是最近的; Master Tree是記錄該樣本的parent,parent是符合Delta條件的鄰居。





距離是用Manhattan距離,Line 2 to 9計算Ro值。Line 10排序樣本,由大Ro到小Ro,O_j代表排名j的樣本號。Line 11 to 19計算符合Delta條件的最短距離,並記錄在Master Tree陣列裡。





Table 1,U是樣本編號,中間四個欄位是每個樣本的屬性,又叫C,class欄是分在哪一群,又叫d。
















Density Cluster for Active Learning

輸入: Master tree陣列,使用者自訂群數k

輸出:群中心陣列ct,塊資訊 二維陣列bl (第二維是動態)

Line 2根據之前的Algo 2 buildMasterTree,取得Ro,然後建立ord排序。

Line 3~4 要找出gamma最大的前k筆index,準備作為群中心

Line 5 的l是Label的縮寫,用來記錄分群的結果。

Line 6~8  Step 1的loop,是要先把群中心編號並Label,並把中心點的Index先放入bl的第i群。

Line 9~13 Step 2,是將未Label的樣本,但parent已經Label了,則依Master Tree的結果,Label成和parent node一樣的Label,並將樣本index放到同一個群的bl。








Active Learning through density clustering演算法說明

輸入: U及C所組成的S如Table 1,N是請人Label的最大樣本數。

輸出: d(x)是對每個樣本Label的結果。

Line 1 初始化,UIII是全部未Label的樣本,UII是電腦自己Label(根據人Label的樣本),UI是要請人Label的樣本。

Line 2 是用buildMasterTree演算法得到Ro陣列, 最短距離delta陣列, Master Tree陣列,在另一篇有解說此演算法。

Line 3~15 是要教和分類可確定Label的同質群( pure blocks)

  Line 3 的k是分群數,分到UI的樣本數大於等於N或UIII的樣本Label完為止。

  Line 4 使用densityCluster演算法得到群中心ct陣列及群清單bl陣列。在另一篇有解說此演算法。

  Line 5 選出影響力大的樣本請人Label

  Line 6 將上一行選出的樣本加入UI,並從UIII中移出。

  Line 8~13 是依序檢查bl (檢查每一群),若bli未全Label,且已Label的數量大於等於根號N,且已Label的樣本Label一致,則將bli未Label的樣本Label成和已Label一樣。

  Line 14 將上一個Loop,樣本是用Label相同Label的方式的,加入到UII,並從UIII移出。

  Line 16~22 如果 UIII沒有全部用完,依序抓bli中未Label的樣本,用Standard voting來Label。












用numba的vectorize加速python計算

用python的for-loop處理工作時,效率很差是眾所皆知,這時可以用numba的JIT來加速,但除此之外,還可以更進一步使用vectorize來加速,vectorize顧名思意是向量式處理資料,我們必須把資料排成向量或距陣,一個一個丟到vectorize函數處理,如下函數:
@vectorize(["float32(uint32,float32,uint16,uint8,uint8,uint16,uint8,uint8)"])
def mymul2(count, timeAtt, dep, io, door, dep2, io2, door2):
  count *= timeAtt
  if dep != dep2:
      count *= 0.5
  if io != io2:
      count *= 0.5
  if door != door2:
      count *= 0.5
  return count
使用函數時:
returnVec = mymul2(count, timeAtt, np.full(len(dep),dep[0]),np.full(len(io),io[0]) , np.full(len(door),door[0]), dep2, io2, door2)
所有傳入的參數,向量長度都一樣,其中np.full(len(dep),dep[0])是因為要把第一個值和所有值比較,故寫成這種型式。

用numba的vectorize加速python計算

用python的for-loop處理工作時,效率很差是眾所皆知,這時可以用numba的JIT來加速,但除此之外,還可以更進一步使用vectorize來加速,vectorize顧名思意是向量式處理資料,我們必須把資料排成向量或距陣,一個一個丟到vectorize函數處理,如下函數:
@vectorize(["float32(uint32,float32,uint16,uint8,uint8,uint16,uint8,uint8)"])
def mymul2(count, timeAtt, dep, io, door, dep2, io2, door2):
  count *= timeAtt
  if dep != dep2:
      count *= 0.5
  if io != io2:
      count *= 0.5
  if door != door2:
      count *= 0.5
  return count
使用函數時:
returnVec = mymul2(count, timeAtt, np.full(len(dep),dep[0]),np.full(len(io),io[0]) , np.full(len(door),door[0]), dep2, io2, door2)
所有傳入的參數,向量長度都一樣,其中np.full(len(dep),dep[0])是因為要把第一個值和所有值比較,故寫成這種型式。

Python小技巧

這篇記一些沒用過或不常用的Python技巧,這些都是我之前沒用過,看書才知道的用法。

#函數預設list會被保留
def f(r=[]):
r.append(2)
f()#[2]
f()#[2,2]
#
None常數

#生成器
[n for n in range(6) if n % 2 == 1]
#若帽號下面沒有程式就用pass
def do_nothing():
pass
#製作產生器物件
(n for n in range(6))
#for也有else
for ....:
break
else: #break就不會執行這一段
#while也有else
while ....:
break
else: #break就不會執行這一段
#生成字典
w = 'letters'
{l: w.count(l) for l in w}
#
def f():
'''
說明文字
'''

離群資料

當要分析公司內部進出記錄時,我們並不了解每個欄及每個值的意思,例如我們不知道不同部門之間的關聯、不知道部門這個欄名是否和我們認知是一樣(它可能是一道門),使得我們在宣告向量空間,把每個部門編號進feature vector,vector的距離並沒有任何意義,例如部門1和部門2的向量距離比部門1到部門3短,對我們沒有幫助。

因為對我們真正有意義的是,該列資料的部門和其它列資料有沒有一樣,故當我們宣告一個向量空間要去找離群資料時,並不是直接算向量距離,而是直接用0或1代表距離,0表同一格,1表不同格。



如下圖,最下面的紅色離群資料點和上方其它資料點,在這個維度(高度)的距離都是1,無論是在最上面的格子或最下面。

Builder Pattern

我作了一個練習,以組裝電腦的觀念設計一builder pattern,builder pattern的特別的地方是適用在建構複雜的物件,builder可以有很多種,也方便替換builder。client不需要知道product細節。

Client:
買電腦

Director:
pcBuilder = new PcBuilder()
if "miniPC" then
  pc =  miniPcBuilder.setCase("XPC shuttle Z95")
       .setCPU("Intel i7 7900k")
       .setMem("Apacer DDR4 2400 32GB")
       .setDPcard("Nvidia 1050 Ti")
       .setMonitor("BenQ 24")
       .setKeyboard("Microsoft natural KB+mouse")
       .build()
    

if "genPC" then
  pc =  PcBuilder.setCase("酷碼 CM 690 III(網孔版)")
    .setPower("be quiet! E10-600W 80+金牌")
    .setMB("華碩 X99-DELUXE/U3.1")
       .setCPU("Intel I7-5820K")
       .setMem("美光 8G*4 DDR4-2400")
       .setDPcard("EVGA GTX750TI 2GB")
       .setMonitor("ASUS 24")
       .setKeyboard("羅技 MK200")
       .setMouse("羅技M3000")
       .build()


return pc

PcBuilder:
pc = new PC();
setCase(case)
pc.case = case
return this
setPower(power)
pc.power = power
return this
setMB(MB)
pc.MB = MB
return this
setCPU(CPU)
pc.CPU = CPU
return this
setMem(Mem)
pc.Mem = Mem
return this
setDPcard(DPcard)
pc.DPcard = DPcard
return this
setMonitor(Monitor)
pc.Monitor = Monitor
return this
setKeyboard(Keyboard)
pc.Keyboard = Keyboard
return this
setMouse(Mouse)
pc.Mouse = Mouse
return this
build()
return pc

miniPcBuilder extend PcBuilder:
pc = new PC();
setCase(case)
pc.case = case
return this
setCPU(CPU)
check_CPU_fit_the_case()
pc.CPU = CPU
return this
setMem(Mem)
check_MEM_fit_the_case()
pc.Mem = Mem
return this
setDPcard(DPcard)
check_DPcard_fit_the_case()
pc.DPcard = DPcard
return this
setMonitor(Monitor)
check_Monitor_fit_the_DPcard()
pc.Monitor = Monitor
return this
setKeyboard(Keyboard)
pc.Keyboard = Keyboard
return this
setMouse(Mouse)
pc.Mouse = Mouse
return this
build()
return pc


 PC:
  case
  power
  MB
  CPU
  Mem
  DPcard
  Monitor
  Keyboard

客戶Linux語系與python中文編碼問題SOP

原因

本篇是因為客戶執行USB驗證時,執行到usb_license.getClientName(101),程式出現錯誤訊息:
UnicodeEncodeError: 'ascii' codec can't encode characters ....
原因是客戶的Linux語系設定有問題,因為回傳的是"某某單位"中文字的UTF8的16進位編碼,python會使用系統預設編碼來解釋讀進來的字串,故解碼失敗。若在Linux執行locale,出現:
locale: Cannot set LC_CTYPE to default locale: No such file or directory
則python會使用自己的ascii編碼,故中文一定解不出來。

方法

本篇是完整修改Linux語系,重開機也不會還原,若只要修改當下運作時的語系,請執行LANG=zh_TW.UTF-8LC_CTYPE=zh_TW.UTF-8
  1. sudo vim /var/lib/locales/supported.d/en <-- br="" en="" local="">新增放置在第一行
    zh_TW.UTF-8 UTF-8 <-- br="">(en_US.UTF-8 UTF-8 <-- p="">
  2. 執行locale-gen
    (如果新加的語系在本機上沒有,就需要執行,例如原本是預設英文en_US.UTF-8,新增zh_TW.UTF-8)
  3. vim /etc/default/locale
    修改LANG=zh_TW.UTF-8

其它

執行locale看看,若前三行出現:
locale: Cannot set LC_CTYPE to default locale: No such file or directory
,表示第二步驟沒執行,或第一步驟的語系設定打錯。
本篇測試的環境是Ubuntu 16.04

Kmean演算法

今天S提到有一家鞋子代工公司希望我們能幫它們多間工廠,設計一個人工智慧方法,能依照員工上下班打卡紀錄,偵測異常狀況。我上網搜尋到微軟的網站有在討論abnormal data的問題,如下,內容是利用Kmean演算法來做,故我去找kMean的資料來看。
https://msdn.microsoft.com/en-us/magazine/jj891054.aspx
Kmean的過程是:
  1. 從N個向量隨機選取K個向量作為分群中心,K個群。
  2. 對剩餘的向量,測量到K個群中心的距離,並歸類到最近的群。
  3. 重新計算每個群的中心。
  4. 重覆1~3步驟,直到新的群中心和舊的相等,或小於Threshold。

Kmean的缺點:
  1. 中心點的選擇影響演算法效率,容易局部最佳化。
  2. 需事先設定K數,必需靠經驗。
  3. 易受異常偏離資料影響,造成群中心不正常偏離。

進出記錄配對

最近的case,需要分析log記錄中的進出刷卡記錄,但因為記錄是進去一筆,出來一筆,然後多個使用者混在一個檔案,故需要寫一個配對的程式,將每個使用者的進出記錄配對起來,才能分析進出的間隔時間,並過濾出只有進去或只有出去的不完整記錄。





















python平行計算及共用變數

最近案子要分析log資料,寫python程式的過程發現pandas.dataframe.apply() 不會自動平行計算,使得各別處理60萬筆資料時,只有一個CPU核心在跑,雖然給客戶的軟體不需要平行計算,但我自己在分析資料時,必須用平行計算來減少時間,故上網查資料研究出平行的方法。下列程式將平行要做的事情放入f函數的定義。


import multiprocessing as mp
def f(x,y):
return x*x*y

#一定要if main這一行,平行計算時會呼叫此主程式檔案,載入函數定義( f() ),若無,每個process都會重跑main下的程式
if __name__ == '__main__':
numCores = 7 #要使用的核心數,我的CPU有8核心,留一個給作業系統用,不然在跑分析時,電腦不能做其它事
y=4 #讓每個process共用的變數,實際程式是一個60萬列的dataframe變數
num_of_rows = 600000
with mp.Pool(numCores) as p:
print(p.starmap(f, [(x,y) for x in range(num_of_rows) ]))

分析公司進出記錄原則

當要分析公司內部進出記錄,我們並不了解每欄每個類別值的意思,例如我們不知道不同部門之間的關聯,使得我們在宣告向量空間,把每個部門編號進feature vector,vector的距離並沒有任何意義,部門1和部門2的向量距離比部門3

python適合向量計算

之前寫工廠進出日誌配對的python程式,工廠日誌的進出是不同筆記錄,進去刷一筆,出來刷一筆,故需要配對,找出只有刷進沒有刷出的,或只有刷出沒有刷進的。但問題在之前寫的程式太慢,因為是用for loop從第一筆往後掃描配對(已經按時間排序好),python在處理距陣運算或兩筆超長向量互相比較很快,但for loop就超慢,故我再將程式改成向量比較方式,使得1.3Mega筆資料只需數秒就比較完(若用for loop約需10倍的時間)。

#資料表df先按時間排序,再按卡號排序
df = df.sort_values(by='origitime').sort_values(by='cardno',kind='mergesort')
#將進出欄,附加日期和卡號,從df資料表複製成一向量a
a = np.array(df[['io','date','cardno']])
#將進出欄,附加日期和卡號,複製成一向量b,但從第二列開始複製,最後再加一列0,湊成和a的維度一樣
b = np.array(df[['io','date','cardno']].iloc[1:,:])
b = np.append(b,[[0,0,0]],axis=0)
#作Boolean計算,a每一維元素是否進,b每一維元素是否出,a和b的同維元素其它資料是否相等,最後結果是Boolean向量
result = (a[:,0] == 1) & (b[:,0] == 2) & (a[:,1] == b[:,1]) & (a[:,2] == b[:,2])
#result的後一個值和前一個值作or計算,但用向量or
result2 = result[1:] | result[:-1]
#剛才的向量or,第一個值無法和前一個值計算,故直接原狀態補進來
df['result'] = result[0]
#將剛才的向量or結果放回去資料表df,從第2筆記錄開始放。
df['result'].iloc[1:] = result2
#df['result']結果是True的該筆資料代表可以成功配對,False代表不行。

2019年12月19日 星期四

Markov Decision Process(MDP)

Example: Grid World












  • A maze-like problem
    • The agent lives in a grid
    • Walls block the agent’s path
  • Noisy movement: actions do not always go as planned
    • 80% of the time, the action North takes the agent North
      (if there is no wall there)
    • 10% of the time, North takes the agent West; 10% East
    • If there is a wall in the direction the agent would have been taken, the agent stays put
  • The agent receives rewards each time step
    • Small punishment each step (negative reward)
    • Big rewards come at the end states
  • Goal: maximize sum of rewards
----------------------------------------------------------------------------------------------
  • An MDP is defined by:
    • A set of states s Î S
    • A set of actions a Î A
    • A transition function T(s, a, s’)
    • Probability that a from s leads to s’, i.e., P(s’| s, a)
    • Also called the model or the dynamics
    • A reward function R(s, a, s’)
    • Sometimes just R(s) or R(s’)
    • A start state
    • terminal state (optional)
  • MDPs are non-deterministic search problems
    • One way to solve them is with expectimax search
    • We’ll have a new tool soon
----------------------------------------------------------------------------------------------
Value Iteration













Reinforcement learning的概念

Reinforcement learning的概念可以用下列兩個例子說明:

The Big Bang Theory(生活大爆炸)第三季第三集(youtube上有,關鍵字Positive reinforcement)

Positive reinforcement
Penny幫Sheldon收盤子
Penny差點坐到Sheldon的專屬位置
Sheldon不喜歡Penny講的蠢話
Penny準備去別的地方講電話
Leonard發現Sheldon正在用正強化訓練Leonard的女朋友,做出Sheldon認為對的行為。
Negative reinforcement (punishment)
Sheldon對Leonard噴水(因Leonard禁止Sheldon訓練他的女朋友)。

B.F. Skinner - pigeon turn (youtube上有)

也叫作operant conditioning (操作制約) ,Skinner的實驗是基於RL的方法訓練一隻鴿子能向左轉一圈。

他準備一隻飢餓的鴿子,一開始鴿子會亂動,當鴿子轉向左邊,Skinner就給它食物做為Reward,強化它的行為,過幾次,鴿子就能向士轉一圈,完成Reinforcement Learning。

這種實驗也類似"巴夫洛夫的狗"。

------------------------------------------------------------------------------------------------------------------------

RL是機器學習中的一派,但是來自於心理學的行為理論(Behaviorist)。在DRL火了之前,資工系學不太到這種東西,其它科系有開"最佳化控制理論"課程的學得到。

RL最特別的地方是Reward的元素,RL演算法只是為了找到最大的累積Reward,RL不需要像ANN(Artificial Neural Network)、DNN(Deep Neural Network)、SVM(Support Vector Machine)去做分類,也不需要像Unsupervised learning去分群,這是RL跟其它機器學習方法最大的不同。

RL的代表演算法有 MDP(Markov Decision Process)和POMDP (Partial Observable MDP) 。

C的include檔不能存取主檔的字串

我將_getCertInfo()搬到document.c(被拿來給主檔include)後,結果_getCertInfo()裡的_get_uuid()回傳的字串,不能被_getCertInfo()存取,"Cannot access memory..."。_get_uuid()在license.c(主檔)裡。

疑似在license.c(主檔)產生的記憶體空間,不能被include的檔案使用。

C的字串空間

C的字串空間要在global的地方宣告,然後才能在各個函數裡面用,如果在local宣告,其它函數存取會發生illegal memory access.

模組化C程式

Other: 對C作模組化(分出很多.h和.c的檔案),方便日後debug

為避免日後無法和同事的程式碼merge,先暫緩修改程式碼,改先看懂原本的程式碼。

但拆出程式碼後,反而產生bug,目前最麻煩的是,在不同檔案的函數回傳的字串,會因為該字串的記憶體空間是在該檔案內宣告,無法回傳給其它檔案的函數使用,會變成illegal memory access。跟python的C compile語法有關,它用的gcc compile語法會設定最佳化。

Tensorflow serving GPU+Docker版懶人包

Tensorflow serving GPU+Docker版懶人包 (by Aug) 在Shareman的下列路徑: M300\VCA\Tensorflow\003_Docker_with_TensorServing\tensor_serving_Docker.tbz

執行下列安裝指令就能完成安裝:

sudo nvidia-docker build -t tensor_serving -f Dockerfile .
sudo nvidia-docker run -it -p 8888:8888 tensor_serving
---------------------------------------------------------------------------
測試執行 bash ./run_example.sh

messenger API 開始按鈕



對話要開始前,需要使用者任一句子觸發,機器人才知道要開始工作,但一開始沒有什麼提示訊息,使用者也不知道要講什麼。

在messenger,我們可以設定 開始使用 按鈕,給第一次使用的使用者觸發歡迎句。
LINUX指令:
-----------------------------------------------------------------------------------------------------------------------
curl -H "Content-Type: application/json" --data @get_started.json https://graph.facebook.com/v2.6/me/messenger_profile?access_token=<自己的TOKEN>
------------------------------------------------------------------------------------------------------------------------------
get_started.json檔
------
{
  "get_started":{
    "payload":"開始使用"
  }
}
-----------------------------------------------------------------------------------------------------------------------

messenger取得用戶GPS位置


本篇介紹Messenger API取得用戶GPS位置的功能。取得GPS位置可以讓我們提供在地化的服務,例如高鐵訂票就不用使用者輸入起始站。
1. 傳送下列JSON指令給使用者,會產生如圖的快送回覆按鈕。下列指令是用windows版的CURL傳送JSON,請改成你的接收者ID,換成你的權杖。接收者ID可以從之前的介紹的webhook.txt取得。
D:\curl\bin\curl -H "Content-Type: application/json" -d "{ \"recipient\":{ \"id\":\"\" }, \"message\":{ \"text\": \"Here is a quick reply!\", \"quick_replies\":[ { \"content_type\":\"location\" } ] }}" https://graph.facebook.com/v2.6/me/messages?access_token=

2. 點下"傳送目前位置"的按鈕後,會出現MAP。



3. 前面確定位置後,會回傳座標給webhook。
webhook.php
$raw = file_get_contents('php://input'); rewrite('webhooks.txt', "\n\n\n".$raw ."\n\n"); $data = json_decode($raw, true); print_r($data); if( $data['object'] == 'page'){ foreach($data['entry'] as $entry) { foreach($entry['messaging'] as $messaging) { rewrite('webhooks.txt', '[sender][id] ='.$messaging['sender']['id']."\n"); rewrite('webhooks.txt', '[message][text] ='.$messaging['message']['text']."\n"); if(!empty($messaging['message']['text'])){ sendText($messaging['sender']['id'], 'Text received, echo: '.$messaging['message']['text']); } else if(!empty($messaging['message']['attachments'][0]['payload']['coordinates'])){ $replyText ='Coordinates: ' .$messaging['message']['attachments'][0]['payload']['coordinates']['lat'] .',' .$messaging['message']['attachments'][0]['payload']['coordinates']['long']; sendText($messaging['sender']['id'], $replyText); } } } }











IKEA吊櫃廚櫃

 好不容易裝好IKEA買來的吊櫃,花了三天。 從組裝,鑽牆,上牆調水平,累死我了。