Skip to content

Commit 3f197a6

Browse files
authored
Merge pull request apachecn#196 from Cugtyt/master
Use broadcasting to simplify autoNorm func in kNN.py
2 parents 22a5bd0 + 4d63742 commit 3f197a6

2 files changed

Lines changed: 28 additions & 94 deletions

File tree

src/python/2.KNN/kNN.py

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -199,12 +199,7 @@ def autoNorm(dataSet):
199199
maxVals = dataSet.max(0)
200200
# 极差
201201
ranges = maxVals - minVals
202-
normDataSet = zeros(shape(dataSet))
203-
m = dataSet.shape[0]
204-
# 生成与最小值之差组成的矩阵
205-
normDataSet = dataSet - tile(minVals, (m, 1))
206-
# 将最小值之差除以范围组成矩阵
207-
normDataSet = normDataSet / tile(ranges, (m, 1)) # element wise divide
202+
norm_dataset = (dataset - minvalue) / ranges
208203
return normDataSet, ranges, minVals
209204

210205

src/python/3.DecisionTree/DecisionTree.py

Lines changed: 27 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
import operator
1212
from math import log
1313
import decisionTreePlot as dtPlot
14+
from collections import Counter
1415

1516

1617
def createDataSet():
@@ -45,33 +46,12 @@ def calcShannonEnt(dataSet):
4546
Returns:
4647
返回 每一组feature下的某个分类下,香农熵的信息期望
4748
"""
48-
# 求list的长度,表示计算参与训练的数据量
49-
numEntries = len(dataSet)
50-
# 下面输出我们测试的数据集的一些信息
51-
# 例如:<type 'list'> numEntries: 5 是下面的代码的输出
52-
# print type(dataSet), 'numEntries: ', numEntries
53-
54-
# 计算分类标签label出现的次数
55-
labelCounts = {}
56-
# the the number of unique elements and their occurance
57-
for featVec in dataSet:
58-
# 将当前实例的标签存储,即每一行数据的最后一个数据代表的是标签
59-
currentLabel = featVec[-1]
60-
# 为所有可能的分类创建字典,如果当前的键值不存在,则扩展字典并将当前键值加入字典。每个键值都记录了当前类别出现的次数。
61-
if currentLabel not in labelCounts.keys():
62-
labelCounts[currentLabel] = 0
63-
labelCounts[currentLabel] += 1
64-
# print '-----', featVec, labelCounts
65-
66-
# 对于label标签的占比,求出label标签的香农熵
67-
shannonEnt = 0.0
68-
for key in labelCounts:
69-
# 使用所有类标签的发生频率计算类别出现的概率。
70-
prob = float(labelCounts[key])/numEntries
71-
# log base 2
72-
# 计算香农熵,以 2 为底求对数
73-
shannonEnt -= prob * log(prob, 2)
74-
# print '---', prob, prob * log(prob, 2), shannonEnt
49+
# 统计标签出现的次数
50+
label_count = Counter(data[-1] for data in dataSet)
51+
# 计算概率
52+
probs = [p[1] / len(dataSet) for p in label_count.items()]
53+
# 计算香农熵
54+
shannonEnt = sum([-p * log(p, 2) for p in probs])
7555
return shannonEnt
7656

7757

@@ -83,38 +63,9 @@ def splitDataSet(dataSet, index, value):
8363
index 表示每一行的index列 划分数据集的特征
8464
value 表示index列对应的value值 需要返回的特征的值。
8565
Returns:
86-
index列为value的数据集【该数据集需要排除index列】
66+
index列为value的数据集
8767
"""
88-
retDataSet = []
89-
for featVec in dataSet:
90-
# index列为value的数据集【该数据集需要排除index列】
91-
# 判断index列的值是否为value
92-
if featVec[index] == value:
93-
# chop out index used for splitting
94-
# [:index]表示前index行,即若 index 为2,就是取 featVec 的前 index 行
95-
reducedFeatVec = featVec[:index]
96-
'''
97-
请百度查询一下: extend和append的区别
98-
list.append(object) 向列表中添加一个对象object
99-
list.extend(sequence) 把一个序列seq的内容添加到列表中
100-
1、使用append的时候,是将new_media看作一个对象,整体打包添加到music_media对象中。
101-
2、使用extend的时候,是将new_media看作一个序列,将这个序列和music_media序列合并,并放在其后面。
102-
result = []
103-
result.extend([1,2,3])
104-
print result
105-
result.append([4,5,6])
106-
print result
107-
result.extend([7,8,9])
108-
print result
109-
结果:
110-
[1, 2, 3]
111-
[1, 2, 3, [4, 5, 6]]
112-
[1, 2, 3, [4, 5, 6], 7, 8, 9]
113-
'''
114-
reducedFeatVec.extend(featVec[index+1:])
115-
# [index+1:]表示从跳过 index 的 index+1行,取接下来的数据
116-
# 收集结果值 index列为value的行【该行需要排除index列】
117-
retDataSet.append(reducedFeatVec)
68+
retDataSet = [data for data in dataSet for i, v in enumerate(data) if i == axis and v == value]
11869
return retDataSet
11970

