正誤表 (2011年5月9日更新)

このページの作成には、O'Reilly Media社の Unconfirmed Errata も参考にしました。

Last modified: Mon May 9 13:48:04 JST 2011

はじめに

ページ 場所 修正内容 備考
ix 下から2行目
 string_list[2]
 ↓
 string_list[1]

x 下から6行目
 print [v*10 for v in l1 if v1>4]
 ↓
 print [v*10 for v in l1 if v>4]

1章 集合知への招待

2章 推薦を行う

ページ 場所 修正内容 備考
9 実行コードの最後の行
{'Snakes on a Plane':4.5,'You, Me and Dupree':1.0}
 ↓
{'Snakes on aPlane':4.5,'Superman Returns':4.0,'You, Me and Dupree':1.0}
'Superman Returns'の評価の値が抜けている。
10 実行コードの2行目
>> sqrt(pow(5-4,2)+pow(4-1,2))
3.1622776601683795
 ↓
>> sqrt(pow(4.5-4,2)+pow(1-2,2))
1.1180339887498949
Tobyの評価の値が誤っている。そのため、両者の距離も違う。
11 実行コードの1行目
>> 1/(1+sqrt(pow(5-4,2)+pow(4-1,2)))
0.2402530733520421
 ↓
>> 1/(1+sqrt(pow(4.5-4,2)+pow(1-2,2)))
0.47213595499957939
同上
11 sim_distance関数の真ん中の行
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2) 
              for item in prefs[person1] if item in prefs[person2]])
 ↓
sum_of_squares=sum([pow(prefs[person1][item]-prefs[person2][item],2)
              for item in si])
誤りではないがコードが冗長である。
11 sim_distance関数の最後の行
return 1/(1 + sum_of_squares)
 ↓
return 1/(1 + sqrt(sum_of_squares))
合計の平方根をとる必要がある。
9 実行コードの5行目
>>>reload(recommendations)
 ↓
>>>import recommendations
このページまでにrecommendationsをimportしていないので、reload はできない。
11 2.3.1 の最後の実行文の結果
0.148148148148 
 ↓
0.294298055086
sim_distance関数に sqrt 関数を追加した結果、戻り値が変わった。
14 2.3.3の第2パラグラフ
sim_vectorと指定する事で
 ↓
sim_distanceと指定する事で

