机器学习(一)--分类,K-Means算法(NBA球星实例、超市用户实例)

离散与连续

数据–数据对象、样本、实例

离散属性–类别属性

  1. 用名称标注
  2. 用类别/类别号来标注

连续属性–连续的小数

  • 在一个区间内连续,用浮点型数值表示

数据集

多个数据组合在一起–数据集合–数据集

  1. 行:代表样本
  2. 列:代表属性

一、机器学习

(一)概念

在历史数据中发现规律,然后利用规律,对新的数据进行预测与指导。
在这里插入图片描述

(二)数据分析与数据挖掘

人工智能的基础

想要一个好的机器学习结果,就必须有一个好的数据处理。

数据分析与数据挖掘的区别

数据分析主要偏向于业务。

数据挖掘主要偏向于对数据价值的挖掘。

在这里插入图片描述

(三)按照学习方式分类

1.监督学习

数据:既有特征值,又有目标值

研究:研究的是特征与目标之间的关系

数据集

训练集与测试集的划分
在这里插入图片描述

算法代表

1.分类算法:目标值是离散的

(1)KNN算法

特点

  1. k值不同,分类的结果不同
  2. 需要将所有的数据,加载到内存,不断计算每一个测试样本与训练样本的距离。时间、空间消耗比较大。
  3. 惰性学习算法

优化
在这里插入图片描述

(2)贝叶斯算法

2.回归算法:目标值是连续的

2.无监督学习

数据:只有特征值,无目标值数据

研究:研究的是样本和样本之间的关系

数据集

不需要划分
在这里插入图片描述

算法代表

1.聚类算法–K-Means算法

利用样本的特征,使最终的结果,同一类别内的样本具有较高的相似性,不同类别的样本具有较高的相异性。
在这里插入图片描述

3.半监督学习

隐马尔可夫模型

二、K-Means

应用场景

用于用户群体的划分。

(一)k-means原理自实现

# 科学计算库
import numpy as np
# 数据可视化库
import matplotlib.pyplot as plt
# 数据处理库
import pandas as pd

def bulid_data():
    '''
    构建数据
    :return:数据
    '''
    # 加载数据
    # 1.open
    # 2.np.loadtxt/np.genfromtxt -- 文本类型的数组
    # 3.pd.read_table
    # sep和delimiter都可以指定分隔符
    # header=None -- 不让它将第一行设为行标
    data = pd.read_table('test.txt',sep='\t',header=None)
    # 转化为矩阵(矩阵--特殊的数组)
    # mat = asmatrix
    # matrix -- 比mat多了一个拷贝内存的过程
    # bmat -- 组合矩阵
    data = np.mat(data.values)
    return data

def center_init(data,k):
    '''
    聚类中心初始化
    :param data: 数据
    :param k: 聚类的类别数目
    :return: center
    '''
    # 确定数据的行下标范围
    index_num = data.shape[0]
    # 确定数据的列数
    column_num = data.shape[1]
    # 使用全零数组为聚类中心占位
    center = np.zeros((k,column_num))

    # 随机选择所有样本中的k个样本作为最开始的聚类中心
    # 计数器
    i = 0
    # 避免重复
    r_list = []
    while True:
        r = np.random.randint(0,index_num-1)
        if r in r_list:
            continue
        else:
            r_list.append(r)
            center[i,:] = data[r,:]
            i+=1
        if len(r_list) == k:
            break
    return center

def distance(v1,v2):
    '''
    距离计算
    :param v1: 点1
    :param v2: 点2
    :return: 距离
    '''
    # # 方法1
    # sum_ = 0
    # # v1.shape -- 二维
    # # v2.shape -- 一维
    # # 将v1由2维降为1维
    # # 将矩阵转换为数组:使用矩阵视图
    # # 矩阵.A --> 数组
    # v1 = v1.A[0]
    # if v1.shape == v2.shape:
    #     for i in range(len(v1)):
    #         sum_ += (v1[i] - v2[i])**2
    # return np.sqrt(sum_)

    # 方法2
    diff = v1 - v2
    d = np.sqrt(np.sum(np.power(diff,2)))
    return d

