必備的module


In [1]:
import numpy as np
from scipy import spatial

在python中計算cosine similarity最快的方法是什麼?

  1. 方法1: 利用spatial.distance.cosin
  2. 方法2: 利用np.dot,但要自己除以向量長度
  3. 方法3: 土法鍊鋼
  4. 方法4: HM的方法

In [2]:
def sim1(n):
    v1 = np.random.randint(0, 100, n)
    v2 = np.random.randint(0, 100, n)
    return 1 - spatial.distance.cosine(v1, v2)

In [3]:
def sim2(n):
    v1 = np.random.randint(0, 100, n)
    v2 = np.random.randint(0, 100, n)
    return np.dot(v1, v2) / np.linalg.norm(v1) / np.linalg.norm(v2)

In [4]:
import math
def sim3(n):
    v1 = np.random.randint(0, 100, n)
    v2 = np.random.randint(0, 100, n)
    return sum(v1 * v2) / math.sqrt(sum(v1 ** 2)) / math.sqrt(sum(v2 ** 2))

In [5]:
from itertools import izip
def dot_product(v1, v2):
    return sum(map(lambda x: x[0] * x[1], izip(v1, v2)))

def sim4(n):
    v1 = np.random.randint(0, 100, n)
    v2 = np.random.randint(0, 100, n)
    prod = dot_product(v1, v2)
    len1 = math.sqrt(dot_product(v1, v1))
    len2 = math.sqrt(dot_product(v2, v2))
    return prod / (len1 * len2)

In [6]:
%timeit sim1(400)


The slowest run took 913.62 times longer than the fastest. This could mean that an intermediate result is being cached 
10000 loops, best of 3: 61.2 µs per loop

In [7]:
%timeit sim2(400)


10000 loops, best of 3: 42.1 µs per loop

In [8]:
%timeit sim3(400)


The slowest run took 874.65 times longer than the fastest. This could mean that an intermediate result is being cached 
10000 loops, best of 3: 189 µs per loop

In [9]:
%timeit sim4(400)


1000 loops, best of 3: 624 µs per loop

結論

HM的方法最慢,用np.dotnp.linalg.norm組合的最快

日期時間的格式


In [10]:
from datetime import datetime as dt

In [11]:
start = dt.now()
start.date(), start.time(), start


Out[11]:
(datetime.date(2016, 2, 2),
 datetime.time(18, 1, 23, 168066),
 datetime.datetime(2016, 2, 2, 18, 1, 23, 168066))

In [12]:
dt.now() - start


Out[12]:
datetime.timedelta(0, 1, 224554)

logging: 整合所有的module log

logging module的用途是讓所有module有一致的介面可以留下執行記錄。基本的logging system有兩個角色

  • Logger: 多個logger組成一個樹狀結構,會傳給root logger匯整
  • Handler: 接收root logger的資訊,並輸出到檔案

在預設情況下,會使用StreamHandler,將log輸出到標準輸出。如果在basicConfig中指定filename參數,則會建立FileHandler輸出到檔案。


In [13]:
import logging
fmtstr = '%(asctime)s [%(levelname)s][%(name)s] %(message)s'
datefmtstr = '%Y/%m/%d %H:%M:%S'
if len(logging.getLogger().handlers) >= 1:
    logging.getLogger().handlers[0].setFormatter(logging.Formatter(fmtstr, datefmtstr))
else:
    logging.basicConfig(format=fmtstr, datefmt=datefmtstr)

In [14]:
# 如果直接呼叫 logging.warning,就是使用root logger
logging.warning("please set %d in %s", 100, "length")


2016/02/02 18:01:31 [WARNING][root] please set 100 in length

如果從某個module呼叫時,就用


In [15]:
# 在root logger下面增加child logger
aaa_logger = logging.getLogger('aaa')
bbb_logger = aaa_logger.getChild('bbb')
ccc_logger = bbb_logger.getChild('ccc')

In [16]:
aaa_logger.warn("hello")


2016/02/02 18:01:37 [WARNING][aaa] hello

In [17]:
bbb_logger.warn("hello")


2016/02/02 18:01:38 [WARNING][aaa.bbb] hello

In [18]:
# 當logger是樹狀結構時,logger的名稱會變成 aaa.bbb.ccc
ccc_logger.warn("hello")


2016/02/02 18:01:39 [WARNING][aaa.bbb.ccc] hello

In [ ]: