2017年11月29日 星期三

Oracle MODEL

Oracle MODEL

tags: oracle MODEL

語法

MODEL [RETURN [UPDATED | ALL] ROWS] [reference models] [PARTITION BY (<cols>)] DIMENSION BY (<cols>) MEASURES (<cols>) [IGNORE NAV] | [KEEP NAV] [RULES [UPSERT | UPDATE] [AUTOMATIC ORDER | SEQUENTIAL ORDER]

語法說明

MODEL:是一個宣告的關鍵字
PARTITION BY:以XX欄位為分組
DIMENSION BY:MODEL維度設定,看成INDEX,可以是複合PK
MEASURES:指定資料欄位,可自行定義
RULES:規則,你怎麼去操作它,如any,cv…

範例

範例_MODEL

範例來源

CREATE TABLE A AS SELECT 'lottu' AS vname, 1 AS vals FROM dual; SELECT vname,vals FROM A MODEL --partition by ()可以忽略 DIMENSION BY(vals) MEASURES(vname) RULES (vname[1]='0924');

結果如下:

VNAME VALS
0924     1

執行結果會發現,vname的部份被指定為0924,因為只有一筆資料,所以index(VALS)=1的部份即為該資料,而且被指定為0924!
如果調整一下RULES!

SELECT vname,vals FROM A MODEL --partition by ()可以忽略 DIMENSION BY(vals) MEASURES(vname) RULES (vname[0]='0924');

結果如下:

    VNAME   VALS
1   lottu 1
2   0924 0

這時候會發現,多了一筆資料了,並且VALS為0!

我們再插入一筆資料,(‘LI’,2)

INSERT INTO A VALUES ('LI',2); COMMIT;

接著執行!

SELECT vname,vals FROM A MODEL DIMENSION BY(vals) MEASURES(vname) RULES (vname[2]='0924');

結果如下:

    VNAME   VALS
1   lottu 1
2   0924 2

跟剛才一樣,RULES將LI調整為0924了!
當然也可以跟剛才不一樣,用不存在的INDEX去做設置。

SELECT vname,vals FROM A MODEL DIMENSION BY(vals) MEASURES(vname) RULES (vname[5]='0924',vname[0]='99');

這次我們加了兩筆記錄進去。

範例_MODEL RETURN UPDATED ROWS_1

MODEL後面如果加上RETURN UPDATED ROWS即代表,有被RULES更新或者插入的資料才會顯示

SELECT vname,vals FROM A MODEL RETURN UPDATED ROWS DIMENSION BY(vals) MEASURES(vname) RULES (vname[0]='0924');

結果如下:

    VNAME   VALS
1   0924 0

我們有兩筆資料,按上面的練習應該是會出現三筆才對!
但這次的SELECT卻只出現一筆,這就是加入RETURN UPDATED ROWS的用途!

範例_MODEL RETURN UPDATED ROWS_2_加總

用另一個例子來說明!
建立另一個新的table,並加入數據!
我們建立了2011年到2014年的資料,希望預測2015年!

CREATE TABLE B(p_id NUMBER,p_year Varchar2(5),p_val NUMBER); INSERT INTO B VALUES (1001,'2011',25); INSERT INTO B VALUES (1001,'2012',35); INSERT INTO B VALUES (1001,'2013',65); INSERT INTO B VALUES (1001,'2014',95); INSERT INTO B VALUES (1002,'2011',25); INSERT INTO B VALUES (1002,'2012',55); INSERT INTO B VALUES (1002,'2013',75); INSERT INTO B VALUES (1002,'2014',95);

接著先以不加入RETURN的方式呈現比較清楚整個資料結構。

SELECT * FROM B MODEL PARTITION BY (p_id) DIMENSION BY (p_year) MEASURES (p_val) RULES (p_val['2015']=p_val['2014']+p_val['2013']);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1001 2011 25
2 1001 2012 35
3 1001 2013 65
4 1001 2014 95
5 1002 2011 25
6 1002 2012 55
7 1002 2013 75
8 1002 2014 95
9 1001 2015 160
10 1002 2015 170

我們以P_ID為分組依據,以P_YEAR為維度,設定P_VAL為呈現的數據,然後設置2015年的值=2013年加上2014年!
接著我們加入RETURN UPDATED ROWS

SELECT * FROM B MODEL RETURN UPDATED ROWS PARTITION BY (p_id) DIMENSION BY (p_year) MEASURES (p_val) RULES (p_val['2015']=p_val['2014']+p_val['2013']);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1001 2015 160
2 1002 2015 170     

只回傳異動的資料,所以只會有2015年的資料呈現。

範例_MODEL RETURN UPDATED ROWS_3_個別處理

資料集的部份一樣是剛才建置的TABLE B
2015年的1001是前兩年的總合,而1002是上年度的2倍。

SELECT * FROM B MODEL RETURN UPDATED ROWS DIMENSION BY (p_id,p_year) MEASURES (p_val) RULES (p_val[1001,'2015']=p_val[1001,'2013']+p_val[1001,'2014'], P_val[1002,'2015']=2 * p_val[1002,'2014']);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1002 2015 190
2 1001 2015 160

這次不設置PARTITION
將P_ID加入維度內(DIMENSION)
並且搜尋數據組一樣為P_VAL
就可以個別的處理兩個P_ID的2015年的銷售計算了。

範例_MODEL RETURN UPDATED ROWS_4_RULES BETWEEN AND

語法:SUM(MEASURES)[DIMENSION BETWEEN CON1 AND CON2]

SELECT * FROM B MODEL RETURN UPDATED ROWS PARTITION BY (p_id) DIMENSION BY (p_year) MEASURES (p_val) RULES (p_val['2015']=sum(p_val)[p_year BETWEEN '2013' AND '2014']);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1001 2015 160
2 1002 2015 170

透過SUM(MEASURES)[DIMENSION BETWEEN CON1 AND CON2]
可以像在操作標準SQL語法一樣設置條件。
此例加總了2013年至2014年的P_VAL

範例_MODEL RETURN UPDATED ROWS_5_RULES FOR

語法:SUM(MEASURES)[FOR DIMENSION IN (CONDITION)]

SELECT * FROM B MODEL RETURN UPDATED ROWS PARTITION BY (p_id) DIMENSION BY (p_year) MEASURES (p_val) RULES (p_val['2015']=sum(p_val)[for p_year in ('2014','2013')]);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1001 2015 160
2 1002 2015 170

這個案例我們用了FOR + IN的語法
FOR DIMENSION IN 條件
所以一樣求得了2013年與2014年的加總
如果P_YEAR本身是數值的話,可以利用表達式

FOR DIMENSION FROM INT1 TO INT2 INCREMENT N

此例來說,如果P_YEAR為數值,那我們的表達式可以以這樣子來表示

for year from 2013 to 2014 increment 1

代表從2013年到2014年,迭代部份一次增加1

最後提到

FOR DIMENSION IN (SELECT 子句)

在IN的部份是可以利用SELECT子句來處理

範例_MODEL RETURN UPDATED ROWS_6_RULES ANY, ISNAY

ANY>位置標記使用
IS ANY>符號標記使用

SELECT * FROM B MODEL RETURN UPDATED ROWS PARTITION BY (p_id) DIMENSION BY (p_year) MEASURES (p_val) RULES (p_val['2017']=SUM(p_val)[ANY]);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1001 2017 220
2 1002 2017 250

我們假設2017年的預測為前面幾年的部份,這時候可以利用ANY表達式!

SELECT * FROM B MODEL RETURN UPDATED ROWS PARTITION BY (p_id) DIMENSION BY (p_year) MEASURES (p_val) RULES (p_val['2017']=SUM(p_val)[P_YEAR IS ANY]);

也可以得到一樣的結果

範例_MODEL RETURN UPDATED ROWS_7_RULES CURRENTV()

SELECT * FROM B MODEL RETURN UPDATED ROWS DIMENSION BY (p_id,p_year) MEASURES (p_val) RULES (p_val[1001,'2015']=p_val[currentv(),'2013']+p_val[currentv(),'2014'], P_val[1002,'2015']=2 * p_val[currentv(),'2014']);

結果如下:

        P_ID   P_YEAR  P_VAL
1 1002 2015 190
2 1001 2015 160

CURRENTV主要用來取得某個DIMENSION目前的值!
對比上面的範例

SELECT * FROM B MODEL RETURN UPDATED ROWS DIMENSION BY (p_id,p_year) MEASURES (p_val) RULES (p_val[1001,'2015']=p_val[1001,'2013']+p_val[1001,'2014'], P_val[1002,'2015']=2 * p_val[1002,'2014']);

2017年11月28日 星期二

機器學習_ML_學習曲線

機器學習_ML_學習曲線

API連結
官方文件
學習曲線與驗證曲線是在機器學習中很重要的兩條線,透過線的呈現可以明白模型究竟是高偏差(high bias)還是高方差(high variance)。
為什麼重要?
因為high bias and high variance在實務上的調校是不相同的!
你去對一個high bias的模型餵再多的資料,效果恐怕是有限的。
你去對一個high variance給了更多的特徵,那不是拿提汽油上場嗎?

high bias 代表 underfitting
high variance 代表 overfitting

學習來自吳恩達老師_機器學習_第六週課程

  • 更多的數據
    • high variance有效
    • high bias沒效
  • 嚐試用更少的特徵
    • high variance有效
  • 取得更有效的特徵
    • high bias有效
  • 用更高的多項式方式
    • high bias有效
    • high variance是浪費時間
  • 減少正規項λ數值
    • high bias有效
  • 增加正規項λ數值
    • high variance有效

學習曲線的部份,從sklearn官方說明可以知道!

Determines cross-validated training and test scores for different training set sizes.

確定不同訓練集大小的交叉驗證訓練和測試分數。
我們可以從學習曲線了解到,我們增加了資料集之後所得的益處有多少!

IMPORT

from sklearn.learning_curve import learning_curve

CLASS

sklearn.model_selection.learning_curve(
    estimator, X, y, groups=None, 
    train_sizes=array([ 0.1, 0.33, 0.55, 0.78, 1. ]),
    cv=None, scoring=None, 
    exploit_incremental_learning=False, n_jobs=1,
    pre_dispatch=’all’, verbose=0, shuffle=False, 
    random_state=None)

參數說明

estimator

使用的分類器,但限制為需要有fit、predict兩個method!

X

訓練資料集

y

對應訓練資料集的label

groups

train_sizes

訓練資料集的使用,使用上可以給一個陣列
像上面的例子([0.1, 0.33, 0.55, 0.78, 1])
要一直大,限制在0-1之間!
或是透過np.linspace(0.1,1.0,n)來設置!
n的部份自行調整!

cv

default 3
定義拆分折數
預設使用分層K折交叉驗證。

scoring

exploit_incremental_learning

default False

n_jobs

default 1
使用多少CPU核心數
-1代表火力全開

pre_dispatch

verbose

default 0
過程是否輸出
0不輸出
1偶爾輸出
2一定輸出

shuffle

是否要亂數排序

random_state

default None
隨機數種子

屬性

回傳三個值!

train_sizes_abs

資料集的切割狀況
假如有1000,你設置了np.linspace(0.1,1.0,10)
那就會回傳100,200,…1000

train_scores

訓練資料集分數

test_scores

測試資料集分數

範例

下面是一個來自官方的範例

import numpy as np
import matplotlib.pyplot as plt
from sklearn.naive_bayes import GaussianNB
from sklearn.svm import SVC
from sklearn.datasets import load_digits
from sklearn.model_selection import learning_curve
from sklearn.model_selection import ShuffleSplit


def plot_learning_curve(estimator, title, X, y, ylim=None, cv=None,
                        n_jobs=1, train_sizes=np.linspace(.1, 1.0, 5)):
    """
    Generate a simple plot of the test and training learning curve.

    Parameters
    ----------
    estimator : object type that implements the "fit" and "predict" methods
        An object of that type which is cloned for each validation.

    title : string
        Title for the chart.

    X : array-like, shape (n_samples, n_features)
        Training vector, where n_samples is the number of samples and
        n_features is the number of features.

    y : array-like, shape (n_samples) or (n_samples, n_features), optional
        Target relative to X for classification or regression;
        None for unsupervised learning.

    ylim : tuple, shape (ymin, ymax), optional
        Defines minimum and maximum yvalues plotted.

    cv : int, cross-validation generator or an iterable, optional
        Determines the cross-validation splitting strategy.
        Possible inputs for cv are:
          - None, to use the default 3-fold cross-validation,
          - integer, to specify the number of folds.
          - An object to be used as a cross-validation generator.
          - An iterable yielding train/test splits.

        For integer/None inputs, if ``y`` is binary or multiclass,
        :class:`StratifiedKFold` used. If the estimator is not a classifier
        or if ``y`` is neither binary nor multiclass, :class:`KFold` is used.

        Refer :ref:`User Guide <cross_validation>` for the various
        cross-validators that can be used here.

    n_jobs : integer, optional
        Number of jobs to run in parallel (default 1).
    """
    plt.figure()
    plt.title(title)
    if ylim is not None:
        plt.ylim(*ylim)
    plt.xlabel("Training examples")
    plt.ylabel("Score")
    train_sizes, train_scores, test_scores = learning_curve(
        estimator, X, y, cv=cv, n_jobs=n_jobs, train_sizes=train_sizes)
    train_scores_mean = np.mean(train_scores, axis=1)
    train_scores_std = np.std(train_scores, axis=1)
    test_scores_mean = np.mean(test_scores, axis=1)
    test_scores_std = np.std(test_scores, axis=1)
    plt.grid()

    plt.fill_between(train_sizes, train_scores_mean - train_scores_std,
                     train_scores_mean + train_scores_std, alpha=0.1,
                     color="r")
    plt.fill_between(train_sizes, test_scores_mean - test_scores_std,
                     test_scores_mean + test_scores_std, alpha=0.1, color="g")
    plt.plot(train_sizes, train_scores_mean, 'o-', color="r",
             label="Training score")
    plt.plot(train_sizes, test_scores_mean, 'o-', color="g",
             label="Cross-validation score")

    plt.legend(loc="best")
    return plt


digits = load_digits()
X, y = digits.data, digits.target


title = "Learning Curves (Naive Bayes)"
# Cross validation with 100 iterations to get smoother mean test and train
# score curves, each time with 20% data randomly selected as a validation set.
cv = ShuffleSplit(n_splits=100, test_size=0.2, random_state=0)

estimator = GaussianNB()
plot_learning_curve(estimator, title, X, y, ylim=(0.7, 1.01), cv=cv, n_jobs=4)

title = "Learning Curves (SVM, RBF kernel, $\gamma=0.001$)"
# SVC is more expensive so we do a lower number of CV iterations:
cv = ShuffleSplit(n_splits=10, test_size=0.2, random_state=0)
estimator = SVC(gamma=0.001)
plot_learning_curve(estimator, title, X, y, (0.7, 1.01), cv=cv, n_jobs=4)

plt.show()

結果如下

上圖的部份,可以明確的發現,資料集的增加並未對模型帶來好的效果,並且這是一個高偏差的模型,調整上增加再多的模型也沒有用。
而下圖的部份在資料集的增加情況下,是有明顯的讓驗證資料集也提升。

範例2

書名:Python Machine Learning
作者:Sebastian Raschka
ISBN:978-986-434-140-5

# import lib
import matplotlib.pyplot as plt
#  學習曲線
from sklearn.learning_curve import learning_curve
#  驗證曲線
from sklearn.learning_curve import validation_curve
#  標準化
from sklearn.preprocessing import StandardScaler
#  標籤編碼
from sklearn.preprocessing import LabelEncoder
#  資料分集
from sklearn.cross_validation import train_test_split
#  管道
from sklearn.pipeline import Pipeline
#  logistic
from sklearn.linear_model import LogisticRegression
import pandas as pd
import numpy as np

# get dateset
df = pd.read_csv('https://archive.ics.uci.edu/ml/machine-learning-databases/breast-cancer-wisconsin/wdbc.data',header=None)
X = df.loc[:, 2:].values
y = df.loc[:, 1].values
#  將標籤編碼
le = LabelEncoder()
#  訓練之後直接轉換
y = le.fit_transform(y)
le.transform(['M', 'B'])

#  資料拆分
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=1)