def k_means_owns(data,k):
    '''
    自实现k-means原理
    :param data: 数据
    :param k: 聚类的类别数目
    :return: 各个样本最终的类别,最终的聚类中心
    '''
    # 初始化聚类中心--随机初始化
    # 随机在所有样本中选取k个聚类中心
    center = center_init(data,k)

    # 数据行数
    index_num = data.shape[0]
    # 定义数组,保存距离样本最近的聚类中心及距离
    new_data = np.zeros((index_num,2))
    flag = True
    while flag:
        flag = False
        # 计算每一个训练样本与聚类中心的距离
        # 双层循环----外层 -- 训练样本
        #             内层 -- 聚类中心
        for i in range(index_num):
            min_dist = 10000000000000000000
            min_index = -1
            for j in range(k):
                # 计算距离
                # 高纬度的数组使用下标,会进行降维度
                # 矩阵是二维的特殊数组,使用索引不会降维度
                d = distance(data[i, :], center[j, :])
                # print(d)
                if d < min_dist:
                    min_dist = d
                    min_index = j
            # 如果当前的样本属于的簇与上一次的不一致
            if new_data[i,0] != min_index:
                new_data[i:] = min_index, min_dist
                flag = True

        if flag:
            # 计算新的聚类中心
            # 计算每一簇的均值 -- 每一簇的中心
            # 使用bool数组索引
            for p in range(k):
                bool_index = new_data[:, 0] == p
                # 选定簇
                p_cluster = data[bool_index, :]
                # 新的聚类中心
                center[p, :] = p_cluster[:, 0].mean(), p_cluster[:, 1].mean()
        # 如果新的聚类中心,与上一次的聚类中心重合--结束
        # 改变思路:如果所有样本所属的聚类中心,与上一次所属的聚类中心相同--结束
    return new_data,center

def show_res_owns(data,new_data,center):
    '''
    结果展示
    :param data: 原始数据
    :param new_data: 保存着各个样本最终的类别
    :param center: 最终的聚类中心
    :return: None
    '''
    # 1.创建画布
    plt.figure()
    # 显示中文,支持负号
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    # 2.绘图
    # 设置颜色列表
    c_list = ['b','g','y','pink']
    # 设置点形状列表
    marker_list = ['*','o','^','D']
    # 绘制散点图
    for i in range(data.shape[0]):
        plt.scatter(data[i,0],data[i,1],c=c_list[int(new_data[i,0])],marker=marker_list[int(new_data[i,0])])
    # 绘制聚类中心
    plt.plot(center[:,0],center[:,1],'bx',markersize=12)
    # 增加名称
    plt.title('聚类结果展示')
    # 保存图片
    plt.savefig('聚类结果展示')
    # 3.绘图展示
    plt.show()

def main():
    # 1.构建数据
    data = bulid_data()
    # print(data)
    # print(type(data))
    # print(data.dtype)
    # 2.自实现k-means算法原理
    # 确定聚类的类别数目
    k = 4
    new_data,center = k_means_owns(data,k)

    # 3.结果展示
    show_res_owns(data,new_data,center)

if __name__ == '__main__':
    main()

(二)使用sklearn

# 科学计算库
import numpy as np
# 数据可视化库
import matplotlib.pyplot as plt
# 数据处理库
import pandas as pd
from sklearn.cluster import KMeans

def bulid_data():
    '''
    构建数据
    :return:数据
    '''
    # 加载数据
    # 1.open
    # 2.np.loadtxt/np.genfromtxt -- 文本类型的数组
    # 3.pd.read_table
    # sep和delimiter都可以指定分隔符
    # header=None -- 不让它将第一行设为行标
    data = pd.read_table('test.txt',sep='\t',header=None)
    # 转化为矩阵(矩阵--特殊的数组)
    # mat = asmatrix
    # matrix -- 比mat多了一个拷贝内存的过程
    # bmat -- 组合矩阵
    data = np.mat(data.values)
    return data

