ValueError:调用函数时数学域错误,但单独运行正常

0 投票
2 回答
2276 浏览
提问于 2025-04-17 08:36

我知道这个问题可能是个新手问题,所以提前道个歉。我读过几本关于基础Python使用的书,现在正在做《编程集体智慧》里的教程,但我在我的代码块中遇到了一个错误:

ValueError: math domain error

我在谷歌上看到过很多类似的错误,但我不太明白为什么会发生。这个程序基本上是处理一个包含电影评论家及其评论的字典,然后第一个函数(sim_pearson)会告诉你两个评论家有多相似。这部分单独运行是没问题的。问题出在我尝试将一个用户与其他所有人进行比较,以便对评论家进行排名时。

这是代码:

# A dictionary of movie critics and their ratings of a small
# set of movies
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}}

from math import sqrt
#now lets use the pearson correlation score to see if we can get better results
#Returns the pearson correlation coefficient for p1 and p2
def sim_pearson(prefs, p1, p2):
    #get the list of mutually rated items
    si={}
    for item in prefs[p1]:
        if item in prefs[p2]:
            si[item]=1

    #find the number of elements
    n=len(si)

    # if they have no rating in common, return 0
    if n == 0: return 0

    #add up all the preferences
    sum1=sum([prefs[p1][it] for it in si])
    sum2=sum([prefs[p2][it] for it in si])

    #sum up 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 up the products
    pSum=sum([prefs[p1][it]*prefs[p2][it] for it in si])

    #Calculate 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


#lets check out the results
print 'here are the results from the Pearson algo:'
print sim_pearson(critics, 'Lisa Rose', 'Gene Seymour')
print sim_pearson(critics, 'Mick LaSalle', 'Jack Matthews')

#now lets rank critics to see who is the most simlair
#Returns the best matches for person from prefs dictionary
#Number of results and similarity functions are optional params.

def topMatches(prefs, person, n=5, similarity=sim_pearson):
    scores=[(similarity(prefs, person, other),other)
            for other in prefs if other != person]
    #sort the list so the highest scores appear at the top
    scores.sort()
    scores.reverse()
    return scores[0:n]


#lets see the ranking
print 'here are the top matches:'
print topMatches(critics, 'Toby', n=3)

错误追踪信息显示有3行代码出现了问题: 追踪信息(最近的调用在最后):

print topMatches(critics, 'Toby', n=3)
for other in prefs if other != person]
den=sqrt((sum1Sq-pow(sum1,2)/n)* sum2Sq-pow(sum2,2)/n)

我不太明白这里发生了什么。这里是书中预期的答案:

[(0.9912, 'Lisa Rose')], (0.9244, 'Mick LaSalle'), (0.8934, 'Claudia Puig')

提前谢谢你们

(坦白说:我数学不好,还在学习Python,所以可能有一些我没注意到的基本问题,但我仔细检查了书中的代码,觉得没有打错字或者其他问题)。

2 个回答

1

你不能用 math.sqrt() 来计算负数的平方根。如果你真的想这么做(不过我怀疑你 真的想这样...),那就用 cmath.sqrt() 来替代吧。

1

我觉得你这行代码缺少了一对括号:

den=sqrt((sum1Sq-pow(sum1,2)/n)* sum2Sq-pow(sum2,2)/n)

我觉得应该是这样的:

den=sqrt((sum1Sq-pow(sum1,2)/n)* (sum2Sq-pow(sum2,2)/n))

我拿了你的代码,做了这个修改,运行后得到了预期的结果。

撰写回答