學習曲線

#  設置pipeline
pipe_lr = Pipeline([
    ('scl', StandardScaler()),  #  標準化
    ('clf', LogisticRegression(  #  logistic , 正規方式為l2
                    penalty='l2', random_state=0))
])
#  訓練,learning_curve預設使用分層k折交叉驗證法
train_sizes, train_scores, test_scores = learning_curve(
                                estimator=pipe_lr,
                                X=X_train,
                                y=y_train,
                                train_sizes=np.linspace(0.1, 1.0, 10),
                                cv=10,
                                n_jobs=1)

繪製圖形

#  訓練曲線
train_mean = np.mean(train_scores, axis=1)
train_std = np.std(train_scores, axis=1)
#  設置x軸是資料集,而y軸是十折的平均得分
plt.plot(train_sizes,train_mean,color='blue',marker='o',markersize=5,label='Training accuracy')
#  設置訓練曲線的均值+-標準差的區塊呈現
plt.fill_between(train_sizes,train_mean + train_std, train_mean - train_std, alpha=0.15, color='blue')
#  驗證曲線
test_mean = np.mean(test_scores, axis=1)
test_std = np.std(test_scores, axis=1)
#  設置x軸是資料集,而y軸是十折的平均得分
plt.plot(train_sizes,test_mean,color='green',marker='s', linestyle='--',markersize=5,label='Validation accuracy')
#  設置驗證曲線的均值+-標準差的區塊呈現
plt.fill_between(train_sizes,test_mean + test_std, test_mean - test_std, alpha=0.15, color='green')
#  設置格線
plt.grid() 
#  設置x、y軸
plt.xlabel('Number of training samples')
plt.ylabel('Accuracy')
#  產生標識在右下
plt.legend(loc='lower right')
#  設置y軸間距
plt.ylim([0.8, 1.0])
plt.show()

