Il existe de nombreuses façons de calculer à quel point une donnée est similaire à une autre. http://wikiwiki.jp/cattail/?%CE%E0%BB%F7%C5%D9%A4%C8%B5%F7%CE%A5
Parmi eux, la distance euclidienne, le coefficient de corrélation du facteur de produit de Pearson et le coefficient de Jaccard sont implémentés en python. Programmation collective des connaissances Chapitre 2 Référence. https://www.oreilly.co.jp/books/9784873113647/
Une distance générale similaire à celle des mathématiques du collège et du lycée. S'il est à 2 ou 3 dimensions, il peut être représenté par une figure et une image peut être créée, mais il n'est pas possible d'imaginer d'autres dimensions. Mais ce que je fais est fondamentalement le même que le troisième et inférieur.
(a_1, a_2, a_3, ... a_i), (b_1, b_2, b_3, ... b_i)
Lorsqu'il y a deux données telles que, la distance euclidienne d entre ab est
d = \sqrt{(a_1 - b_1)^2 + (a_2 -b_2)^2 + (a_3 -b_3)^2 + ...+(a_i-b_i)^2}
Si cela reste tel quel, la distance sera renvoyée, mais je veux une valeur facile à comprendre en tant que degré de similitude, par exemple plus les valeurs sont similaires de 0 à 1, plus elles sont proches de 1. Une telle valeur peut être obtenue en ajoutant 1 à ce d et en prenant le nombre inverse pour éviter une erreur de division à 0.
1/(1 + d)
Ce qui suit est l'implémentation de ceci en python.
recommendation.py
import math
def sim_distance(prefs, person1, person2):
#Liste des choses que personne1 et personne2 évaluent
si = {}
for item in prefs[person1]:
if item in prefs[person2]:
si[item] = 1
#La similitude est de 0 si ni personne1 ni personne2 ne sont
if len(si) == 0 :
return 0
#Carré de différence pour chaque élément
squares = [(prefs[person1][item] - prefs[person2][item]) ** 2 for item in si]
sum_of_sqrt = math.sqrt(sum(squares))
return 1/(1 + sum_of_sqrt)
Essayez de trouver la similitude en utilisant les données suivantes. critcs stocke plusieurs films et la note de 5 points de chaque personne pour ces films.
critics = {
'Lisa Rose': {
'Lady in the Water': 2.5,
'Snakes on a Plane': 3.5,
'Just My Luck': 3.0,
'Superman Returns': 3.5,
'The Night Listener': 3.0,
'You, Me and Dupree': 2.5,
},
'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,
}
}
$ python
Python 3.5.1 (default, Nov 7 2016, 22:30:16)
[GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.42.1)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import recommendation
>>> recommendation.sim_distance(critics, 'Lisa Rose', 'Gene Seymour')
0.29429805508554946
Si les données ne sont pas normalisées, trouver simplement la distance euclidienne ne donnera que des résultats subtils. Par exemple, lors de l'évaluation d'un film, lorsque M. A et M. B ont des goûts similaires. Dans ce cas, je veux que MM. A et B aient un degré élevé de similitude. Supposons que les évaluations des films X, Y et Z par deux personnes soient les suivantes.
Film X | Film Y | Film Z | |
---|---|---|---|
Monsieur A | 3 | 1.5 | 3.5 |
Monsieur B | 4 | 2 | 5 |
Bien que les goûts semblent similaires, M. A a une évaluation plutôt sèche et M. B a une évaluation douce. Lorsque cela est calculé par la sim_distance ci-dessus, la similitude est de 0,348. Si les points d'évaluation sont biaisés ou obstrués, quelle que soit la similitude des goûts, la distance euclidienne ne peut pas les couvrir.
Le coefficient de corrélation du facteur produit de Pearson est utilisé dans de tels cas. Quantifiez la corrélation, pas la simple distance entre les données.
\frac{ \sum_{i=1}^{n} (X_i - \bar{X})(Y_i - \bar{Y}) } { \sqrt{ \sum_{i=1}^{n} (X_i - \bar{X})^2} \sqrt{ \sum_{i=1}^{n} (Y_i - \bar{Y})^2} }
La barre supérieure est la valeur moyenne. Je ne suis pas sûr de ce que je fais simplement en regardant la formule, mais la molécule est codisperse et le dénominateur est l'écart type de chaque donnée. Peut-il être considéré comme un calcul de similarité cosinus? (Je ne comprends pas bien ...)
Référence: http://mathtrain.jp/correlation http://aoki2.si.gunma-u.ac.jp/lecture/Soukan/pearson.html http://d.hatena.ne.jp/sleepy_yoshi/20110325/p1
Implémentez ceci en python
def sim_pearson(prefs, person1, person2):
si = {}
for item in prefs[person1]:
if item in prefs[person2]:
si[item] = 1
n = len(si)
if n == 0: return 0
mean1 = sum([prefs[person1][item] for item in si]) / n
mean2 = sum([prefs[person2][item] for item in si]) / n
variance1 = math.sqrt(sum([((prefs[person1][item] - mean1) ** 2) for item in si]))
variance2 = math.sqrt(sum([((prefs[person2][item] - mean2) ** 2) for item in si]))
covariance = sum([(prefs[person1][item] - mean1)*(prefs[person2][item] - mean2) for item in si])
if variance1 * variance2 == 0: return 0
return covariance / (variance1 * variance2)
>>> data = {'Asan': {'X': 3.0,'Y': 1.5,'Z': 3.5,},'Bsan': {'X': 4.0,'Y': 2.0,'Z': 5.0,}}
>>> recommendation.sim_pearson(data, 'Asan', 'Bsan')
0.9958705948858225
Un nombre beaucoup plus élevé que la distance euclidienne est sorti. Ensuite, j'ai pensé que le coefficient de corrélation du facteur produit de Pearson était le plus fort, mais il ne pouvait pas être bien compris à moins qu'il ne s'agisse d'une relation linéaire sur le diagramme de dispersion, les données de comparaison devaient être distribuées normalement et les valeurs aberrantes étaient Il semble que s'il y en a, il sera traîné par lui, alors nous devons remplir les conditions dans une certaine mesure.
Dans la programmation des connaissances collectives, la fonction de recherche du coefficient de corrélation du facteur produit du même Pearson a été implémentée comme suit.
def sim_pearson(prefs, p1, p2):
'''
Returns the Pearson correlation coefficient for p1 and p2.
'''
# Get the list of mutually rated items
si = {}
for item in prefs[p1]:
if item in prefs[p2]:
si[item] = 1
# If they are no ratings in common, return 0
if len(si) == 0:
return 0
# Sum calculations
n = len(si)
# Sums of all the preferences
sum1 = sum([prefs[p1][it] for it in si])
sum2 = sum([prefs[p2][it] for it in si])
# Sums of the squares
sum1Sq = sum([pow(prefs[p1][it], 2) for it in si])
sum2Sq = sum([pow(prefs[p2][it], 2) for it in si])
# Sum of the products
pSum = sum([prefs[p1][it] * prefs[p2][it] for it in si])
# Calculate r (Pearson score)
num = pSum - sum1 * sum2 / n
den = sqrt((sum1Sq - pow(sum1, 2) / n) * (sum2Sq - pow(sum2, 2) / n))
if den == 0:
return 0
r = num / den
return r
https://github.com/arthur-e/Programming-Collective-Intelligence/blob/master/chapter2/recommendations.py
Quand j'ai regardé ce code dans ce livre, je ne pouvais pas comprendre comment transformer la formule ci-dessus en ce type d'implémentation, j'ai donc implémenté la formule comme avant. Quand j'ai vérifié avec scipy.stats.pearsonr
dans scipy, le code que j'ai implémenté et ce code a renvoyé la même valeur. Peu importe l'implémentation que vous utilisez, mais je ne sais pas comment transformer l'expression pour obtenir le code affiché dans la programmation d'intelligence collective ci-dessous ... Si vous le savez, faites-le moi savoir.
Calculez la similitude entre les ensembles.
J( A, B ) = \frac { \mid A \cap B \mid } { \mid A \cup B \mid } = \frac { \mid A \cap B \mid } { |A| + |B| - \mid A \cap B \mid }
https://en.wikipedia.org/wiki/Jaccard_index#Tanimoto_similarity_and_distance
Il est utilisé lorsque vous souhaitez calculer la similitude entre les phrases. Extrayez les mots utilisés dans la phrase A et les mots utilisés dans la phrase B, et trouvez la valeur de l'ensemble de somme des mots et de la partie commune. Dans de tels cas, plus il y a de mots couramment utilisés, plus la similitude est élevée.
def sim_jaccard(prefs, a, b):
si = {}
for item in prefs[a]:
if item in prefs[b]:
si[item] = 1
n = len(si)
if n == 0:
return 0
len_a = len(prefs[a])
len_b = len(prefs[b])
return n / (len_a + len_b - n)
>>> data = {'machine-learning': ['DNN', 'python', 'chainer', 'scikit-learn'], 'python-waf': ['python', 'django', 'flask', 'pyenv']}
>>> recommendation.sim_pearson(data, 'machine-learning', 'python-waf')
0.14285714285714285
Recommended Posts