2016-07-14 2 views
0

dicts (sklearn)에서 유클리드 거리를 계산 : 사실 그들은 위키 텍스트에서 단어가 포함 된나는 두 <code>dictionaries</code> 이미 다음과 같이 내 코드에서 계산이

X = {'a': 10, 'b': 3, 'c': 5, ...} 
Y = {'a': 8, 'c': 3, 'e': 8, ...} 

, 그러나 이것은 무슨 뜻인지 보여주기 위해 봉사해야한다 . 반드시 같은 키를 포함하지는 않습니다.

가 처음에 나는이 같은 sklearn의 페어 메트릭 사용하고 싶었 다음 shape에 액세스하려고

-------------------------------------------------------------------------- 
AttributeError       Traceback (most recent call last) 
<ipython-input-124-7ff03bd40683> in <module>() 
     6 biden = wiki[wiki['name'] == 'Joe Biden']['tf_idf'][0] 
     7 
----> 8 obama_biden_distance = pairwise_distances(obama, biden, metric='euclidean', n_jobs=2)[0][0] 

/home/xiaolong/development/anaconda3/envs/coursera_ml_clustering_and_retrieval/lib/python3.4/site-packages/sklearn/metrics/pairwise.py in pairwise_distances(X, Y, metric, n_jobs, **kwds) 
    1205   func = partial(distance.cdist, metric=metric, **kwds) 
    1206 
-> 1207  return _parallel_pairwise(X, Y, func, n_jobs, **kwds) 
    1208 
    1209 

/home/xiaolong/development/anaconda3/envs/coursera_ml_clustering_and_retrieval/lib/python3.4/site-packages/sklearn/metrics/pairwise.py in _parallel_pairwise(X, Y, func, n_jobs, **kwds) 
    1058  ret = Parallel(n_jobs=n_jobs, verbose=0)(
    1059   fd(X, Y[s], **kwds) 
-> 1060   for s in gen_even_slices(Y.shape[0], n_jobs)) 
    1061 
    1062  return np.hstack(ret) 

AttributeError: 'dict' object has no attribute 'shape' 

이 뭔가처럼 읽어 나에게 그러나

from sklearn.metrics.pairwise import pairwise_distances 

obama = wiki[wiki['name'] == 'Barack Obama']['tf_idf'][0] 
biden = wiki[wiki['name'] == 'Joe Biden']['tf_idf'][0] 

obama_biden_distance = pairwise_distances(obama, biden, metric='euclidean', n_jobs=2)[0][0] 

을,이 오류를 제공합니다 속성은 dict에는 없습니다. 나는 그것이 numpy 배열을 필요로한다고 생각한다. 사전에 어떤 특정 키가없는 경우 0 값으로 가정하면 sklearn 함수가 정확한 거리를 계산할 수 있도록 사전을 변환 할 수 있습니까?

답변

3

왜 희소 표현에서 직접하지 않습니까?

In [1]: import math 

In [2]: Y = {'a': 8, 'c':3,'e':8} 

In [3]: X = {'a':10, 'b':3, 'c':5} 

In [4]: math.sqrt(sum((X.get(d,0) - Y.get(d,0))**2 for d in set(X) | set(Y))) 
Out[4]: 9.0 
+0

. 또한 각 배열에는 존재하지 않는 키에 0이 있어야합니다. 그렇지 않으면 유클리드 거리가 잘못되었습니다. – Zelphir

+0

@Zelphir 웁스! 네가 옳아. 음, 코사인 거리를 사용 하시겠습니까? ㅎ. 그러나 실제로는 기본값을 사용하여'get' 메소드를 사용하여 작동하도록 수정할 수 있습니다. –

+0

@Zelphir 교차 대신에 합집합과 함께. 나는 이전에 많은 문서들로 구성된 큰 어휘와 코퍼라틴을 사용해 동일한 접근법을 사용 했었습니다. –

0

값이 출력되는 X.get(search_string,0)을 사용하려는 것 같습니다. 찾지 못하면 0입니다. 검색 문자열이 많으면 [X.get(s,0) for s in list_of_strings]을 수행하여 출력 목록을 푸시 할 수 있습니다.