從圖形可以看的出來,針對訓練資料集的部份,正負了標準差之後的區域差異不大,但在驗證資料集的部份卻並非如此,這代表著這個模型有著過適的問題。

2017年11月13日 星期一

PL/SQL常用設定

PLSQL_常用設定

常用的個人化設置

PLSQL個人化設置


關鍵字自動大寫


顯示行號



HIGHLIGHT編輯行

PICPICKSHAPE

自動排版


快速關閉視窗


複製特別格式

如果需要滿足其它程式語言的格式的時候,利用這功能可以省去不少時間。


執行單條語法

不同的SELECT語句通常需要選擇範圍之後才有辦法執行,設置之後只要游標在上就可以執行該段SQL語法,唯一重點在於結尾需要加上分號

設置連線指示燈

顏色管理可以有效避免自己登錯帳號跟資料庫

設置null欄位的顏色

避免空值與NULL分不清楚

Python pycallgraph

Python pycallgraph

文件連結
在python中,如果想追蹤整個程式的執行流程,甚至繪出流程圖的話,可以透過安裝套件『pycallgraph』來實作。

需求套件

pip install pycallgraph

相依套件

graphviz
需求有此套件才有辦法實作

問題排除

參考Stackoverflow
pycallgraph.exceptions.PyCallGraphException: 
The command "dot" is required to be in your path.
在實作的時候不斷的出現此問題,詭異的是,即使透過修正系統環境變數還是一樣。
在透過pyChram中的run\edit config\環境變數調整之後,沒有錯誤訊息,但是執行之後也無法產生圖面。


