[Python数据分析] 6-挖掘建模(无监督学习)

# III.无监督学习编码实现(聚类和关联)
# 1.数据集的设定
import numpy as np
import matplotlib.pyplot as plt
import scipy.stats as ss
# 引入sklearn包中的datasets接口模拟一些点
from sklearn.datasets import make_circles,make_moons,make_blobs
n_samples = 1000
circles = make_circles(n_samples=n_samples,factor=0.5,noise=0.05)
moons = make_moons(n_samples=n_samples,noise=0.05)
blobs = make_blobs(n_samples=n_samples,random_state=8,center_box=(-1,1),cluster_std=0.1)
random_data = np.random.rand(n_samples,2),None  # 二维是为了方便可视化
# random_data2 = np.random.randint(10,size=n_samples)
# print(type(random_data2))
# print(random_data2)
colors = "bgrcmyk"
data = [circles,moons,blobs,random_data]
f = plt.figure()
# 2.模型建立,引入一个列表,一会儿装模型用
models = [("None",None)]
# Clustering-i.基于切割的K-means
# 原则:所有的类都有一个中心,属于一个类的点到它的中心的距离比到其他类中心点的距离更近
# 算法:
    # A.从n个样本中随机选取K个作为初始化的质心,K的个数为分类的数
    # B.对每个样本测量其到各个质心的距离,并把它归到最近的质心的类中
    # C.重新计算已经得到的各类的质心
    # D.迭代B和C过程,直到新的质心不变或小于指定的阈值
# 注意点:
    # 1.初始质心的位置可能会影响最终聚类的结果(多试几次找出稳定点)
    # 2.离群点会影响整体的聚类效果(将质心换成取重点的K-Medoids算法)
    # 3.必须要指定K(借助其他衡量因子确定K的个数)
from sklearn.cluster import KMeans
models.append(("K-means",KMeans(n_clusters=3)))
# Clustering-ii.基于密度的DBSCAN(找到密度相连的最大集合)
# 原则:一定区域内,密度到达一定程度才叫一个类,否则叫离群点
# 概念:
    # 1.E邻域:给定对象半径为E内的区域为该对象的E邻域
    # 2.核心对象:如果给定对象E邻域内的样本点个数大于等于MinPts,则称该对象为核心对象
    # 3.直接密度可达:对于样本集合D,如果样本点q在p的E邻域内,且p为核心对象,那么对象q从对象p直接密度可达
    # 4.密度可达:对于样本集合D,给定一串样本点p1,p2…pn,p=p1,q=pn,假设对象pi从pi-1直接密度可达,则对象q从对象p密度可达
    # 5.密度相连:存在样本集合D中的一点o,如果对象o到对象p和对象q都是密度可达,那么p和q密度相连
# 注意点:
    # 优:对离群点不敏感
    # 劣:需要KD-Tree等数据结构的辅助,且参数问题较难解决
from sklearn.cluster import DBSCAN
# min_samples:最小分类数,eps:E邻域
models.append(("DBSCAN",DBSCAN(min_samples=3,eps=0.2)))
# Clustering-iii.基于层次的聚类算法
# 原则:依次聚类最近的集合
# 距离衡量的方法:最短距离,最长距离,平均距离,Ward
# 注意点:
    # 优:聚类灵活
    # 劣:计算复杂度比较高,离群点影响比较大
from sklearn.cluster import AgglomerativeClustering
# n_cluster:分类数,linkage:距离计算方式
models.append(("AgglomerativeClustering",AgglomerativeClustering(n_clusters=3,linkage="ward")))
# Clustering-iv.基于图的Split算法
# 原则:与基本层次聚类思路相反,为从顶至下
#  注意点:
    # 优:图建立方式及分裂方式灵活