def show_res(data,y_predict,center):
    '''
    结果展示
    :param data: 原始数据
    :param y_predict:预测类别
    :param center: 聚类中心
    :return: None
    '''
    # 1.创建画布
    plt.figure()
    # 显示中文,支持负号
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    # 2.绘图
    # 设置颜色列表
    c_list = ['b','g','y','pink']
    # 设置点形状列表
    marker_list = ['*','o','^','D']
    # 绘制散点图
    for i in range(data.shape[0]):
        plt.scatter(data[i,0],data[i,1],c=c_list[y_predict[i]],marker=marker_list[y_predict[i]])
    # 绘制聚类中心
    plt.plot(center[:,0],center[:,1],'bx',markersize=12)
    # 增加名称
    plt.title('聚类结果展示')
    # 保存图片
    plt.savefig('聚类结果展示')
    # 3.绘图展示
    plt.show()

def main():
    # 1.构建数据
    data = bulid_data()
    # 2.使用sklearn中的KMeans进行聚类分析
    # 确定聚类的类别数目
    k = 4
    # (1)构建算法实力
    # n_clusters--指定聚类的类别
    km = KMeans(n_clusters=k)
    # init='k-means++'--以一种更优的方式选取初始聚类中心
    # (2)进行训练数据
    km.fit(data)
    # (3)验证模型的好坏,即得到预测值
    y_predict = km.predict(data)
    # k-means算法--得到聚类中心
    center = km.cluster_centers_
    print('预测类别:\n',y_predict)
    print('聚类中心:\n',center)
    # 3.结果可视化
    show_res(data,y_predict,center)

if __name__ == '__main__':
    main()

(三)实例–NBA球星(sklearn)

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from sklearn.cluster import KMeans

def show_res(data,y_predict,center):
    '''
    结果展示
    :param data: 原始数据
    :param y_predict:预测类别
    :param center: 聚类中心
    :return: None
    '''
    # 1.创建画布
    plt.figure()
    # 显示中文,支持负号
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    # 2.绘图
    # 设置颜色列表
    c_list = ['b','g','y','pink','red']
    # 设置点形状列表
    marker_list = ['*','o','^','D','8']
    # 绘制散点图
    for i in range(data.shape[0]):
        plt.scatter(data[i,0],data[i,1],c=c_list[y_predict[i]],marker=marker_list[y_predict[i]])
    # 绘制聚类中心
    plt.plot(center[:,0],center[:,1],'bx',markersize=12)
    # 增加名称
    plt.title('NBA球星聚类结果展示')
    # 保存图片
    plt.savefig('NBA球星聚类结果展示')
    # 3.绘图展示
    plt.show()

def build_data(data):
    '''
    数据预处理
    :return:预处理后的数据
    '''
    # 2.数据合并
    # 只有一个表

    # 3.数据清洗
    #   (1)检测与处理缺失值
    #       检测:pd.inull().sum()
    #       处理:删除值、填充法、插值法
    #           处理非NaN类型缺失值,先将这种数据转化为np.NaN类型,再进行处理
    # res_null = pd.isnull(data).sum()
    # print(res_null)    # 无缺失值

    #   (2)处理异常值
    #       3sigma原理、箱线图分析法
    # 无异常值

    # 4.筛选有用的特征
    data = data.loc[:, ['时间', '助攻', '得分']]
    # print(data.dtypes)
    # 时间     object
    # 助攻    float64
    # 得分    float64
    # 将时间这一列的空格缺失值,转换成np.NaN类型
    data.loc[:, '时间'].replace(' ', np.NaN, inplace=True)
    # res_null = pd.isnull(data).sum()
    # print(res_null)    # 时间列有393个空值

    # 处理缺失值
    # 使用上一个邻居来填充缺失值
    data.loc[:'时间'].fillna(method='pad', inplace=True)
    # res_null = pd.isnull(data).sum()
    # print(res_null)    # 无空值

    # 将时间的数据类型转化为float类型
    data.loc[:, '时间'] = data.loc[:, '时间'].astype(np.float64)
    # print(data.dtypes)

    # 构建最终的得分/分钟  助攻/分钟
    data.loc[:, '得分/分钟'] = data.loc[:, '得分'] / data.loc[:, '时间']
    data.loc[:, '助攻/分钟'] = data.loc[:, '助攻'] / data.loc[:, '时间']
    data = data.loc[:, ['得分/分钟', '助攻/分钟']]
    return data