最後透過import os來做環境變數的調整,就正常了。
import os
os.environ["PATH"] += os.pathsep + r'C:/Program Files (x86)/Graphviz2.38/bin/'

排除題外話

在查詢git上的issues的時候也發現其它問題,似乎在windows上有點小毛病。
git

範例

範例取自官方,只是加入了import os
#!/usr/bin/env python2
# -*- coding: utf-8 -*-
#!/usr/bin/env python
"""
This example demonstrates a simple use of pycallgraph.
"""
from pycallgraph import PyCallGraph
from pycallgraph.output import GraphvizOutput
#  手動自己加入
import os
os.environ["PATH"] += os.pathsep + r'C:/Program Files (x86)/Graphviz2.38/bin/'

class Banana:

    def eat(self):
        pass


class Person:

    def __init__(self):
        self.no_bananas()

    def no_bananas(self):
        self.bananas = []

    def add_banana(self, banana):
        self.bananas.append(banana)

    def eat_bananas(self):
        [banana.eat() for banana in self.bananas]
        self.no_bananas()


def main():
    graphviz = GraphvizOutput()
    graphviz.output_file = 'basic.png'

    with PyCallGraph(output=graphviz):
        person = Person()
        for a in xrange(10):
            person.add_banana(Banana())
        person.eat_bananas()