# 3.聚类结果对比,画图
# enumerate()函数用于将一个可遍历的数据对象(如列表,元组或字符串)组合为一个索引序列,同时列出数据和数据下标,一般用在for循环当中
# 遍历下标inx,实体部分clt
# 以models中的第1项为例inx为0,clt为("None",None)
for inx,clt in enumerate(models):
    # clt分为2部分,可以用这个形式指定clt名字和clt实体
    # clt_name对应"None",clt_entity对应"None"的实体部分
    clt_name,clt_entity = clt
    # 同样的,遍历data的下标i和实体dataset
    for i,dataset in enumerate(data):
        # X对应数组,Y对应标注
        X,Y = dataset
        # 如果data实体是空的话,分类结果为0,分类的项目与数组长度一致
        if not clt_entity:
            clt_res = [0 for item in range(len(X))]
        # 如果data实体不为空的,分类结果为fit结果
        else:
            clt_entity.fit(X)
            clt_res = clt_entity.labels_.astype(np.int)
        f.add_subplot(len(models),len(data),inx*len(data)+i+1)
        plt.title(clt_name)
        for p in range(len(X)):
            plt.scatter(X[p,0],X[p,1],color=colors[clt_res[p]])
plt.show()

 [Python数据分析] 6-挖掘建模(无监督学习)_第1张图片

# Association-i.关联规则(反映一个事物与其他事物之间的相互依存性和关联性,目的:找到频繁项集)
#     1.概念:
#         1)项目:一个字段,对交易来说一般指一次交易中的一个物品,如尿布
#         2)事物:一个集合,对交易来说一般指发生的所有项目集合,如{啤酒,尿布}
#         3)项集:一个集合,包含若干项目的集合(一次事务中的)
#         4)频繁项集:某个项集的支持度大于设定阈值,则称这个项集为频繁项集
#         5)支持度:项集{X,Y}在总项集中出现的概率(Support)
#         6)置信度:在先决条件X发生的条件下,由关联规则{X->Y}推出Y的概率(Confidence),条件概率的概念
#         7)提升度:表示含有X的条件下同时含有Y的概率,与无论含不含X含有Y的概率之比,(Confidence({X->Y})/Support({Y}))
#         * 频繁项集的组合可能是频繁的也可能是非频繁的,非频繁项集的组合一定是非频繁的
#     2.算法:Apriori:用低阶频繁项集和设定的阈值找到高阶频繁项集
#         A.指定支持度的阈值
#         B.判断项集的支持度与阈值的大小关系
# 
# Association-i.序列规则(在关联规则的前提下将时间因素考虑进来,剔除关联规则中时间点靠后的项对时间点靠前的项的支持)
#     1.应用:预测用户在本次购物之后,下次购物会购买其他什么用作搭配
#     2.算法:Apriori-All
#         A.Forward:Apriori
#         B.Backward:去掉时间序列之后的项对之前的项的支持

from itertools import combinations
def comb(lst):
    ret=[]
    for i in range(1,len(lst)+1):
        ret+=list(combinations(lst,i))
    return ret
class AprLayer(object):
    d=dict()
    def __init__(self):
        self.d=dict()
class AprNode(object):
    def __init__(self,node):
        self.s=set(node)
        self.size=len(self.s)
        self.lnk_nodes=dict()
        self.num=0
    def __hash__(self):
        return hash("__".join(sorted([str(itm) for itm in list(self.s)])))
    def __eq__(self, other):
        if "__".join(sorted([str(itm) for itm in list(self.s)]))=="__".join(sorted([str(itm) for itm in list(other.s)])):
            return True
        return False
    def isSubnode(self,node):
        return self.s.issubset(node.s)
    def incNum(self,num=1):
        self.num+=num
    def addLnk(self,node):
        self.lnk_nodes[node]=node.s

class AprBlk():
    def __init__(self,data):
        cnt=0
        self.apr_layers = dict()
        self.data_num=len(data)
        for datum in data:
            cnt+=1
            datum=comb(datum)
            nodes=[AprNode(da) for da in datum]
            for node in nodes:
                if not node.size in self.apr_layers:
                    self.apr_layers[node.size]=AprLayer()
                if not node in self.apr_layers[node.size].d:
                    self.apr_layers[node.size].d[node]=node
                self.apr_layers[node.size].d[node].incNum()
            for node in nodes:
                if node.size==1:
                    continue
                for sn in node.s:
                    sub_n=AprNode(node.s-set([sn]))
                    self.apr_layers[node.size-1].d[sub_n].addLnk(node)

    def getFreqItems(self,thd=1,hd=1):
        freq_items=[]
        for layer in self.apr_layers:
            for node in self.apr_layers[layer].d:
                if self.apr_layers[layer].d[node].num

 

你可能感兴趣的:(数据挖掘,数据分析)