17 2.4 の最後の実行文の結果
[(3.5002478401415877, 'The Night Listener'), (2.7561242939959363, 'Lady in the 
Water'), (2.4619884860743739, 'Just My Luck')]
 ↓
[(3.457128694491423, 'The Night Listener'), (2.7785840038149239, 'Lady in the
Water'), (2.4224820423619167, 'Just My Luck')]
sim_distance関数に sqrt 関数を追加した結果、戻り値が変わった。
20 最後の行
http://code.google.com/p/pydelicious/source
 ↓
http://code.google.com/p/pydelicious/downloads/list
URLが変更された
21 2.6.2のコード コードの先頭に次を追加する
import time

24 calculateSimilarItems関数の仮引数
def calculateSimilarItems(prefs,n=10):
 ↓
def calculateSimilarItems(prefs,n=10,similarity=sim_distance):
様々な類似度を利用できるように、similarity引数を追加する。
25 calculateSimilarItems関数でtopMatches関数呼び出しの実引数
scores=topMatches(itemPrefs,item,n=n,similarity=sim_distance)
 ↓
scores=topMatches(itemPrefs,item,n,similarity)
同上
26 表2-3 正規化の行を次に変更する
3.183  2.598  2.473
 ↓
3.183  2.473  2.598

3章 グループを見つけ出す

ページ 場所 修正内容 備考
33 節の番号
3.3.2
 ↓
3.2.2

34 getwords関数の4行目
words=re.compile(r'[^A-Za-z]+').split(txt)
 ↓
words=re.compile(r'[^A-Za-z]+').split(txt)
英文字を表す正規表現なので、Zとaの間の^は不要。
34 20行目
次のコードをgeneratefeedvetor.pyの
 ↓
次のコードをgeneratefeedvector.pyの
vectorのcが足りない。
47~48 kcluster関数の8行目以降
9行目以降の次の部分のインデントを1段浅くする、つまり先頭の空白を2つずつ削除する。
    lastmatches=None
    ...
        clusters[i]=avgs

48 21行 次の行のインデントを2段浅くする、つまり先頭の空白を4つ削除する。
return bestmatches

48 下から5行目
[rownames[r] for r in k[0]]
 ↓
[blognames[r] for r in kclust[0]]

48 下から2行目
rownames[r] for r in k[1]]
 ↓
[blognames[r] for r in kclust[1]]

49~51 3.7 嗜好のクラスタ Zeboサイトは閉鎖されたようだ。www.zebo.comもmember.zebo.comも応答がない。
50 35行 currentuserの行のインデントを1段深くする
        itemowners[txt][currentuser]=1
      currentuser+=1
 ↓
        itemowners[txt][currentuser]=1
        currentuser+=1
    
現在のインデントだと、アイテムリストのないユーザに対しても ID が降られるため,51ページの実行コードでアイテムリストをzebo.txtへ出力したとき、 アイテムのない多くユーザまでも出力されてしまう。

4章 検索とランキング

ページ 場所 修正内容 備考
63 実行コードの最後の行
BeautifulSoup 3.1.0.1 では次のコードを実行すると、実行エラーとなる。
>> crawler.crawl(pagelists)
Could not parse page http://kiwitobes.com/wiki/Perl.html

その原因は、Perl.htmlの680行目に次のaタグの記述誤りである。
<div class="printfooter">
  Retrieved from "<a </div>
そのため、別のURL(例えばhttp://www.w3c.org/)を指定して実行するか、
BeautifulSoup 3.0.7aをインストールする。

65 図4-1 検索エンジンのスキーマ
wordlocation、linkwordsのテーブルに存在するrowidフィールドが書かれていない。
rowidフィールドは各レコードのIDを格納するデフォルトフィールドなので、本質的な誤りではない。
66 gettextonlyメソッドの2行目
if v==Null:
 ↓
if v==None:
Nullという値はpythonにはなく、Noneである。日本語訳では修正されているが,PCI_Code.zipでは修正されていない
68 addlinkrefメソッドの2行目
words=self.separateWords(linkText)
 ↓
words=self.separatewords(linkText)
日本語訳では修正されているが,PCI_Code.zipでは修正されていない
70 getmatchrowsメソッドのfor文の3行目
"select rowid from wordlist where word='%s'" % word).fetchone()
 ↓
"select rowid from wordlist where word='%s'" % word.lower()).fetchone()
addtoindexメソッドでは、separatewordsメソッドによって小文字に変換した単語のリストを生成して、wordlistテーブルに登録しているので、問い合あせのときも検索語を小文字に変換する必要がある。
70 getmatchrowsメソッドの最後のexecute文
fullquery='select %s from %s where %s' % (fieldlist,tablelist,clauselist)
 ↓
if tablenumber == 0: return None,wordids
fullquery='select %s from %s where %s' % (fieldlist,tablelist,clauselist)
問い合わせ q にマッチするページが存在しない場合,このexecute文には from 節と where節がないため実行エラーとなるため。
72 queryメソッドの1行目
rows,wordids=self.getmatchrows(q)
 ↓
rows,wordids=self.getmatchrows(q)
if rows == None: return
問い合わせ q にマッチするページが存在しない場合は,以降の処理が実行エラーとなるため。
72 queryメソッドの1行目
rankedscores=sorted([(score,url) for (url,score) in scores.items()],reverse=1)
 ↓
rankedscores=[(score,url) for (url,score) in scores.items()]
rankedscores.sort()
rankedscores.reverse()
sorted関数はpython 2.3ではサポートされていないため、日本語版のコードはエラーとなる。修正前のPCI_Code.zipのコードはpythonのどのバージョンでも実行できる。
74 e.query('functional programming')の実行結果 検索結果のページの順番とスコアはこの本の値と異なる。各ページの内容が変更されているためである。
78 図4.3
ページ C より右に出ている線が3本なのを4本に変更する


81 4.6.3節の1行目
ランク付けする協力な方法としては
 ↓
ランク付けする強力な方法としては

81 linktextscore関数の10行目 次の部分のインデントを1段深くする
linkscores[toid]+=pr

90 backPropagate関数の最後の行 次の部分のインデントを1段深くする
self.wi[i][j]=self.wi[i][j]+N*change

91 updatedatabase関数の3行目 次の部分のインデントを1段深くする
for i in range(len(self.wordids)):

5章 最適化

ページ 場所 修正内容 備考
97 5.2 節の最初のコード
 [4,4,4,2,2,6,6,5,5,6,6,0]
 ↓ 
 [1,4,3,2,7,3,6,3,2,4,5,3]
98ページの実行例の変数 s の値に合わせた。
98 5.2 節のprintschedule関数のfor文の2~3行
out=flights[(origin,destination)][int(r[d])]
ret=flights[(destination,origin)][int(r[d+1])]
 ↓ 
out=flights[(origin,destination)][int(r[d*2])]
ret=flights[(destination,origin)][int(r[d*2+1])]
解 r は人数 d の2倍の長さなので、d を2倍する必要がある。日本語版では修正されているが、PCI_Code.zipでは修正されていない。
98 2番目のコードの実行例
>>> import optimization
>>> s=[1,4,3,2,7,3,6,3,2,4,5,3]
>>> optimization.printschedule(s)
   Seymour    Boston  8:04-10:11 $ 95 12:08-14:05 $142
    Franny    Dallas 12:19-15:25 $342 10:51-14:16 $256
     Zooey     Akron 10:53-13:36 $189  9:58-12:56 $249
      Walt     Miami  9:15-12:29 $225 16:50-19:26 $304
     Buddy   Chicago 16:43-19:00 $246 10:33-13:11 $132
       Les     Omaha 11:08-13:07 $175 15:07-17:21 $129
 ↓
>>> import optimization
>>> s=[1,4,3,2,7,3,6,3,2,4,5,3]
>>> optimization.printschedule(s)
   Seymour       BOS  8:04-10:11 $ 95 12:08-14:05 $142
    Franny       DAL 10:30-14:57 $290  9:49-13:51 $229
     Zooey       CAK 17:08-19:08 $262 10:32-13:16 $139
      Walt       MIA 15:34-18:11 $326 11:08-14:38 $262
     Buddy       ORD  9:42-11:32 $169 12:08-14:47 $231
       Les       OMA 13:37-15:08 $250 11:07-13:24 $171
空港名はBostonではなくBOSのように省略記号で表示される。
また、printschedule関数の上のバグを修正したため、行き帰りの飛行便の出力が変わった。
99 schedulecost関数のfor文の最初のブロック
  outbound=flights[(origin,destination)][int(sol[d])]
  returnf=flights[(destination,origin)][int(sol[d+1])]  
 ↓
  outbound=flights[(origin,destination)][int(sol[d*2])]
  returnf=flights[(destination,origin)][int(sol[d*2+1])]  
日本語版では修正されているが、PCI_Code.zipでは修正されていない。
100 schedulecost関数の2番目の for文の最初のブロック
  outbound=flights[(origin,destination)][int(sol[d])]
  returnf=flights[(destination,origin)][int(sol[d+1])]  
 ↓
  outbound=flights[(origin,destination)][int(sol[d*2])]
  returnf=flights[(destination,origin)][int(sol[d*2+1])]  
日本語版では修正されているが、PCI_Code.zipでは修正されていない。
100 schedulecost関数の2番目のfor文の後のif文
if latestarrival>earliestdep: totalprice+=50
 ↓
if latestarrival < earliestdep: totalprice+=50
「レンタカーの返却時刻 earliestdep が借り出し時刻 latestarrival よりも遅くなる」の逆になっている。 日本語版では修正されているが、PCI_Code.zipでは修正されていない。
100 真ん中の実行コード
reload(opptimization)
 ↓
reload(optimization)
スペルミス。pが1つ多い。
100 真ん中の実行コード出力
optimization.schedulecost(s)
5285
 ↓
optimization.schedulecost(s)
4585
上述のバグを修正した結果、出力も変わった。
100 5.4 節の5行目
出立便と帰宅便が9フライトずつあるので、
domainには人数の2倍の数の(0,8)を並べたリストを与える。
 ↓
出立便と帰宅便が10フライトずつあるので、
domainには人数の2倍の数の(0,9)を並べたリストを与える。
schedule.txtには出立便と帰宅便が10フライトずつ書かれているので。
101 randomoptimize関数の9行目
   # コストの取得
    cost=costf(r)
 ↓  
    # コストの取得
    cost=costf(r)
コメントのインデントを1文字だけ下げる
101 randomoptimize関数の最後の行
return r
 ↓
return bestr

101 実行例の2行目
>>> domain=[(0,8)]*(len(optimization.people)*2)
 ↓
>>> domain=[(0,9)]*(len(optimization.people)*2)
出立便と帰宅便が10フライトずつあるので。
103 hillclimb関数のfor文
if sol[j]<domain[j][1]:
  neighbors.append(sol[0:j]+[sol[j]+1]+sol[j+1:])
if sol[j]>domain[j][0]:
  neighbors.append(sol[0:j]+[sol[j]-1]+sol[j+1:])
 ↓
if sol[j]>domain[j][0]:
  neighbors.append(sol[0:j]+[sol[j]-1]+sol[j+1:])
if sol[j]<domain[j][1]:
  neighbors.append(sol[0:j]+[sol[j]+1]+sol[j+1:])
sol[j]の範囲の検査が正しくない。 sol[j]を1増減したとき、domain[j][0]以上で、domain[j][1]以下の値になる必要がある。
105 annealingoptimize関数の太字の部分
p=pow(math.e,(-eb-ea)/T)
 ↓
p=pow(math.e,-abs(eb-ea)/T)
104ページの最後の行の確率 p の式と異なっている。 日本語版では修正されているが、PCI_Code.zipでは修正されていない。
108 上から13行目
scores=[(costf(v),v) for v in pop]
 ↓
scores=[(costf(v),v) for v in pop if v != None]
mutate関数がNoneを返すことがある。
108 最後の行目
突然変異で作る者の割合
 ↓
突然変異で作る確率
geneticoptimize関数ではmutate関数を呼ぶ場合を random.random() < mutprob で判断しているので、 mutprobは割合ではなく確率である。
110~116 5.8 節 次のページに書かれているように Kayak API は現在サポートされていない。"anonymous access to kayak API denied"のXML文書が返される。
http://www.kayak.com/labs/api/search/
Kayak Search API is no longer supported
api.kayak.comにアクセスしても警告のHTML文書が返される。
117 5.8 節
('James', ('Hercules', 'Athena'))]
 ↓
('Neil', ('Hercules', 'Athena'))]
118ページと120ページの実行例の出力にあわせると Neil である。
119 dormcost関数の3行目
slots=[0,0,1,1,2,2,3,3,4,4]
 ↓