def main():
    # 1.加载、构建数据
    data = pd.read_excel('nba_data.xlsx')
    # print(data)
    # print(data.columns)

    data = build_data(data)
    # [5].标准化?
    #   做数据分析时,暂时不要做;要进行机器学习算法构建模型的时候,必须要做
    # 无需消除量纲

    # [6].构建模型--算法模型--进行训练数据--进行预测
    # 确定聚类类别数量
    k = 5
    # 创建算法实例
    km = KMeans(n_clusters=k)
    # 训练数据
    km.fit(data.values)
    # 进行预测
    y_predict = km.predict(data.values)
    # 预测中心
    center = km.cluster_centers_
    print('预测值:\n',y_predict)
    print('聚类中心:\n',center)

    # 7.数据可视化--折线图、散点图、直方图、柱状图、饼图、箱线图
    show_res(data.values,y_predict,center)

    # 8.结论

if __name__ == '__main__':
    main()

三、补充

(一)3sigma

在这里插入图片描述

异常值处理之3sigma

import pandas as pd

# 3sigma原则
# [mean-3*std,mean+s*std]
# 99.73%的数据

def three_sigma(data):
    '''
    进行3sigma异常值处理
    :param data: 需要进行处理的数据--series
    :return: bool数组
    '''
    # 下限
    low = data.mean() - 3*data.std()
    up = data.mean() + 3*data.std()

    # 正常--True,异常--False
    bool_index = (low <= data) & (data <= up)

    return bool_index

# 验证异常值处理
detail = pd.read_excel('meal_order_detail.xlsx')
# print(detail)
# print(detail.columns)
print(detail.shape[0])

# 对菜品的单价数据进行异常值剔除
bool_index = three_sigma(detail.loc[:, "amounts"])

detail = detail.loc[bool_index,:]
# print('按照菜品单价剔除异常值之后的结果\n',detail)
print(detail.shape[0])

(二)标准化

量级相差过大,就需要进行标准化

1.离差标准化

x = (x-min)/(max-min)

2.标准差标准化(推荐)

x = (x-mean)/std

3.小数定标标准化

通过移动数据的小数点位置来进行标准化。

k --> int(np.ceil(np.log10(|x|.max())))

x = x/10^k

(三)维度

行的方向是行增大的方向,即向下

列的方向是列增大的方向,即向右

1.一维

shape:(9,)

一维的数组只有列维度

axis=0,axis=-1 – 代表列维度

2.二维(多个一维组成)

shape:(2,3)

行列维度

axis=0,axis=-2 – 代表行维度

axis=1,axis=-1 – 代表列维度

3.三维(多个二维组成)

shape:(1,2,3)

块行列维度

axis=0 – 代表块维度

axis=1 – 代表行维度

axis=2 – 代表列维度

4.四维(多个三维组成)

shape:(1,2,3,4)

堆块行列维度

……

……

mean()默认维度测试

import numpy as np
import pandas as pd

df = pd.DataFrame(data=np.array([[1,2,5],[1,3,4],[4,4,5]]))

print(df)
print(df.mean())

#    0  1  2
# 0  1  2  5
# 1  1  3  4
# 2  4  4  5
# 0    2.000000
# 1    3.000000
# 2    4.666667
# dtype: float64

发现最终的结果,求的是一列的平均值,即行增大的方向,也就是按行的方向求的。

即mean()默认的axis=0。

四、作业

  1. 将NBA实例的sklearn实现改为自实现
  2. 超市用户聚类案例

