MCU單晶片韌體設計

2017年10月20日 星期五

為什麼要對特徵標準化(feature normalization)?




為什麼在做clustering 或Classification  常會將Feature做Normalize, 但為什麼要呢?
google了些關於正規化(normalize)的資料 都只有公式和分布狀態的資訊 但我疑惑的點是在比較資料時 但還是不懂為什麼要正規化呢?

z-score:
標準化(normalize)就是去掉不同Feature單位的影響. 所以標準化只改變尺度(Scale)和中心點(平移)但Shape 不變

所以對每一個feature 都做正規化後,Feature 之間都是"unit variance", 每一個Feature 都具有相同的scale。例如: 用身高的數值都比眼睛視力的數值大, 正規化後都變具有相同的scale

Feature具有相同scale , 對於d loss/d w 就不會有差異, 否則scale較大的, 它的w對Loss 影響較大


https://en.wikipedia.org/wiki/Feature_scaling

===================================
Normalization 的程序:








2017年10月17日 星期二

Python 操控 S4A 透過通訊協定來下手

Python 操控 S4A 透過通訊協定來下手

S4A Project 是一個有趣的專案,讓Scratch 也可以操作Arduino。 要達到這樣的功能,Arduino需燒入S4A的官方韌體。
在這邊要說的是,其實不用 scratch 也可以直接操作帶有 S4A 韌體的板子,只要搞清楚其中的連線是如何進行的就可以。這邊用 Python 的程式碼來控制 S4A 的板子。

通訊協定封包格式

其實 S4A 的板子在連線之後是透過 UART 介面來收發封包進行連線和操作的。所以我們可以使用邏輯分析儀來進行UART封包的分析:

取樣之後會發現 S4A 板每 16 ms 就發送一個封包給 scratch,而 scratch 會每85ms就回一個封包給 S4A 板子。

我們先將S4A板子傳給 scratch 的封包放大來看,可以看到裡面的傳遞數值的情形:

可以知道每個封包帶有 16 bytes,而S4A封包的設計上是用一個 high byte 和 一個low byte 共兩個 byte 組成一個 Channel 的資訊。所以可以知道,S4A 每16ms送一次的封包之中就帶有8個channel的資訊,這就符合 scratch 上在連線時所看到的即時channel資訊(analog x 6 和 digit x 2)。也就是 s4a每16ms就會更新一次所有 輸入pin腳(共8個)的資訊。
將目光轉移到 scratch 傳給 s4a 板子的封包。

可以知道每個封包帶有 20 bytes,所以 S4A 每 85ms 送一次的封包之中就帶有10個channel的資訊,也就是 scratch 每 85ms 就要更新一次所有 輸出 pin腳(共20個)的資訊。而這10個channel所代表的輸出資訊表如下。表格中有所有輸出入channel的定義和封包格式。其中我們將 motoduino所使用到用來控制車輪的輸出項標示出來。

不過光看表格其實很難理解所,每2byte所組成的 channel 資訊的格式是怎麼樣的,所以下我們整理了一下,以方便理解。

如上圖所示,每個 channel 的資訊是由兩個值: Channel ID 和 Value 所組成。
Channel ID 用來表示指定的輸出入 pin 腳號碼,以 s4a 板子傳遞給 scratch 來說,channel ID 為 "2" ,二進位表示 "0010",此二進位值要填進去上圖的4格紅色格子中。
Value 用來表示指定 pin 腳的數值,如果是數位輸出入其值為1或0,如果是pwm輸出時其值為0~255,如果是類比輸入時其值為0~1023。將數值轉換為二進位時最多會使用到10個bit,將這10bit分成前三格 後七格 的形式分別填入 high-byte 的右邊三格綠色格子和low-byte的右邊7個格子。
而 high byte 的最左邊的一格格子會固字填入 "1" ,low byte 的最左邊格子會固定填入 "0",這樣的話,我們在解析封包的時候才不會把 high-byte 和 low-byte 搞錯。


用Python 程式碼來做編碼和解碼的動作

知道這樣的規則之後,我們就可以用一小段程式碼寫出編解碼的函示:
def pack_to_data(data):
    dev_id = (data[0] & 0b01111000) >> 3
    dev_val = ((data[0] & 0b00000111 ) << 7) | (data[1] & 0b01111111)
    return (dev_id, dev_val)

def data_to_pack(dev_id,dev_val):
    data[0] = 0b10000000|( dev_id<<3)|((dev_val>>7)&0b00000111)
    data[1] = (0b0001111111&dev_val)
    return bytes([data[0],data[1]])