for i in range(len(dorms)): slots+=[i,i]
printsolution関数と同じように、寮 dorms の個数が変更されてもよいように修正する。
119 5.9.3 の実行例 reload(dorm)の前に次の文を追加する
import optimization
randomoptimize関数などを使うため。
119 5.9.3 の実行例
optimization.geneticoptimize(dorm.domain,dorm.dormcost)
 ↓
s=optimization.geneticoptimize(dorm.domain,dorm.dormcost)
最後の行のdorm.printsolution(s)で解 s を参照するために必要である。
124 drawnetwork関数の最後の行
img.show()
 ↓
img.save('social.jpg','JPEG')
バグではないが、画像をファイルに保存したい場合はこの部分を修正する。
124 ページ中央の実行例
drawnetwork(sol)
 ↓
socialnetwork.drawnetwork(sol)
モジュール名が必要である。
124 図5-9 drawnetwork関数では、人名 n を表示位置 p に次の文で表示しているため、ノードに対応する人名の位置がプログラムと異なる。
draw.text(p,n,(0,0,0))
figure5-9.jpgのように、人名の左上がノードの位置に表示されるべきである。

6章 ドキュメントフィルタリング

ページ 場所 修正内容 備考
133 最初の段落の最後の文
それよりも単語が同じカテゴリのドキュメントで見つかるにつれ、値をだんだんと0に近づける
 ↓