if __name__ == '__main__':
    main()
透過with實作PyCallGraph,完成之後會在專案底下看到basic.png!

進階範例

實作進階的部份設置多為過濾掉不想要的,或是設置最深階度。

最深階度

from pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph.output import GraphvizOutput


#  max_depth設置最深追蹤梯度
config = Config(max_depth=1)
graphviz = GraphvizOutput(output_file='basic.png')

with PyCallGraph(output=graphviz, config=config):
    #  這邊加入你要追蹤的項目

過濾

from pycallgraph import PyCallGraph
from pycallgraph import Config
from pycallgraph import GlobbingFilter
from pycallgraph.output import GraphvizOutput


config = Config()
config.trace_filter = GlobbingFilter(exclude=[
    'pycallgraph.*',
    '*.secret_function',
])

graphviz = GraphvizOutput(output_file='basic.png')

with PyCallGraph(output=graphviz, config=config):
    #  這邊加入你要追蹤的項目

Python cx_Oracle

Python cx_Oracle

安裝cx_Oracle

dll 找不到指定程序

過程一波三折,建議作法是,先不要聽網路上的八卦,把所有cx_Oracle移除,然後把依著網路八卦複製什麼檔到那裡的檔案通通砍了!
然後至官網下載對應的版本(作業系統、資料庫版本)之後,就可以直接安裝!!
是的,我弄了四個多小時就是這樣子做就好了!
不過對於oracle的設置確認還是要先處理好!

tnsping 可以測試是否設置正常

import cx_Oracle

沒有錯誤訊息的時候眼淚都流出來了!

連線oracle

MIS2000老師有教過,連接資料庫四步驟!
CONNECTION->SQLCOMMAND->SQLREADER->CLOSE(有借記得要有還)

db = cx_Oracle.connect(帳號, 密碼, 連接的資料庫)
db.version


眼淚再次的噴發!看到版本了!

一般來說,如果直接透過cx_Oracle.cursor.excute來取得資料集的話,這個回傳資料集會是一個物件!

cursor = db.Cursor()
sql = 'select 123 coluu from dual'
cursor.excute(sql)

當然這要看實際的應用是不是有要保留這個物件,有的話就可以配合pickle來將檔案序列化(我是這樣想@@)
不過如果要做直接使用的話,也可以搭配pandas

pandas

import pandas as pd
df = pd.read_sql(sql, db)

就可以開始做後續的利用了!
不過別忘了,有借有還!

db.close()

cx_oracle query

官方git sample

import cx_Oracle
db = cx_Oracle.connect(帳號, 密碼, 連接的資料庫)
sql = 'select 123 coluu from dual union select 456 coluu from dual'
cursor = db.Cursor()

一次取一筆:fetchone

每執行一次,指標就會往下一筆過去