第一段程式碼是用來解碼的。參數 data 是一個 2byte 的s4a封包。最後會回傳dev_id(就是channel ID)和 dev_val (就是value)。
而第二段程式碼是用來解碼的。代入參數dev_id (channel ID)和 dev_val (Value)之後就會回傳s4a 形式的封包。

Python 程式碼和s4a板子溝通

在Linux 系統上,arduino 用USB連接之後,會出現 "/dev/ttyUSB0" 這個裝置檔。這表示說,arduino 是用標準的 serial port 的形式來連線。所以我們用下面的一段python程式碼來建立起連線:
#!/usr/bin/env python3

import serial
from time import sleep
import sys
import threading


#ser = serial.Serial('/dev/ttyUSB0',9600,8,serial.PARITY_NONE,serial.STOPBITS_ONE)




class s4a_slave(object):

    def __init__(self,port):
        self.ser = serial.Serial(port,38400,8,'N',1)
        self.pin_outputs = [0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0] # dev id : 4 ~ 13
        self.pin_inputs = [0,0,0,0,0,0,0,0,0,0,0] # analog 0 ~ 5
        self.count = 0

    def main_loop(self):
        while(True):
            sleep(0.001)
            data = self.ser.read(2)
            if data[0] & 0b10000000:
                dev_id, dev_val = self.pack_to_data(data)
                self.pin_inputs[dev_id] = dev_val
            else:
                data = self.ser.read()
            self.count += 1
            if( self.count >= 64):
                self.count = 0
                for i in range(4,14):
                    data = self.data_to_pack( i , self.pin_outputs[i] )
                    self.ser.write(data)

    def pack_to_data(self,data):
        dev_id = (data[0] & 0b01111000) >> 3
        dev_val = ((data[0] & 0b00000111 ) << 7) | (data[1] & 0b01111111)
        return (dev_id, dev_val)

    def data_to_pack(self,dev_id,dev_val):
        data = [0,0]
        data[0] = 0b10000000 | ((dev_id & 0b00001111) << 3) | ( ( dev_val >> 7 ) & 0b00000111 )
        data[1] = ( 0b0001111111 & dev_val )
        return bytes([data[0],data[1]])

    def start(self):
        self.th = threading.Thread(target = self.main_loop , args=())
        self.th.start()

    def set_dev(self,dev_id,dev_val):
        if((dev_val >= 0) and (dev_val < 1024)):
            self.pin_outputs[dev_id] = int(dev_val)



if __name__=="__main__":
    s4a = s4a_slave('/dev/ttyUSB0')
    s4a.start()
    while(True):
        cmd = input().split()
        s4a.set_dev(int(cmd[0]),int(cmd[1]))
程式碼執行之後,畫面會等待使用者輸入如下的指令:
5 200 (按ENTER)
表示將channel ID 5 的 Value 設定為 200(channel ID 5 的 pin 腳被s4a定義為 pwm 輸出)。 如果正確連線的話,s4a板子的 pin 5 就會開始輸出 pwm 訊號 (duty cycle 為 200/255)。
進行到這裡,其實我們就可以不用再管scratch 而直接使用python來控制 s4a 的板子了。


變異數、變異係數、相關係數



變異數Variance) : 用來衡量資料的分散程度, 可以用來比較兩個同單位DataSet的分散程度

  E(X)=μ

A.變異數=變方=Var(X)σ²
B.變異數Var(X)為對數據的變異程度的衡量,常用來量測資料分散程度之指標值,變異數其定義為:每一個觀測值和平均值之間的偏差值的平方值的平均。

變異係數 (Coefficient of Variation)
 可以用來比較兩個不同單位DataSet的分散程度

定義說明:
          一組資料的變異係數是指將此組資料的標準差除以平均數所的商化為百分比所得之值。
                   設此組資料的平均數為,標準差為 s,則其變異係數為                                                   

詳細說明:
          變異係數是一種相對差異量數,用以比較單位不同或單位相
          同但資料差異甚大的資料分散情形。
範例解說:
          1.調查五位學生之身高及體重如下,試比較其分散程度。
            身高:172、168、164、170、176(公分)
            體重:62、57、58、64、64(公斤)
            
          解答:
               因為身高與體重的單位不同,欲比較二者的分散程度,
               可利用變異係數來比較。
               先計算身高與體重各自的平均數與標準差,得平均身高
               為170公分、標準差為4.47公斤,平均體重為61公斤、
               標準差為3.31公斤。
               計算身高的變異係數為4.47/170*100% = 2.63%,而體重
               的變異係數為3.31/61*100% = 5.4%。比較二者,體重的
               變異係數較大,所以體重的分散程度較大。