それよりも単語が別のカテゴリのドキュメントで見つかるにつれ、値をだんだんと0に近づける
同じカテゴリに見つかる単語が増えた場合は、確率の値は0ではなく1に近づくため、逆になってしまう。
142 最後の実行コードの4行目 次の行を削除する
cl.setdb('test.db')
この節ではまだDBを使わない
143 実行コードの10行目
 >>> cl.classify('quick money')
 'good'
 ↓
 >>> cl.classify('quick money')
 'bad'

143 6.7.1節の2行目
 多くのユーザによって同時によってトレーニングされたり、
 ↓
 多くのユーザによって同時にトレーニングされたり、

146 12行目
 これはhttp://kiwitobes.lcom/feeds/python_search.xml
 ↓
 これはhttp://kiwitobes.com/feeds/python_search.xml
余分な l がある。
146 read関数の14行目
 print 'Guess: '+str(classifier.classify(entry))
 ↓
 print 'Guess: '+str(classifier.classify(fulltext))
日本語訳では修正されているが,PCI_Code.zipでは修正されていない。 ただし、6.9節で定義している entryfeatures 関数を使うときは、この引数名を fulltext から entry に戻す必要がある。
146 read関数の17行目
 classifier.train(entry,cl)
 ↓
 classifier.train(fulltext,cl)
同上
147 真ん中の実行コード 最初の行に次を追加
 >>> import docclass