(一)NBA–自实现

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def bulid_data(data):
    data = data.loc[:,['时间','助攻','得分']]
    # res_null = pd.isnull(data).sum()
    # print(res_null)
    data.loc[:,'时间'].replace(' ',np.NaN,inplace=True)
    data.loc[:,'时间'].fillna(method='pad',inplace=True)
    data.loc[:'时间'] = data.loc[:'时间'].astype(np.float64)
    data.loc[:,'助攻/时间'] = data.loc[:,'助攻']/data.loc[:,'时间']
    data.loc[:,'得分/时间'] = data.loc[:,'得分']/data.loc[:,'时间']
    data = data.loc[:,['得分/时间','助攻/时间']]
    return np.mat(data.values)

def center_init(data,k):
    index_num = data.shape[0]
    column_num = data.shape[1]
    # print(index_num)
    center = np.zeros((k,column_num))
    r_list = []
    i = 0
    while True:
        r = np.random.randint(0,index_num-1)
        if r in r_list:
            continue
        else:
            r_list.append(r)
            center[i,:] = data[r,:]
            i += 1
        if len(r_list) == k:
            break
    return center

def distance(v1,v2):
    diff = v1-v2
    return np.sqrt(np.sum(np.power(diff,2)))

def k_means_owns(data,k):
    # 随机选取k个聚类中心
    center = center_init(data,k)

    index_num = data.shape[0]
    new_data = np.zeros((index_num,2))
    flag = True
    while flag:
        flag = False
        for i in range(index_num):
            min_distence = 1000000000000000
            min_index = -1
            for j in range(k):
                # 计算距离聚类中心距离
                d = distance(data[i,:],center[j,:])
                if d < min_distence:
                    min_distence = d
                    min_index = j
            if new_data[i,0] != min_index:
                flag = True
                new_data[i,:] = min_index,min_distence

        if flag:
            # 计算新的聚类中心
            for p in range(k):
                bool_index = new_data[:,0] == p
                p_cluster = data[bool_index,:]
                center[p,:] = p_cluster[:,0].mean(),p_cluster[:,1].mean()
    return new_data,center

def show_res(data,new_data,center):
    plt.figure()
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    c_list = ['c','g','y','pink','red']
    marker_list = ['*','o','^','D','8']
    # 绘制样本数据
    for i in range(data.shape[0]):
        plt.scatter(data[i,0],data[i,1],c=c_list[int(new_data[i,0])],marker=marker_list[int(new_data[i,0])])
    # 绘制聚类中心
    plt.plot(center[:, 0], center[:, 1], 'bx', markersize=12)
    plt.title('NBA球星聚类分析结果')
    plt.savefig('NBA球星聚类分析结果')
    plt.show()

def main():
    # 读取数据
    data = pd.read_excel('../03.实例:基于k_means算法实现NBA球员聚类分析/nba_data.xlsx')
    # print(data)
    # 构建数据
    data = bulid_data(data)
    # k-means自实现
    # 确定聚类中心个数
    k = 5
    new_data,center = k_means_owns(data, k)
    show_res(data,new_data,center)

if __name__ == '__main__':
    main()

(二)超市用户–sklearn

import numpy as np
import pandas as pd
from sklearn.cluster import KMeans
import matplotlib.pyplot as plt

def stand_sca(data):
    '''
    标准差标准化
    :param data:需要标准化的数据
    :return:标准化后的数据
    '''
    data = (data-data.mean())/data.std()
    return data

def min_max_sca(data):
    '''
    离差标准化
    :param data: 需要标准化的数据
    :return: 标准化后的数据
    '''
    data = (data-data.min(axis=0))/(data.max(axis=0)-data.min(axis=0))
    return data

def desc_sca(data):
    '''
    小数定标标准化
    :param data: 需要标准化的数据
    :return: 标准化之后的数据
    '''
    k = int(np.ceil(np.log10(data.abs().max())))
    data = data / (10**k)
    return data

def build_data():
    # 1.构建数据
    data = pd.read_table('company.csv', sep=',', encoding='gbk')

    # 2.筛选特征值
    data = data.loc[:,['平均每次消费金额','平均消费周期(天)']]

    # 3.缺失值检测
    # res_null = pd.isnull(data).sum()
    # print(res_null)

    # 4.处理异常值
    # 无异常值

    # 5.标准化
    # (1)标准差标准化
    # data = stand_sca(data)
    # (2)离差标准化
    data = min_max_sca(data)
    return np.mat(data.values)

