mirror of
https://github.com/apachecn/ailearning.git
synced 2026-05-09 07:31:53 +08:00
BIN
src/python/10.kmeans/kMeans.pyc
Normal file
BIN
src/python/10.kmeans/kMeans.pyc
Normal file
Binary file not shown.
@@ -11,45 +11,48 @@ Ch 11 code
|
||||
print(__doc__)
|
||||
from numpy import *
|
||||
|
||||
|
||||
# 加载数据集
|
||||
def loadDataSet():
|
||||
return [[1, 3, 4], [2, 3, 5], [1, 2, 3, 5], [2, 5]]
|
||||
|
||||
|
||||
# 创建集合 C1。即对 dataSet 进行去重,排序,放入 list 中,然后转换所有的元素为 frozenset
|
||||
def createC1(dataSet):
|
||||
"""createC1(创建一个数据集)
|
||||
"""createC1(创建集合 C1)
|
||||
|
||||
Args:
|
||||
dataSet 加载的原始数据集
|
||||
dataSet 原始数据集
|
||||
Returns:
|
||||
frozenset 返回一个元素为frozenset格式的list
|
||||
frozenset 返回一个 frozenset 格式的 list
|
||||
"""
|
||||
|
||||
C1 = []
|
||||
for transaction in dataSet:
|
||||
for item in transaction:
|
||||
if not [item] in C1:
|
||||
# 遍历所有的元素,然后append到C1中
|
||||
# 遍历所有的元素,如果不在 C1 出现过,那么就 append
|
||||
C1.append([item])
|
||||
# 对数组进行 从小到大 的排序
|
||||
print 'sort前=', C1
|
||||
# 对数组进行 `从小到大` 的排序
|
||||
# print 'sort 前=', C1
|
||||
C1.sort()
|
||||
# frozenset表示冻结的set集合,元素无改变;可以把它当字典的key来使用
|
||||
print 'sort后=', C1
|
||||
print 'frozenset=', map(frozenset, C1)
|
||||
# frozenset 表示冻结的 set 集合,元素无改变;可以把它当字典的 key 来使用
|
||||
# print 'sort 后=', C1
|
||||
# print 'frozenset=', map(frozenset, C1)
|
||||
return map(frozenset, C1)
|
||||
|
||||
|
||||
# 计算候选数据集 CK 在数据集 D 中的支持度,并返回支持度大于最小支持度(minSupport)的数据
|
||||
def scanD(D, Ck, minSupport):
|
||||
"""scanD(计算支持support, retList表示满足support的key, supportData表示全集的集合)
|
||||
"""scanD(计算候选数据集 CK 在数据集 D 中的支持度,并返回支持度大于最小支持度 minSupport 的数据)
|
||||
|
||||
Args:
|
||||
D 原始数据集, D用来判断,CK中的元素,是否存在于原数据D中
|
||||
Ck 所有key的元素集合
|
||||
D 数据集
|
||||
Ck 候选项集列表
|
||||
minSupport 最小支持度
|
||||
Returns:
|
||||
retList 支持度大于阈值的集合
|
||||
supportData 全量key的字典集合
|
||||
retList 支持度大于 minSupport 的集合
|
||||
supportData 候选项集支持度数据
|
||||
"""
|
||||
# ssCnt 临时存放Ck的元素集合,查看Ck每个元素 并 计算元素出现的次数 生成相应的字典
|
||||
|
||||
# ssCnt 临时存放选数据集 Ck 的频率. 例如: a->10, b->5, c->8
|
||||
ssCnt = {}
|
||||
for tid in D:
|
||||
for can in Ck:
|
||||
@@ -59,34 +62,35 @@ def scanD(D, Ck, minSupport):
|
||||
ssCnt[can] = 1
|
||||
else:
|
||||
ssCnt[can] += 1
|
||||
# 元素有多少行
|
||||
numItems = float(len(D))
|
||||
numItems = float(len(D)) # 数据集 D 的数量
|
||||
retList = []
|
||||
supportData = {}
|
||||
for key in ssCnt:
|
||||
# 计算支持度
|
||||
# 支持度 = 候选项(key)出现的次数 / 所有数据集的数量
|
||||
support = ssCnt[key]/numItems
|
||||
if support >= minSupport:
|
||||
# 在retList的首位插入元素,只存储支持度满足频繁项集的值
|
||||
# 在 retList 的首位插入元素,只存储支持度满足频繁项集的值
|
||||
retList.insert(0, key)
|
||||
# 存储所有的key和对应的support值
|
||||
# 存储所有的候选项(key)和对应的支持度(support)
|
||||
supportData[key] = support
|
||||
return retList, supportData
|
||||
|
||||
|
||||
# creates Ck
|
||||
# 输入频繁项集列表 Lk 与返回的元素个数 k,然后输出所有可能的候选项集 Ck
|
||||
def aprioriGen(Lk, k):
|
||||
"""aprioriGen(循环数据集,然后进行两两合并)
|
||||
"""aprioriGen(输入频繁项集列表 Lk 与返回的元素个数 k,然后输出候选项集 Ck。
|
||||
例如: 以 {0},{1},{2} 为输入且 k = 2 则输出 {0,1}, {0,2}, {1,2}. 以 {0,1},{0,2},{1,2} 为输入且 k = 3 则输出 {0,1,2}
|
||||
仅需要计算一次,不需要将所有的结果计算出来,然后进行去重操作
|
||||
这是一个更高效的算法)
|
||||
|
||||
Args:
|
||||
Lk 频繁项集的list
|
||||
k 元素的前k-2相同,就进行合并
|
||||
Lk 频繁项集列表
|
||||
k 返回的项集元素个数(若元素的前 k-2 相同,就进行合并)
|
||||
Returns:
|
||||
retList 元素两两合并的数据集
|
||||
"""
|
||||
|
||||
retList = []
|
||||
lenLk = len(Lk)
|
||||
# 循环Lk这个数组
|
||||
for i in range(lenLk):
|
||||
for j in range(i+1, lenLk):
|
||||
L1 = list(Lk[i])[: k-2]
|
||||
@@ -95,7 +99,7 @@ def aprioriGen(Lk, k):
|
||||
# print '-----j=', j, k-2, Lk, Lk[j], list(Lk[j])[: k-2]
|
||||
L1.sort()
|
||||
L2.sort()
|
||||
# 第一次L1,L2为空,元素直接进行合并,返回元素两两合并的数据集
|
||||
# 第一次 L1,L2 为空,元素直接进行合并,返回元素两两合并的数据集
|
||||
# if first k-2 elements are equal
|
||||
if L1 == L2:
|
||||
# set union
|
||||
@@ -103,9 +107,9 @@ def aprioriGen(Lk, k):
|
||||
retList.append(Lk[i] | Lk[j])
|
||||
return retList
|
||||
|
||||
|
||||
# 找出数据集 dataSet 中支持度 >= 最小支持度的候选项集以及它们的支持度。即我们的频繁项集。
|
||||
def apriori(dataSet, minSupport=0.5):
|
||||
"""apriori
|
||||
"""apriori(首先构建集合 C1,然后扫描数据集来判断这些只有一个元素的项集是否满足最小支持度的要求。那么满足最小支持度要求的项集构成集合 L1。然后 L1 中的元素相互组合成 C2,C2 再进一步过滤变成 L2,然后以此类推,知道 CN 的长度为 0 时结束,即可找出所有频繁项集的支持度。)
|
||||
|
||||
Args:
|
||||
dataSet 原始数据集
|
||||
@@ -114,118 +118,117 @@ def apriori(dataSet, minSupport=0.5):
|
||||
L 频繁项集的全集
|
||||
supportData 所有元素和支持度的全集
|
||||
"""
|
||||
# C1表示让元素转化为frozenset,并按照顺序存放到list中
|
||||
# C1 即对 dataSet 进行去重,排序,放入 list 中,然后转换所有的元素为 frozenset
|
||||
C1 = createC1(dataSet)
|
||||
# 对每一行进行set转换,然后存放到集合中
|
||||
# print 'C1: ', C1
|
||||
# 对每一行进行 set 转换,然后存放到集合中
|
||||
D = map(set, dataSet)
|
||||
print 'D=', D
|
||||
# 计算支持support, 计算在数据集D中,C1集合中元素是否满足minSupport
|
||||
# L1表示满足support的key, supportData表示全集的集合
|
||||
# print 'D=', D
|
||||
# 计算候选数据集 C1 在数据集 D 中的支持度,并返回支持度大于 minSupport 的数据
|
||||
L1, supportData = scanD(D, C1, minSupport)
|
||||
# print "L1=", L1, "\n", "outcome: ", supportData
|
||||
|
||||
# L加了一层list, L一共2曾list
|
||||
# L 加了一层 list, L 一共 2 层 list
|
||||
L = [L1]
|
||||
k = 2
|
||||
# 判断L的第一层list是否有元素,就说说:L1是否有元素
|
||||
# 判断 L 的第 k-2 项的数据长度是否 > 0。第一次执行时 L 为 [[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])]]。L[k-2]=L[0]=[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])],最后面 k += 1
|
||||
while (len(L[k-2]) > 0):
|
||||
# 如果L的每个元素子项和后面任意一个元素项,进行对比, 就对前后2个频繁项集的合并,得到CK
|
||||
print 'k=', k, L, L[k-2]
|
||||
Ck = aprioriGen(L[k-2], k)
|
||||
print 'Ck', Ck
|
||||
# print 'k=', k, L, L[k-2]
|
||||
Ck = aprioriGen(L[k-2], k) # 例如: 以 {0},{1},{2} 为输入且 k = 2 则输出 {0,1}, {0,2}, {1,2}. 以 {0,1},{0,2},{1,2} 为输入且 k = 3 则输出 {0,1,2}
|
||||
# print 'Ck', Ck
|
||||
|
||||
# 计算合并后的数据集的支持度
|
||||
# Lk满足支持度的key的list, supK表示key全集
|
||||
Lk, supK = scanD(D, Ck, minSupport)
|
||||
# 如果字典没有,就追加元素,如果有,就更新元素
|
||||
Lk, supK = scanD(D, Ck, minSupport) # 计算候选数据集 CK 在数据集 D 中的支持度,并返回支持度大于 minSupport 的数据
|
||||
# 保存所有候选项集的支持度,如果字典没有,就追加元素,如果有,就更新元素
|
||||
supportData.update(supK)
|
||||
if len(Lk) == 0:
|
||||
break
|
||||
# Lk表示满足频繁子项的集合,L元素在增加
|
||||
# Lk 表示满足频繁子项的集合,L 元素在增加,例如:
|
||||
# l=[[set(1), set(2), set(3)]]
|
||||
# l=[[set(1), set(2), set(3)] [set(1, 2), set(2, 3)]]
|
||||
# l=[[set(1), set(2), set(3)], [set(1, 2), set(2, 3)]]
|
||||
L.append(Lk)
|
||||
k += 1
|
||||
# print 'k=', k, len(L[k-2])
|
||||
return L, supportData
|
||||
|
||||
|
||||
# 计算可信度(confidence)
|
||||
def calcConf(freqSet, H, supportData, brl, minConf=0.7):
|
||||
"""calcConf(对2元素的频繁项,计算置信度,例如: {1,2}/{1} 或者{1,2}/{2} 看是否满足条件)
|
||||
"""calcConf(对两个元素的频繁项,计算可信度,例如: {1,2}/{1} 或者 {1,2}/{2} 看是否满足条件)
|
||||
|
||||
Args:
|
||||
freqSet 每一组的各个元素
|
||||
H 将元素变成set集合
|
||||
supportData 所有元素的支持度全集
|
||||
brl bigRuleList的空数组
|
||||
minConf 置信度的阈值
|
||||
freqSet 频繁项集中的元素,例如: frozenset([1, 3])
|
||||
H 频繁项集中的元素的集合,例如: [frozenset([1]), frozenset([3])]
|
||||
supportData 所有元素的支持度的字典
|
||||
brl 关联规则列表的空数组
|
||||
minConf 最小可信度
|
||||
Returns:
|
||||
prunedH 记录 置信度大于阈值的集合
|
||||
prunedH 记录 可信度大于阈值的集合
|
||||
"""
|
||||
# 记录 可信度大于阈值的集合
|
||||
# 记录可信度大于最小可信度(minConf)的集合
|
||||
prunedH = []
|
||||
for conseq in H:
|
||||
# 计算自信度的值,例如元素 H=set(1, 2), 分别求:supportData[1] 和 supportData[2]
|
||||
# 例如: confidence= frozenset([2, 3, 5]) frozenset([2, 3]) frozenset([5])
|
||||
# print 'confidence=', freqSet, conseq, freqSet-conseq
|
||||
conf = supportData[freqSet]/supportData[freqSet-conseq]
|
||||
for conseq in H: # 假设 freqSet = frozenset([1, 3]), H = [frozenset([1]), frozenset([3])],那么现在需要求出 frozenset([1]) -> frozenset([3]) 的可信度和 frozenset([3]) -> frozenset([1]) 的可信度
|
||||
|
||||
# print 'confData=', freqSet, H, conseq, freqSet-conseq
|
||||
conf = supportData[freqSet]/supportData[freqSet-conseq] # 支持度定义: a -> b = support(a | b) / support(a). 假设 freqSet = frozenset([1, 3]), conseq = [frozenset([1])],那么 frozenset([1]) 至 frozenset([3]) 的可信度为 = support(a | b) / support(a) = supportData[freqSet]/supportData[freqSet-conseq] = supportData[frozenset([1, 3])] / supportData[frozenset([1])]
|
||||
if conf >= minConf:
|
||||
# 意思是说: 只要买了freqSet-conseq集合,一定会买 conseq集合【freqSet-conseq集合 和 conseq集合 是全集】
|
||||
# 只要买了 freqSet-conseq 集合,一定会买 conseq 集合(freqSet-conseq 集合和 conseq集合 是全集)
|
||||
print freqSet-conseq, '-->', conseq, 'conf:', conf
|
||||
brl.append((freqSet-conseq, conseq, conf))
|
||||
prunedH.append(conseq)
|
||||
return prunedH
|
||||
|
||||
|
||||
# 递归计算频繁项集的规则
|
||||
def rulesFromConseq(freqSet, H, supportData, brl, minConf=0.7):
|
||||
"""rulesFromConseq
|
||||
|
||||
Args:
|
||||
freqSet 每一组的各个元素
|
||||
H 将元素变成set集合
|
||||
supportData 所有元素的支持度全集
|
||||
brl bigRuleList的空数组
|
||||
minConf 置信度的阈值
|
||||
Returns:
|
||||
prunedH 记录 可信度大于阈值的集合
|
||||
freqSet 频繁项集中的元素,例如: frozenset([2, 3, 5])
|
||||
H 频繁项集中的元素的集合,例如: [frozenset([2]), frozenset([3]), frozenset([5])]
|
||||
supportData 所有元素的支持度的字典
|
||||
brl 关联规则列表的数组
|
||||
minConf 最小可信度
|
||||
"""
|
||||
# H[0]是freqSet的元素组合的第一个元素
|
||||
# H[0] 是 freqSet 的元素组合的第一个元素,并且 H 中所有元素的长度都一样,长度由 aprioriGen(H, m+1) 这里的 m + 1 来控制
|
||||
# 该函数递归时,H[0] 的长度从 1 开始增长 1 2 3 ...
|
||||
# 假设 freqSet = frozenset([2, 3, 5]), H = [frozenset([2]), frozenset([3]), frozenset([5])]
|
||||
# 那么 m = len(H[0]) 的递归的值依次为 1 2
|
||||
# 在 m = 2 时, 跳出该递归。假设再递归一次,那么 H[0] = frozenset([2, 3, 5]),freqSet = frozenset([2, 3, 5]) ,没必要再计算 freqSet 与 H[0] 的关联规则了。
|
||||
m = len(H[0])
|
||||
# 判断,freqSet的长度是否>组合的长度+1, 避免过度匹配 例如:计算过一边{1,2,3} 和 {1, 2} {1, 3},就没必要再计算了进一步合并来计算 {1,2,3}和{1,2,3}的组合关系
|
||||
if (len(freqSet) > (m + 1)):
|
||||
print 'freqSet******************', len(freqSet), m + 1, freqSet, H, H[0]
|
||||
# 合并数据集集合,组合为2/3/..n的集合
|
||||
# print 'freqSet******************', len(freqSet), m + 1, freqSet, H, H[0]
|
||||
# 生成 m+1 个长度的所有可能的 H 中的组合,假设 H = [frozenset([2]), frozenset([3]), frozenset([5])]
|
||||
# 第一次递归调用时生成 [frozenset([2, 3]), frozenset([2, 5]), frozenset([3, 5])]
|
||||
# 第二次 。。。没有第二次,递归条件判断时已经退出了
|
||||
Hmp1 = aprioriGen(H, m+1)
|
||||
# 返回记录 可信度大于阈值的集合
|
||||
# 返回可信度大于最小可信度的集合
|
||||
Hmp1 = calcConf(freqSet, Hmp1, supportData, brl, minConf)
|
||||
# 如果有2个结果都可以,直接返回结果就行,下面这个判断是多余,我个人觉得
|
||||
print 'Hmp1=', Hmp1
|
||||
print 'len(Hmp1)=', len(Hmp1), 'len(freqSet)=', len(freqSet)
|
||||
# 计算可信度后,还有数据大于最小可信度的话,那么继续递归调用,否则跳出递归
|
||||
if (len(Hmp1) > 1):
|
||||
print '----------------------', Hmp1
|
||||
# print '----------------------', Hmp1
|
||||
# print len(freqSet), len(Hmp1[0]) + 1
|
||||
rulesFromConseq(freqSet, Hmp1, supportData, brl, minConf)
|
||||
|
||||
|
||||
# 生成关联规则
|
||||
def generateRules(L, supportData, minConf=0.7):
|
||||
"""generateRules
|
||||
|
||||
Args:
|
||||
L 频繁项集的全集
|
||||
supportData 所有元素和支持度的全集
|
||||
minConf 置信度的阈值
|
||||
L 频繁项集列表
|
||||
supportData 频繁项集支持度的字典
|
||||
minConf 最小置信度
|
||||
Returns:
|
||||
bigRuleList 关于 (A->B+置信度) 3个字段的组合
|
||||
bigRuleList 可信度规则列表(关于 (A->B+置信度) 3个字段的组合)
|
||||
"""
|
||||
bigRuleList = []
|
||||
# 循环L频繁项集,所有的统一大小组合(2/../n个的组合,从第2组开始)
|
||||
# 假设 L = [[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])], [frozenset([1, 3]), frozenset([2, 5]), frozenset([2, 3]), frozenset([3, 5])], [frozenset([2, 3, 5])]]
|
||||
for i in range(1, len(L)):
|
||||
# 获取频繁项集中每个组合的所有元素
|
||||
# [[frozenset([1]), frozenset([3]), frozenset([2]), frozenset([5])], [frozenset([1, 3]), frozenset([2, 5]), frozenset([2, 3]), frozenset([3, 5])], [frozenset([2, 3, 5])]]
|
||||
for freqSet in L[i]:
|
||||
# 假设:freqSet=frozenset([1, 3]) H1=[1, 3]
|
||||
# 组合总的元素并遍历子元素,并转化为冻结的set集合,再存放到list列表中
|
||||
# 假设:freqSet= frozenset([1, 3]), H1=[frozenset([1]), frozenset([3])]
|
||||
# 组合总的元素并遍历子元素,并转化为 frozenset 集合,再存放到 list 列表中
|
||||
H1 = [frozenset([item]) for item in freqSet]
|
||||
# 2个的组合,走else, 2个以上的组合,走if
|
||||
# 2 个的组合,走 else, 2 个以上的组合,走 if
|
||||
if (i > 1):
|
||||
rulesFromConseq(freqSet, H1, supportData, bigRuleList, minConf)
|
||||
else:
|
||||
@@ -297,26 +300,43 @@ def getTransList(actionIdList, billTitleList): #this will return a list of lists
|
||||
# print "confidence: %f" % ruleTup[2]
|
||||
# print #print a blank line
|
||||
|
||||
def testApriori():
|
||||
# 加载测试数据集
|
||||
dataSet = loadDataSet()
|
||||
print 'dataSet: ', dataSet
|
||||
|
||||
# Apriori 算法生成频繁项集以及它们的支持度
|
||||
L1, supportData1 = apriori(dataSet, minSupport=0.7)
|
||||
print 'L(0.7): ', L1
|
||||
print 'supportData(0.7): ', supportData1
|
||||
|
||||
# Apriori 算法生成频繁项集以及它们的支持度
|
||||
L2, supportData2 = apriori(dataSet, minSupport=0.5)
|
||||
print 'L(0.5): ', L2
|
||||
print 'supportData(0.5): ', supportData2
|
||||
|
||||
def testGenerateRules():
|
||||
# 加载测试数据集
|
||||
dataSet = loadDataSet()
|
||||
print 'dataSet: ', dataSet
|
||||
|
||||
# Apriori 算法生成频繁项集以及它们的支持度
|
||||
L1, supportData1 = apriori(dataSet, minSupport=0.5)
|
||||
print 'L(0.7): ', L1
|
||||
print 'supportData(0.7): ', supportData1
|
||||
|
||||
# 生成关联规则
|
||||
rules = generateRules(L1, supportData1, minConf=0.5)
|
||||
print 'rules: ', rules
|
||||
|
||||
def main():
|
||||
# # 以前的测试
|
||||
# project_dir = os.path.dirname(os.path.dirname(os.getcwd()))
|
||||
# # 收集并准备数据
|
||||
# dataMat, labelMat = loadDataSet("%s/resources/Apriori_testdata.txt" % project_dir)
|
||||
# 测试 Apriori 算法
|
||||
# testApriori()
|
||||
|
||||
# 现在的的测试
|
||||
# 1. 加载数据
|
||||
dataSet = loadDataSet()
|
||||
print dataSet
|
||||
# 调用 apriori 做购物篮分析
|
||||
# 支持度满足阈值的key集合L,和所有元素和支持度的全集suppoerData
|
||||
L, supportData = apriori(dataSet, minSupport=0.5)
|
||||
print L, '\n', supportData
|
||||
print '\ngenerateRules\n'
|
||||
rules = generateRules(L, supportData, minConf=0.25)
|
||||
print rules
|
||||
# 生成关联规则
|
||||
testGenerateRules()
|
||||
|
||||
# # 项目实战
|
||||
# # 项目案例
|
||||
# # 构建美国国会投票记录的事务数据集
|
||||
# actionIdList, billTitleList = getActionIds()
|
||||
# # 测试前2个
|
||||
@@ -329,7 +349,7 @@ def main():
|
||||
# rules = generateRules(L, supportData, minConf=0.95)
|
||||
# print rules
|
||||
|
||||
# # 项目实战
|
||||
# # 项目案例
|
||||
# # 发现毒蘑菇的相似特性
|
||||
# # 得到全集的数据
|
||||
# dataSet = [line.split() for line in open("input/11.Apriori/mushroom.dat").readlines()]
|
||||
@@ -344,6 +364,5 @@ def main():
|
||||
# if item.intersection('2'):
|
||||
# print item
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
BIN
src/python/11.Apriori/apriori.pyc
Normal file
BIN
src/python/11.Apriori/apriori.pyc
Normal file
Binary file not shown.
Reference in New Issue
Block a user