cursor.execute(sql)
#  取回第一筆
row = cursor.fetchone()
print(row)
#  取回第二筆
row = cursor.fetchone()
print(row)

結果如下:

>>>cursor.fetchone()
(123,)
>>>cursor.fetchone()
(456,)

一次取多筆:fetchmany

透過numRows指定一次取回的筆數

cursor.execute(sql)
res = cursor.fetchmany(numRows=3)

結果如下:

>>>res = cursor.fetchmany(numRows=2)
>>>res
[(123,), (456,)]

一次全取回:fetchall

cursor.execute(sql)
all = cursor.fetchall()

結果如下:

>>>all
[(123,), (456,)]

直接迴圈取回:execute

for cur in cursor.execute(sql):
  print(cur)

結果如下:

(123,)
(456,)

確認影響筆數:rowcount

在執行一個動作之後確認影響筆數
在select的情況下,回傳的不是影響筆數,而是目標游標所在。
這部份很多人誤會了!

cursor.rowcount

結果如下:

2

SQL Statement帶參數

在執行select的時候,帶參數是很正常的需求。
所以where條件上,需要可以依需求來取得資料。

str_sql = "select column from yourTable where col1=:col_a and col2=:col_b"
cursor.execute(str_sql, {col_a: 'your condition', col_b: 'your condition'})

或者也可以將參數先用dict格式裝起來

str_sql = "select column from yourTable where col1=:col_a and col2=:col_b"
dict_con = {'col_a': 'your condition', 'col_b': 'your condition'}
cursor.execute(str_sql, dict_con)

批次寫入資料庫

Oracle官方文件
不少情況在寫入資料庫的時候需求批量處理,簡單的作法上當然是透過迴圈來處理,但是這部份cx_Oracle與oracle都替我們想好了。
透過executemany搭配tuple就可以滿足了。

官方範例

create_table = "
CREATE TABLE python_modules (
module_name VARCHAR2(50) NOT NULL,
file_path VARCHAR2(300) NOT NULL
)
"
from sys import modules
cursor.execute(create_table)
M = []
for m_name, m_info in modules.items():
try:
    M.append((m_name, m_info.__file__))
except AttributeError:
    pass

>>> len(M)
76
>>> cursor.prepare("INSERT INTO python_modules(module_name, file_path) VALUES (:1, :2)")
>>> cursor.executemany(None, M)
>>> db.commit()
>>> r = cursor.execute("SELECT COUNT(*) FROM python_modules")
>>> print cursor.fetchone()
(76,)
>>> cursor.execute("DROP TABLE python_modules PURGE")

重點的部份在於後段的cursor.prepare與cursor.executemany的搭配使用!

str_sql = "select column from yourTable where col1=:col_a and col2=:col_b"
cursor.prepare(str_sql)

dict_con = {'col_a': 'your condition', 'col_b': 'your condition'}
cursor.execute(None, dict_con)

2017年11月10日 星期五

機器學習_ML_模型指標_f1_score

機器學習_ML_模型指標_f1_score

原文連結
適用性:Classification metrics

各種的數值計算都跟上面這張圖有關。(取自(維基百科))

在資料集的正負比例相差太過極端,這種情況即稱為skewed data(偏斜)
在偏斜情況下,用精度(accaury)來做模型效能並不恰當,用召回率(recall)跟(查準率)precision配合做整理,會讓整個模型的效能更明確。
這時候f1_score就出現了!

F1 = 2 * (precision * recall) / (precision + recall)

IMPORT

from sklearn.metrics import f1_score

範例

from sklearn.metrics import precision_score
from sklearn.metrics import recall_score
from sklearn.metrics import f1_score
from sklearn.metrics import confusion_matrix
y_true = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0 ,1]
y_pred = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1 ,1]
confusion_matrix(y_true=y_true, y_pred=y_pred)
precision_score(y_true, y_pred)
recall_score(y_true, y_pred)
f1_score(y_true, y_pred)

結果如下

>>> confusion_matrix(y_true=y_true, y_pred=y_pred)
array([[8, 2],
       [0, 3]], dtype=int64)
>>> precision_score(y_true, y_pred)
0.59999999999999998
>>> recall_score(y_true, y_pred)
1.0
>>> f1_score(y_true, y_pred)
0.74999999999999989

數據的部份我故意設定過,讓召回率變高,精隼率變低!
從這可以發現,高召回不代表有好的模型,因為精隼率是不高的,
透過f1_score可以更平均整個模型的效能評估。
調整一下

y_true = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0 ,1]
y_pred = [0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1 ,1]
confusion_matrix(y_true=y_true, y_pred=y_pred)
precision_score(y_true, y_pred)
recall_score(y_true, y_pred)
f1_score(y_true, y_pred)

上面的模型簡直完美!

>>> confusion_matrix(y_true=y_true, y_pred=y_pred)
array([[4, 1],
       [0, 8]], dtype=int64)