不過變異數是絕對離差量數,變異係數則是相對的 
當多組資料要比較離散程度時,若是每組資料單位相同, 則可用變異數或標準差來比較,值愈大,愈離散。 
若單位不同,則要用變異係數來比較,  因為變異係數等於標準差除以平均數,是一個沒有單位的值 .這樣才能做比較 

例如, 不同公司比較員工身高的分散程度,則可以用變異數去比較因為比的都是同樣的單位。
 若是不同單位的比較,則要用變異係數,表示資料相對分散程度,而沒有單位值。








相關係數(Correlation coefficient): 用來衡量兩個變數之間的關係密切程度
 相關係數的值介於–1與+1之間,即–1≤r≤+1。其性質如下:
  • 當r>0時,表示兩變數正相關,r<0時,兩變數為負相關。
  • 當|r|=1時,表示兩變數為完全線性相關,即為函數關係。
  • 當r=0時,表示兩變數間無線性相關關係。
  • 當0<|r|<1時,表示兩變數存在一定程度的線性相關。且|r|越接近1,兩變數間線性關係越密切;|r|越接近於0,表示兩變數的線性相關越弱。
  • 一般可按三級劃分:|r|<0.4為低度線性相關;0.4≤|r|<0.7為顯著性相關;0.7≤|r|<1為高度線性相關。

 r=\frac{\sum(x-\overline{x})(y-\overline{y})}{\sqrt{\sum(x-\overline{x})^2\sum(y-\overline{y})^2}}  



表1  廣告費與月平均銷售額相關表  單位:萬元
年廣告費投入月均銷售額
12.5
15.3
23.2
26.4
33.5
34.4
39.4
45.2
55.4
60.9
21.2
23.9
32.9
34.1
42.5
43.2
49.0
52.8
59.4
63.5
  參照表1,可計算相關係數如表2:
序號廣告投入(萬元)
x
月均銷售額(萬元)
y
x^2y2xy
1
2
3
4
5
6
7
8
9
10
12.5
15.3
23.2
26.4
33.5
34.4
39.4
45.2
55.4
60.9
21.2
23.9
32.9
34.1
42.5
43.2
49.0
52.8
59.4
63.5
156.25
234.09
538.24
696.96
1122.25
1183.36
1552.36
2043.04
3069.16
3708.81
449.44
571.21
1082.41
1162.81
1806.25
1866.24
2401.00
2787.84
3528.36
4032.25
265.00
365.67
763.28
900.24
1423.75
1486.08
1930.60
2386.56
3290.76
3867.15
合計346.2422.514304.5219687.8116679.09
r=\frac{n\sum xy-\sum x\sum y}{\sqrt{n\sum x^2-(\sum x)^2}\sqrt{n\sum y^2-(\sum y)^2}}
=\frac{10\times 16679.09-346.2\times 422.5}{\sqrt{10\times 14304.52-346.2^2}\sqrt{10\times 19687.81-422.5^2}}
=0.9942
  相關係數為0.9942,說明廣告投入費與月平均銷售額之間有高度的線性正相關關係。

[相關文章][3] 什麼是機器學習? (學習簡介)

[相關課程]

[1]TensorFlow Lite for MCU https://bit.ly/3j2fIIt 
[2]AI機器學習&深度學習 http://bit.ly/2KDZZz4 
[3] AIoT智能聯網運算實戰(使用OpenVINO) http://bit.ly/2IlIUK8 
[4]AI自然語言與推薦系統應用 https://bit.ly/3qnO2Tg 
[5]python程式設計 https://bit.ly/359cz4m







2017年10月3日 星期二

Python 處理Excel (.csv) 欄位計算使用Numpy




Python 處理Excel (.csv) 欄位計算使用Numpy



Numpy是Python用來科學計算的一個非常重要的函式庫,numpy主要用來處理一些矩陣對象,可以說numpy讓Python有了Matlab功能。

import numpy as np

p.s  使用numpy 要先安裝此module
   pip3 install numpy

產生5x7陣列
a = np.arange(35).reshape(5,7)
print(a)


[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]
 [21 22 23 24 25 26 27]
 [28 29 30 31 32 33 34]]


取出特定cell的值
print(a[2,4])


18

取出特定列
print(a[0:3,:])  #取出某些列中的全部欄位 從第0列~第3列



[[ 0  1  2  3  4  5  6]
 [ 7  8  9 10 11 12 13]
 [14 15 16 17 18 19 20]]