def k_means(data):
    # 确定聚类中心个数
    k = 3
    # 1.创建算法实例
    km = KMeans(n_clusters=k)
    # 2.训练数据
    km.fit(data)
    # 3.进行预测
    y_predict = km.predict(data)
    # 获取聚类中心
    center = km.cluster_centers_
    # print('预测值:\n',y_predict)
    # print('聚类中心:\n',center)
    return y_predict,center

def show(data,y_predict,center):
    plt.figure()
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    c_list = ['pink','yellow','green','blue']
    marker_list = ['*','>','^','o']
    for i in range(data.shape[0]):
        plt.scatter(data[i,0],data[i,1],c=c_list[y_predict[i]],marker=marker_list[y_predict[i]])
    plt.plot(center[:,0],center[:,1],'bx',markersize=12)
    plt.title('超市用户聚类结果')
    plt.savefig('超市用户聚类结果')
    plt.show()

def main():
    data = build_data()
    # print(data)
    y_predict,center = k_means(data)
    show(data,y_predict,center)

if __name__ == '__main__':
    main()

(三)超市用户–自实现

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

def stand_sca(data):
    '''
    标准差标准化
    '''
    data = (data - data.mean())/data.std()
    return data

def min_max_sca(data):
    '''
    离差标准化
    '''
    data = (data - data.min())/(data.max()-data.min())
    return data

def build_data():
    # 获取数据
    data = pd.read_table('company.csv', sep=',', encoding='gbk')

    # 获取有效数据
    data = data.loc[:,['平均每次消费金额','平均消费周期(天)']]

    # 检测缺失值
    # res_null = pd.isnull(data).sum()
    # print(res_null)

    # 检测异常值
    # 无异常值

    # 标准化
    data = min_max_sca(data)

    return np.mat(data.values)

def center_init(data,k):
    index_num = data.shape[0]
    center = np.zeros((k,data.shape[1]))
    r_list = []
    i = 0
    while True:
        r = np.random.randint(0,index_num-1)
        if r in r_list:
            continue
        else:
            center[i,:] = data[r,:]
            r_list.append(r)
            i += 1
        if len(r_list) == k:
            break
    return center

def distance(v1,v2):
    diff = v1-v2
    d = np.sqrt(np.sum(np.power(diff,2)))
    return d

def k_means_owns(data,k):
    center = center_init(data,k)
    # print(center)

    index_num = data.shape[0]
    column_num = data.shape[1]
    new_data = np.zeros((index_num,column_num))
    for i in range(index_num):
        min_dis = 1000000000000
        min_index = -1
        for j in range(k):
            d = distance(data[i,:],center[j,:])
            if d < min_dis:
                min_dis = d
                min_index = j
        new_data[i,:] = min_index,min_dis

    for p in range(k):
        bool_index = new_data[:,0] == p
        p_cluster = data[bool_index,:]
        center[p,:] = p_cluster[:,0].mean(),p_cluster[:,1].mean()
    return new_data,center

def show(data,new_data,center):
    plt.figure()
    plt.rcParams['font.sans-serif'] = 'SimHei'
    plt.rcParams['axes.unicode_minus'] = False
    c_list = ['pink','yellow','green','blue']
    marker_list = ['*','>','^','o']
    for i in range(data.shape[0]):
        plt.scatter(data[i,0],data[i,1],c=c_list[int(new_data[i,0])],marker=marker_list[int(new_data[i,0])])
    plt.plot(center[:,0],center[:,1],'bx',markersize=12)
    plt.title('超市用户聚类结果')
    plt.savefig('超市用户聚类结果')
    plt.show()

def main():
    data = build_data()
    print(data)
    k = 3
    new_data,center = k_means_owns(data,k)
    show(data,new_data,center)

if __name__ == '__main__':
    main()
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章