2014-04-18 22 views
1

我正在嘗試使用scipy.spatial.distance來實現euclidean distance,這是我以前正常編寫的。歐幾里德距離錯誤:不受支持的操作數類型

from math import sqrt 

critics = {'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5, 
         'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 
         'The Night Listener': 3.0}, 
      'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 
          'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 
          'You, Me and Dupree': 3.5}, 
      'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0, 
           'Superman Returns': 3.5, 'The Night Listener': 4.0}, 
      'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 
          'The Night Listener': 4.5, 'Superman Returns': 4.0, 
          'You, Me and Dupree': 2.5}, 
      'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
          'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0, 
          'You, Me and Dupree': 2.0}, 
      'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
          'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5}, 
      'Toby': {'Snakes on a Plane': 4.5, 'You, Me and Dupree': 1.0, 'Superman Returns': 4.0}} 


def sim_distance(preference, person1, person2): 
    si = {} 
    for item in preference[person1]: 
     if item in preference[person2]: 
      si[item] = 1 

    if len(si) == 0: return 0 

    sum_of_scores = sum([pow(preference[person1][item] - preference[person2][item], 2) 
         for item in preference[person1] if item in preference[person2]]) 

    return 1/(1 + sum_of_scores) 


a = sim_distance(critics, 'Lisa Rose','Mick LaSalle') 
print(a) #0.333 

當前實現完美的作品,但使用scipy模塊嘗試時,我不能夠理解應該爲此提供什麼類型的輸入。這是我的嘗試。

from scipy.spatial.distance import euclidean 


a = euclidean(critics['Lisa Rose'], critics['Mick LaSalle']) 
print(a) 

回溯

Traceback (most recent call last): 
    File "C:/Users/Ajay/PycharmProjects/SO/new.py", line 22, in <module> 
    a = euclidean(critics['Lisa Rose'], critics['Mick LaSalle']) 
    File "C:\Python33\lib\site-packages\scipy\spatial\distance.py", line 224, in euclidean 
    dist = norm(u - v) 
TypeError: unsupported operand type(s) for -: 'dict' and 'dict' 

當提到的euclidean實施,似乎輸入應給出tuples,但我無法理解如何處理這一點。

def euclidean(u, v): 
    """ 
    Computes the Euclidean distance between two 1-D arrays. 

    The Euclidean distance between 1-D arrays `u` and `v`, is defined as 

    .. math:: 

     {||u-v||}_2 

    Parameters 
    ---------- 
    u : (N,) array_like 
     Input array. 
    v : (N,) array_like 
     Input array. 

    Returns 
    ------- 
    euclidean : double 
     The Euclidean distance between vectors `u` and `v`. 

    """ 
    u = _validate_vector(u) 
    v = _validate_vector(v) 
    dist = norm(u - v) 
    return dist 

請賜教。

回答

1

歐幾里德距離定義爲兩個向量之間的差值的L2範數,您可以在euclidean函數中看到dist = norm(u - v)。您的critics['Lisa Rose']critics['Mick LaSalle']是詞典,而-(減法)操作沒有爲詞典數據類型定義。此外,norm是爲類似數組的數據類型定義的。

因此,如果你真的需要使用scipy.spatial.distance.euclidean對於你的情況,你需要創建一個類爲您critics,並在你的類,你需要通過定義__sub__方法,該方法返回一個類似數組的數據類型重載-運營商。

+1

什麼是最好的情況下,找到距離呢? – ajkumar25

+0

你是什麼意思?這取決於你如何定義距離。 – ysakamoto

+0

@sakamoto謝謝。 – ajkumar25

0

我打了一個漂亮的API與醜陋的代碼:

http://vectordict.readthedocs.org/en/latest/vector.html#metrics

重要:我不建議使用在所有這些代碼(我是正確的重寫的話),只看到它是如何工作的,並也許尊重API但不使用代碼。

通過覆蓋+/-/*//「線性代數方式,您可能會對如何使用字典以及如何實現它以及如何使其生活更輕鬆返回來執行«math»感興趣

這裏是L2標準的實施:的sqrt(self.dot(個體經營))

https://github.com/jul/ADictAdd_iction/blob/master/vector_dict/VectorDict.py#L972

我主張用API是與對象線性algebrae定義一致所以很容易使感你讀了什麼。

from vector_dict.VectorDict import cos 
from vector_dict.VectorDict import convert_tree, VectorDict 
crit = {'Lisa Rose': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.5, 
         'Just My Luck': 3.0, 'Superman Returns': 3.5, 'You, Me and Dupree': 2.5, 
         'The Night Listener': 3.0}, 
      'Gene Seymour': {'Lady in the Water': 3.0, 'Snakes on a Plane': 3.5, 
          'Just My Luck': 1.5, 'Superman Returns': 5.0, 'The Night Listener': 3.0, 
          'You, Me and Dupree': 3.5}, 
      'Michael Phillips': {'Lady in the Water': 2.5, 'Snakes on a Plane': 3.0, 
           'Superman Returns': 3.5, 'The Night Listener': 4.0}, 
      'Claudia Puig': {'Snakes on a Plane': 3.5, 'Just My Luck': 3.0, 
          'The Night Listener': 4.5, 'Superman Returns': 4.0, 
          'You, Me and Dupree': 2.5}, 
      'Mick LaSalle': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
          'Just My Luck': 2.0, 'Superman Returns': 3.0, 'The Night Listener': 3.0, 
          'You, Me and Dupree': 2.0}, 
      'Jack Matthews': {'Lady in the Water': 3.0, 'Snakes on a Plane': 4.0, 
          'The Night Listener': 3.0, 'Superman Returns': 5.0, 'You, Me and Dupree': 3.5}, 
      'Toby': {'Snakes on a Plane': 4.5, 'You, Me and Dupree': 1.0, 'Superman Returns': 4.0}} 
dd = convert_tree(crit) 
print "cos" 
print cos(dd['Gene Seymour'], dd['Toby']) 
# 0.770024275094 
print "L2 distance" 
print dd['Gene Seymour'].norm() 
# 8.35164654425  
print "jaccard similarities" 
print dd['Gene Seymour'].jaccard(dd['Toby']) 
# 0.579335793358 

PS我猜想,如果你正在進行規範微積分,那是爲了進行比較,並且我跳到了你想做相似性測量的結論。

+0

它很棒。我將叉回購,並嘗試貢獻:) – ajkumar25

+0

實際上,新的重寫是在這裏。 https:// github。com/jul /射箭 在我看來,使用defaultdict不如特性有趣。 射箭的命名是愚蠢的,我必須重新命名這些東西(我的意思是,我甚至不記得自己的命名約定)。 當我感覺到/問題時,我停止了對它的工作。但是,使用py3打包的故障真的讓我失望了一個月,所以我停止了對它的研究。我對py3 vs py2戰爭無能爲力。 – user1458574