>>> precision_score(y_true, y_pred)
0.88888888888888884
>>> recall_score(y_true, y_pred)
1.0
>>> f1_score(y_true, y_pred)
0.94117647058823528

機器學習_ML_模型指標_precision_score

機器學習_ML_模型指標_precision_score

原文連結
適用性:Classification metrics

各種的數值計算都跟上面這張圖有關。(取自(維基百科))
PPV=TPTP+FP
在資料集的正負比例相差太過極端,這種情況即稱為skewed data(偏斜)
在偏斜情況下,用精度(accaury)來做模型效能並不恰當,用召回率(recall)跟(查準率)precision比較。

The precision is intuitively the ability of the classifier not to label as positive a sample that is negative.

查準率很直觀的表達了分類器無法標記負樣本的能力。

IMPORT

from sklearn.metrics import precision_score

範例

from sklearn.metrics import precision_score
from sklearn.metrics import confusion_matrix
y_true = [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0 ,1]
y_pred = [0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 ,1]
confusion_matrix(y_true=y_true, y_pred=y_pred)
precision_score(y_true, y_pred)

結果
5/(5+2)
TN FP
FN TP

array([[3, 2],
       [3, 5]], dtype=int64)
#  precision
0.7142857142857143

比對一下recall

from sklearn.metrics import recall_score
recall_score(y_true, y_pred)

結果為

>>> recall_score(y_true, y_pred)
0.625

機器學習_ML_模型指標_recall_score

機器學習_ML_模型指標_recall_score

原文連結
適用性:Classification metrics

各種的數值計算都跟上面這張圖有關。(取自(維基百科))
TP/(TP+FN)
TP/P
找到真真的的能力
召回率同意於真陽率
用意在於評估模型真的去預測到我們想要的那個部份有多好。
對於類別數據差異量很大的數據集,accuracy想必會非常漂亮,
這時候如果沒有特別的注意,會誤以為模型效能非常好。
這時候透過recall(召回)與precision(精確)來結合判斷產生f1,會是一個不錯的評估。

IMPORT

from sklearn.metrics import recall_score

範例

from sklearn.metrics import recall_score
from sklearn.metrics import confusion_matrix
y_true = [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0 ,1]
y_pred = [0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 ,1]
confusion_matrix(y_true=y_true, y_pred=y_pred)
recall_score(y_true, y_pred)
結果
5/(5+3)
TN FP
FN TP
array([[3, 2],
       [3, 5]], dtype=int64)
0.625
多標籤的話,就需要使用average參數
from sklearn.metrics import recall_score
y_true = [1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0 ,1]
y_pred = [0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1 ,1]
recall_score(y_true, y_pred, average='binary')  #  default 用於標籤數為2
recall_score(y_true, y_pred, average='macro')
recall_score(y_true, y_pred, average='micro')
recall_score(y_true, y_pred, average='weighted')
recall_score(y_true, y_pred, average='samples')
recall_score(y_true, y_pred, average=None)

結果
binary:0.625
macro:0.61250000000000004
micro:0.61538461538461542 
weighted:0.61538461538461542
samples:
None:[0.6, 0.625]  #  為None的時候會回傳所有LABEL的機率
micro average,微觀平均來說是取所有lable的加總計算,怎麼說,就是0與1的機率加總。
以0為主的話是3/(2+3)
以1為主的話是5/(5+3)
micro averave = (3+5)/(5+8) = 0.6153846xxxx
macro average,宏觀平均來說,就是label平均,怎麼說,當我們的average為None的時候已經幫我們算出來了,(0.6+0.625)/2,即為macro average
所以微觀來說,我們得到的數字意義在於總結對真假的真正預測性為何。
而宏觀來說即是平均性。

2017年11月6日 星期一

Python_enumerate

Python_enumerate

說明

回傳陣列以及相對的index

範例

for i, j in enumerate(來源陣列, 起始值=default=0):
print(i, j)

結果

ORACLE_SELECT複製TABEL

ORACLE_SELECT複製TABEL

如果有個TABLE格式一樣要直接複製的話,可以直接透過SELECT來處理!
不過用這方法的話,KEYS值不會過來,還有PRIVILEGES的授權也不會過來,記得再手工補上!

CREATE TABLE PE_TBL_C31R_TEMP AS 
SELECT * FROM PE_TBL_C31R

Python_zip

Python_zip

說明

將多個array中相同index的值取出做一個新的陣列
有點像是行列互換的概念
但如果array不同長度的話,會取到有相同的為止!
另外在python 3中,zip回傳會是一個可迭代物件!
用list()就可以讓它現形了!

範例

a = [1,2,3,4,5,6]
b = [1,2,3,4,5]
c = [1,2,3,4]
list(zip(a,b))  
list(zip(a,c))  
d = zip(a,c)
zip(*d)

結果


其它

python 3中的zip直接去print的狀況