2
당신은 당신의 사전의 모든 키를 사용하여 목록을 작성하여 시작할 수

은 (는이 목록을 정렬 할 것을 유의해야합니다) :

X = {'a': 10, 'b': 3, 'c': 5} 
Y = {'a': 8, 'c': 3, 'e': 8} 
data = [X, Y] 
words = sorted(list(reduce(set.union, map(set, data)))) 

이 파이썬 2에서 잘 작동하지만, 경우 Python 3을 사용하고 있다면 from functools import reduce 문장을 추가해야합니다 (이 문제를 확인하려면 @Zelphir에게 감사드립니다). 당신이 functools 모듈을 수입하지 않으려면 다음과 같은 코드에 의해 위의 코드 조각의 마지막 행을 대체 할 수

words = set(data[0]) 
for d in data[1:]: 
    words = words | set(d) 
words = sorted(list(words)) 

당신이 선택하는 방법이다 무엇 이건, 목록 words은 해주는데 따른 손쉬운 셋업하는 것을 가능하게 각 행이 사전 (표본)에 해당하고 해당 사전 (지형지 물)의 값이 해당 키에 해당하는 열에 배치되는 행렬을 올립니다.

from sklearn.metrics.pairwise import pairwise_distances as pd 
dist = pd(feats, metric='euclidean') 

다음 대화 형 세션이 작동하는 방법을 보여줍니다 :

feats = zip(*[[d.get(w, 0) for d in data] for w in words]) 

이 행렬은 scikit의 기능 pairwise_distance에 전달 될 수있는 마지막

In [227]: words 
Out[227]: ['a', 'b', 'c', 'e'] 

In [228]: feats 
Out[228]: [(10, 3, 5, 0), (8, 0, 3, 8)] 

In [229]: dist 
Out[229]: 
array([[ 0., 9.], 
     [ 9., 0.]]) 

, 당신은에 위의 코드를 래핑 수 함수를 사용하여 임의의 사전의 쌍 거리를 계산합니다.

def my_func(data, metric='euclidean'): 
    words = set(data[0]) 
    for d in data[1:]: 
     words = words | set(d) 
    words = sorted(list(words)) 
    feats = zip(*[[d.get(w, 0) for d in data] for w in words]) 
    return pd(feats, metric=metric) 

래퍼가 버전간에 작동하도록 reduce에 대한 호출을 피했습니다.

데모 :

가 50 만 데이터 포인트 이상이며, 내가 sklearn이 무거운하자 싶어
In [237]: W = {'w': 1} 

In [238]: Z = {'z': 1} 

In [239]: my_func((X, Y, W, Z), 'cityblock') 
Out[239]: 
array([[ 0., 15., 19., 19.], 
     [ 15., 0., 20., 20.], 
     [ 19., 20., 0., 2.], 
     [ 19., 20., 2., 0.]]) 
+0

또한'functools'에서'reduce'를 가져와야한다는 것에주의해야합니다. – Zelphir

+0

'functools'에서'reduce'를 가져와야한다는 것에주의해야합니다. 이전에 함수의 이름을 바꾸는 것을 잊어 버렸고 우연히 다른 함수를 두 번 실행하여 답변의 함수가 허용 된 답변의 다른 함수와 똑같이 작동한다고 생각하게되었습니다. 그러나 이름을 변경하고 다시 시도 할 때 몇 가지 문제가 발생하여 함수를 실행할 수 없습니다./어딘가에서 실수를 한 것일 수 있습니다. – Zelphir

+0

'reduce()'를'functools'에서 가져와야한다고 생각하는 이유는 무엇입니까? 내 코드의 유일한 수입 문장은'sklearn.metrics.pairwise from pairwise_distances from pd'입니다. (그런데, 당신은 당신이 pairwise distance를 계산하기 위해 그것을 사용하기를 원한다고 언급했습니다.) 다른 함수는 내장 함수, 즉'reduce()','map()','list()','set()','zip()'및'sorted() 'set.union()'과'dict.get()'과 같은 클래스 메소드에서. https://docs.python.org/2/library/functions.html#reduce에서 자신을 설득하십시오. – Tonechas