149 entryfeatures関数の8行目
summarywords=[s.lower() for s in splitter.split(entry['summary']) 
 ↓
summarywords=[s for s in splitter.split(entry['summary']) 
大文字の単語を識別するため、ディクショナリ f に登録するときに小文字に変換する。
149 entryfeatures関数の14行目
f[w]=1
 ↓
f[w.lower()]=1
同上
149 entryfeatures関数の19行目
f[twowords]=1
 ↓
f[twowords.lower()]=1
同上
149 entryfeatures関数の21行目
f['Publisher:'+entry['publisher']]=1
 ↓
f['Creator:'+entry['author']]=1
f['Publisher:'+entry['publisher']]=1
creatorフィールドを特徴として登録するため。なお、feedparserでは creator フィールドは author フィールドに統一して扱っている。

7章 決定木によるモデリング

ページ 場所 修正内容 備考
156 表7-1 表7-1の10行(Dig)と11行(Google)の間に次の行を挿入
 Slashdot UK No 21 None

163 buildtree関数の1行目
if len(rows)==0: return decisionnode()
 ↓
if len(rows)==0: return None
buildtree関数で、resultsがNoneのノードを生成するのは枝の場合だけないので、tbとfbを指定しないdecisionnode()というコンストラクタは誤りである。
164 buildtree関数の最後から5と6行目
trueBranch=buildtree(best_sets[0])
falseBranch=buildtree(best_sets[1])
 ↓
trueBranch=buildtree(best_sets[0],scoref)
falseBranch=buildtree(best_sets[1],scoref)
buildtree関数の引数scoref をbuildtree関数に渡すように変更した。
164 buildtree関数の最後から4行目
    falseBranch=buildtree(best_sets[1],scoref)
     return decisionnode(col=best_criteria[0],value=best_criteria[1],
                        tb=trueBranch,fb=falseBranch)
 ↓
    falseBranch=buildtree(best_sets[1],scoref)
    return decisionnode(col=best_criteria[0],value=best_criteria[1],
                        tb=trueBranch,fb=falseBranch)
buildtree関数のreturn文のインデントを前の行と同じにする。
165 実行例の出力の7行目
 F-> 0:slashdot?
  ↓
F-> 0:slashdot?
出力のインデントの誤り。先頭の空白が1つ多い。
174 Zillow APIについて Zillow APIのディベロッパキーを取得する方法は http://www.zillow.com/howto/api/APIOverview.htm を参照。
getaddressdata関数で使用しているGetDeepSearchResults APIの仕様は http://www.zillow.com/howto/api/GetDeepSearchResults.htmを参照。

174 getaddressdata関数の12行目から21行目
  if 1:
    zipcode=doc.getElementsByTagName('zipcode')[0].firstChild.data
    ...
  else:
    return None
 ↓
  try:
    zipcode=doc.getElementsByTagName('zipcode')[0].firstChild.data
    ...
  except:
    return None
日本語訳では修正されているが,PCI_Code.zipでは修正されていない。 Zillowへの検索要求の際にエラーが発生するため、日本語訳のコードが正しい。
174 getaddressdata関数の下から5行目
 rooms=doc.getElementsByTagName('totalRooms')[0].firstChild.data
 ↓
 rooms=1
PCI_Code.zipでは修正後の行のように修正されている。 Zillow APIではtotalRooms がサポートされなくなったため。
175 getpricelist関数の5行目
l1.append(data)
 ↓
if data!=None:
  l1.append(data) 
zillowサイトへの検索要求がエラーで終わった場合、getaddressdata関数の戻り値Noneを変数l1に追加しないため。
176 7.12節 HotOrNot API Profile -- www.programmableweb.com に書かれているようにHotornotサイトのAPIは2008年で終了したため利用できない。
179 実行例の1, 2行目
south=treepredict2.mdclassify((None,None,'South'),hottree)
midat=treepredict2.mdclassify((None,None,'Mid Atlantic'),hottree)
 ↓
south=treepredict.mdclassify((None,None,'South'),hottree)
midat=treepredict.mdclassify((None,None,'Mid Atlantic'),hottree)
モジュールの名前はtreepredict2ではなくtreepredictである。

8章 価格モデルの構築


9章 高度な分類手法:カーネルメソッドとSVM

ページ 場所 修正内容 備考
214 31行目
 advanceclassify.pyという名前のファイルを作成し、
 ↓
 advancedclassify.pyという名前のファイルを作成し、

215 32行目
 plot(xdn,ydn,'ro')
 ↓
 plot(xdn,ydn,'r+')

216 6行目
 そうでなければ×として表示されている。
 ↓
 そうでなければ+として表示されている。

222 31行目
 elif v=='no':return 0
 ↓
 elif v=='no':return -1

10章 特徴を発見する

11章 進化する知性

12章 アルゴリズムのまとめ


ċ
module.txt
(3k)
Bobo2016,
2009/08/03 18:36
Comments