Python logging_basic opreation

Python logging_basic opreation

官方文件

用於記錄程式執行間的錯誤訊息、執行訊息…等你想記錄的訊息,不需要再自己寫log的function來記錄了。
下面的部份設置之後,已經足夠應付一般應用了(文件說的)
有需求的部份,可以再學習進階版,不過要自備飲料!(也是文件上說的)

logging.basicConfig設置

basicConfig的設置,必需在一開始的時候就設置了,一但執行了其它method之後再調整,理論上是不會有任何的作用的。
如真的希望調整,就必需透過filemode來處理了。

logging.basicConfig(filename='example.log', filemode='w', level=logging.DEBUG)

這時候如果檔名一致的話,就會直接蓋掉了,要注意。

設置記錄層級與檔名

設置檔案名稱為example.log,並且記錄層級調整為DEBUG.

logging.basicConfig(filename='example.log', level=logging.DEBUG)

改變訊息格式

透過basicConfig內的format參數可以調整log的格式!

levelname、message

如果你想調整你的記錄訊息格式的話,可以透過format來處理。
在執行method的時候,內文就是參數message了。

import logging
logging.basicConfig(format='%(levelname)s:%(message)s', level=logging.DEBUG, filemode='w')
logging.debug('This message should appear on the console')
#  結果
#DEBUG:This message should appear on the console

asctime、created

import logging
logging.basicConfig(format='%(asctime)s,%(created)f:%(message)s', level=logging.DEBUG, filemode='w')
logging.warning('This message should appear on the console')
#  結果
#2017-10-30 11:45:14,710,1509335114.710247:This message should appear on the console

asctime的部份還可以透過參數datefmt來設置格式,格式設置方式與time.strftime()相同。

import logging
logging.basicConfig(format='%(asctime)s %(message)s', datefmt='%m/%d/%Y %I:%M:%S %p')
logging.warning('is when this event was logged.')

filename、funcName

import logging
logging.basicConfig(format='%(filename)s, %(funcName)s:%(message)s', level=logging.DEBUG, filemode='w')
logging.warning('filename and funcName.')
#  結果
#<stdin>, <module>:filename and funcName.

levelname、levelno

import logging
logging.basicConfig(format='%(levelname)s, %(levelno)s:%(message)s', level=logging.DEBUG, filemode='w')
logging.warning('levelname and levelno.')
#  結果
#<WARNING, 30:levelname and levelno.
name、pathname、relativeCreated
import logging
logging.basicConfig(format='%(name)s,%(pathname)s,%(relativeCreated)d:%(message)s', level=logging.DEBUG, filemode='w')
logging.warning('name、pathname、relativeCreated')
#  結果
#root,<stdin>,476:name、pathname、relativeCreated
lineno、module、msecs

格式清單

還蠻多不懂的,要一個一個測試

Attribute name Format Description Description
args You shouldn’t need to format this yourself.
asctime %(asctime)s log建立的時間,格式為’2003-07-08 16:49:45,896’(人類可讀時間)
created %(created)f log建立的時間,格式為time.time…‘1509332841.1471474’
exc_info You shouldn’t need to format this yourself. Exception tuple (à la sys.exc_info) or, if no exception has occurred, None.
filename %(filename)s 含部份路徑的檔案名稱
funcName %(funcName)s 產生該log的function名稱
levelname %(levelname)s 記錄層級名稱(DEBUG、INFO、…)
levelno %(levelno)s 記錄層級數值(10、20、…
lineno %(lineno)d 產生該log的行數
module %(module)s Module (name portion of filename).
msecs %(msecs)d log建立的時間的毫秒
message %(message)s 記錄的訊息
msg You shouldn’t need to format this yourself. The format string passed in the original logging call. Merged with args to produce message, or an arbitrary object (see Using arbitrary objects as messages).
name %(name)s Name of the logger used to log the call.
pathname %(pathname)s 產生該log的來源文件完整路徑
process %(process)d ProcessID
processName %(processName)s ProcessName
relativeCreated %(relativeCreated)d Time in milliseconds when the LogRecord was created, relative to the time the logging module was loaded.
stack_info You shouldn’t need to format this yourself. Stack frame information (where available) from the bottom of the stack in the current thread, up to and including the stack frame of the logging call which resulted in the creation of this record.
thread %(thread)d Thread ID
threadName %(threadName)s Thread Name

記錄層級

層級 層級數值
CRITICAL 50
ERROR 40
WARNING 30
INFO 20
DEBUG 10
NOTSET 0

Python pyad安裝異常排除

Python pyad安裝異常排除

官方github
官方網頁
安裝上,似乎無法直接透過pip install來處理。
需要安裝pywin32才能執行pyad

pip install https://github.com/zakird/pyad/archive/master.zip

如果無法直接安裝的話,就先下載zip再安裝。
參考來源