取出特定列、欄
print(a[0:3,0:4]) 
# [start:end:step] 用來連續抓取一塊矩陣範圍, 可以使用step參數 (step=1,2,3...) , 預設step=1 (step=1可以不寫)


[[ 0  1  2  3]
 [ 7  8  9 10]
 [14 15 16 17]]

print(a[1:5:2,::3])   #row : 1,3 ; column: no start, so start(0):no end:step 3==> 0,3,6,....
[[ 7 10 13]
 [21 24 27]]


取出特定欄
print(a[:,1])     #start 不寫表示從0開始, end不寫表示算到最後  [ 1  8 15 22 29]



[ 1  8 15 22 29]

取出多個特定欄位
print(a[:,[1,3,4]])  #取出所有列中的某些特定欄, 第1欄, 第3欄,第4欄


[[ 1  3  4]
 [ 8 10 11]
 [15 17 18]
 [22 24 25]
 [29 31 32]]


欄位相乘
f1,f2=1,2
y1=a[:,f1]
y2=a[:,f2]
y=y1*y2
print(y)  


[  2  72 240 506 870]

找最大值 print(np.max(y))


870

找最小值

print(np.min(y))


2

陣列元素值加總
print(np.sum(y))


1690

陣列元素四捨五入
np.around([0.55, 0.65, 0.05], decimals=1)

array([0.6, 0.6, 0.0])


[python] numpy meshgrid



numpy


numpy
import numpy as np
import matplotlib.pyplot as plt

#plt.axis([0, 6, 0, 20])

xvalues = np.array([1,2,3,4]);
yvalues = np.array([5,6,7]);
xx, yy = np.meshgrid(xvalues, yvalues)
print(xx)
print(yy)
plt.plot(xx, yy, marker='.', color='k', linestyle='none')
plt.show()


[[1 2 3 4]
 [1 2 3 4]
 [1 2 3 4]]
[[5 5 5 5]
 [6 6 6 6]
 [7 7 7 7]]










2017年10月2日 星期一

RDBMS-ACID



ACID,是指資料庫管理系統DBMS)在寫入或更新資料的過程中,為保證資料交易 transaction是正確可靠的,所必須具備的四個特性:原子性(atomicity,或稱不可分割性)、一致性(consistency)、隔離性(isolation,又稱獨立性)、持久性(durability)。
在資料庫系統中,一個資料交易是指:由一系列資料庫操作組成的一個完整的邏輯過程。例如銀行轉帳,從原帳戶扣除金額,以及向目標帳戶添加金額,這兩個資料庫操作的總和,構成一個完整的邏輯過程,不可拆分。這個過程被稱為一個事務,具有ACID特性。ACID的概念在ISO/IEC 10026-1:1992文件的第四段內有所說明。


  • 原子性:一個transaction中的所有操作,要麼全部完成,要麼全部不完成,不會結束在中間某個環節。事務在執行過程中發生錯誤,會被回滾(Rollback)到事務開始前的狀態,就像這個事務從來沒有執行過一樣。
  • 一致性:在transaction開始之前和事務結束以後,資料庫的完整性沒有被破壞。這表示寫入的資料必須完全符合所有的預設規則,這包含資料的精確度、串聯性以及後續資料庫可以自發性地完成預定的工作。
  • 隔離性:資料庫允許多個transaction同時對其數據進行讀寫和修改的能力,隔離性可以防止多個transaction 同時執行時而導致數據的不一致。
  • 持久性:transaction處理結束後,對數據的修改就是永久的,即便系統故障也不會丟失。


RDBMS (Relational DBMS ) 的SQL


1.)資料定義語言(Data Definition Language,DDL)是SQL語言集中負責資料結構定義與資料庫物件定義的語言,由CREATE、ALTER與DROP組成

2.)資料查詢語言(Data Query Language, DQL)是SQL語言中,負責進行資料查詢而不會對資料本身進行修改的語句,這是最基本的SQL語句。

3.)資料操作語言(Data Manipulation Language, DML)是SQL語言中,負責對資料庫物件執行資料存取工作的指令集,以INSERT、UPDATE、DELETE三種指令為核心,分別代表插入、更新與刪除,是開發以資料為中心的應用程式必定會使用到的指令,因此有很多開發人員都把加上SQL的SELECT語句的四大指令以「CRUD」來稱呼。


4.) 資料控制語言 (Data Control Language,DCL) 在SQL語言中,是一種可對資料存取權進行控制的指令,它可以控制特定使用者帳戶對資料表、檢視表、預存程式、使用者自訂函式等資料庫物件的控制權。由 GRANT 和 REVOKE 兩個指令組成。