12071

@@ -126,36 +77,24 @@ def chooseBestFeatureToSplit(dataSet):
12677
Returns:
12778
bestFeature 最优的特征列
12879
"""
129-
# 求第一行有多少列的 Feature, 最后一列是label列嘛
130-
numFeatures = len(dataSet[0]) - 1
131-
# label的信息熵
132-
baseEntropy = calcShannonEnt(dataSet)
133-
# 最优的信息增益值, 和最优的Featurn编号
134-
bestInfoGain, bestFeature = 0.0, -1
135-
# iterate over all the features
136-
for i in range(numFeatures):
137-
# create a list of all the examples of this feature
138-
# 获取每一个实例的第i+1个feature,组成list集合
139-
featList = [example[i] for example in dataSet]
140-
# get a set of unique values
141-
# 获取剔重后的集合,使用set对list数据进行去重
142-
uniqueVals = set(featList)
143-
# 创建一个临时的信息熵
144-
newEntropy = 0.0
145-
# 遍历某一列的value集合,计算该列的信息熵
146-
# 遍历当前特征中的所有唯一属性值,对每个唯一属性值划分一次数据集,计算数据集的新熵值,并对所有唯一特征值得到的熵求和。
147-
for value in uniqueVals:
148-
subDataSet = splitDataSet(dataSet, i, value)
149-
prob = len(subDataSet)/float(len(dataSet))
150-
newEntropy += prob * calcShannonEnt(subDataSet)
151-
# gain[信息增益]: 划分数据集前后的信息变化, 获取信息熵最大的值
152-
# 信息增益是熵的减少或者是数据无序度的减少。最后,比较所有特征中的信息增益,返回最好特征划分的索引值。
153-
infoGain = baseEntropy - newEntropy
154-
print 'infoGain=', infoGain, 'bestFeature=', i, baseEntropy, newEntropy
155-
if (infoGain > bestInfoGain):
156-
bestInfoGain = infoGain
157-
bestFeature = i
158-
return bestFeature
80+
# 计算初始香农熵
81+
base_entropy = calcShannonEnt(dataSet)
82+
best_info_gain = 0
83+
best_feature = -1
84+
# 遍历每一个特征
85+
for i in range(len(dataSet[0]) - 1):
86+
# 对当前特征进行统计
87+
feature_count = Counter([data[i] for data in dataSet])
88+
# 计算分割后的香农熵
89+
new_entropy = sum(feature[1] / float(len(dataSet)) * calcShannonEnt(splitDataSet(dataSet, i, feature[0])) \
90+
for feature in feature_count.items())
91+
# 更新值
92+
info_gain = base_entropy - new_entropy
93+
print('No. {0} feature info gain is {1:.3f}'.format(i, info_gain))
94+
if info_gain > best_info_gain:
95+
best_info_gain = info_gain
96+
best_feature = i
97+
return best_feature
15998

16099

161100
def majorityCnt(classList):

0 commit comments

Comments
 (0)