lvah

lvah 查看完整档案

填写现居城市  |  填写毕业院校  |  填写所在公司/组织填写个人主网站
编辑
_ | |__ _ _ __ _ | '_ \| | | |/ _` | | |_) | |_| | (_| | |_.__/ \__,_|\__, | |___/ 个人简介什么都没有

个人动态

lvah 发布了文章 · 2019-04-17

机器学习(八)-基于KNN分类算法的手写识别系统

1 项目介绍

基于k-近邻分类器(KNN)的手写识别系统, 这里构造的系统只能识别数字0到9。

数据集和项目源代码

  • 难点: 图形信息如何处理?

图像转换为文本格式

2 准备数据

将图像转换为测试向量

  • 训练集:

    • 目录trainingDigits
    • 大约2000个例子
    • 每个数字大约有200个样本;
  • 测试集

    • 目录testDigits
    • 大约900个测试数据。

将图像格式化处理为一个向量。我们将把一个32×32的二进制图像矩阵转换为1×1024的向量, 如下图所示,
在这里插入图片描述


import numpy as np
def img2vector(filename):
    """
    # 将图像数据转换为(1,1024)向量
    :param filename: 
    :return: (1,1024)向量
    """
    # 生成一个1*1024且值全为0的向量;
    returnVect = np.zeros((1, 1024))
    # 读取要转换的信息;
    file = open(filename)
    # 依次填充
    # 读取每一行数据;
    for i in range(32):
        lineStr = file.readline()
        # 读取每一列数据;
        for j in range(32):
            returnVect[0, 32 * i + j] = int(lineStr[j])
    return returnVect

3 实施 KNN 算法

对未知类别属性的数据集中的每个点依次执行以下操作, 与上一个案例代码相同:
(1) 计算已知类别数据集中的点与当前点之间的距离;
(2) 按照距离递增次序排序;
(3) 选取与当前点距离最小的k个点;
(4) 确定前k个点所在类别的出现频率;
(5) 返回前k个点出现频率最高的类别作为当前点的预测分类。


def classify(inX, dataSet, labels, k):
    """
    :param inX: 要预测的数据
    :param dataSet: 我们要传入的已知数据集
    :param labels:  我们要传入的标签
    :param k: KNN里的k, 也就是说我们要选几个近邻
    :return: 排序的结果
    """
    dataSetSize = dataSet.shape[0]  # (6,2) 6
    # tile会重复inX, 把他重复成(datasetsize, 1)型的矩阵
    # print(inX)
    # (x1 - y1), (x2- y2)
    diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
    # 平方
    sqDiffMat = diffMat ** 2
    # 相加, axis=1 行相加
    sqDistance = sqDiffMat.sum(axis=1)
    # 开根号
    distances = sqDistance ** 0.5
    # print(distances)
    # 排序 输出的是序列号index,并不是值
    sortedDistIndicies = distances.argsort()
    # print(sortedDistIndicies)

    classCount = {}
    for i in range(k):
        voteLabel = labels[sortedDistIndicies[i]]
        classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
        # print(classCount)
    sortedClassCount = sorted(classCount.items(), key=lambda d: float(d[1]), reverse=True)
    return sortedClassCount[0]

4 测试算法

使用 k-近邻算法识别手写数字

  • 测试集里面的信息;

在这里插入图片描述

def handWritingClassTest(k):
    """
    # 测试手写数字识别错误率的代码
    :param k:
    :return:
    """
    hwLabels = []
    import os
    # 读取所有的训练集文件;
    trainingFileList = os.listdir('data/knn-digits/trainingDigits')
    # 获取训练集个数;
    m = len(trainingFileList)
    # 生成m行1024列全为0的矩阵;
    trainingMat = np.zeros((m, 1024))
    # 填充训练集矩阵;
    for i in range(m):
        fileNameStr = trainingFileList[i]    # fileNameStr: 0_0.txt
        fileStr = fileNameStr.split('.')[0]  # fileStr: 0_0
        classNumStr = int(fileStr.split('_')[0])    # (数字分类的结果)classNumStr: 0
        # 填写真实的数字结果;
        hwLabels.append(classNumStr)
        # 图形的数据: (1,1024)向量
        trainingMat[i, :] = img2vector("data/knn-digits/trainingDigits/%s" % fileNameStr)

    # 填充测试集矩阵;
    testFileList = os.listdir('data/knn-digits/testDigits')
    # 默认错误率为0;
    errorCount = 0.0
    # 测试集的总数;
    mTest = len(testFileList)
    # 填充测试集矩阵;
    for i in range(mTest):
        fileNameStr = testFileList[i]
        fileStr = fileNameStr.split('.')[0]
        classNumStr = int(fileStr.split('_')[0])
        vectorTest = img2vector("data/knn-digits/testDigits/%s" % fileNameStr)

        # 判断预测结果与真实结果是否一致?
        result = classify(vectorTest, trainingMat, hwLabels, k)

        if result != classNumStr:
            # 如果不一致,则统计出来, 计算错误率;
            errorCount += 1.0
            print("[预测失误]:分类结果是:%d, 真实结果是:%d" % (result, classNumStr))
    print("错误总数:%d" % errorCount)
    print("错误率:%f" % (errorCount / mTest))
    print("模型准确率:%f" %(1-errorCount / mTest))
    return errorCount


print(handWritingClassTest(2))
  • 效果展示

在这里插入图片描述

5 KNN算法手写识别的缺点

算法的执行效率并不高。

  • 每个测试向量做2000次距离计算,每个距离计算包括了1024个维度浮点运算,总计要执行900次;
  • 需要为测试向量准备2MB的存储空间

有没有更好的方法?

  • k决策树就是k-近邻算法的优化版,可以节省大量的计算开销。
查看原文

赞 0 收藏 0 评论 0

lvah 发布了文章 · 2019-04-17

机器学习(七)-基于KNN分类的约会网站配对改进算法

1 项目介绍

某APP用户一直使用在线约会软件寻找适合自己的约会对象。尽管约会网站会推荐不同的人选,但她并不是喜欢每一个人。经过一番总结,她发现曾交往过三种类型的人:

  • 不喜欢的人(3)
  • 魅力一般的人(2)
  • 极具魅力的人(1)

某APP用户希望分类软件可以更好地帮助她将匹配对象划分到确切的分类中。此外还可以收集了约会软件未曾记录的数据信息,她认为这些数据更有助于匹配对象的归类。收集的部分信息如下图所示:
数据集下载
在这里插入图片描述
样本主要包含以下3种特征:

  • 每年获得的飞行常客里程数
  • 玩视频游戏所耗时间百分比
  • 每周消费的冰淇淋公升数

2 准备数据:从文本文件中解析数据

在将上述特征数据输入到分类器之前,必须将待处理数据的格式改变为分类器可以接受的格式。


import numpy as np
def file2matrix(filename):
    """

    :param filename: APP用户收集的约会数据的文件名
    :return:
        returnMat: 用户提供的每行数据信息,三列,
                    分别是每年获得的飞行常客里程数,
                    玩视频游戏所耗时间百分比,
                    每周消费的冰淇淋公升数
        classLabelVetor:
                    用户的评价信息, 一般分为3类(1,2,3)

    """
    fr = open(filename)
    arrayOfLines = fr.readlines()
    # print(arrayOfLines)
    # 获得文件行数;
    numerOfLines = len(arrayOfLines)
    # 创建要返回的Numpy矩阵;
    returnMat = np.zeros((numerOfLines, 3))
    # 解析文件数据到矩阵中;
    classLabelVetor = []
    index = 0
    for line in arrayOfLines:
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index, :] = listFromLine[0:3]
        classLabelVetor.append(listFromLine[-1])
        index += 1
    return returnMat, classLabelVetor

print(file2matrix('data/datingTestSet2'))

返回的值显示:

在这里插入图片描述

3 分析数据:使用 Matplotlib 创建散点图

使用Matplotlib库图形化清晰地标识了三个不同的样本分类区域,具有不同爱好的人其类别区域也不同。

def draw_pic(datingDataMat, datingLabels):
    """
    每年获取的飞行常客里程数与每周所消费的冰淇淋公升数”构成的散点图。
    :param datingDataMat:
    :param datingLabels:
    :return:
    """
    #  中文显示乱码问题;
    myfont = font_manager.FontProperties(fname="/usr/share/fonts/cjkuni-uming/uming.ttc", size=12)
    # 创建画布
    fig = plt.figure()
    ax = fig.add_subplot(111)
    ax.scatter(datingDataMat[:, 0], datingDataMat[:, 2],
               15 * datingLabels, datingLabels)

    plt.xlabel("每年的飞行里程数", fontproperties=myfont)
    plt.ylabel("每周消费的冰淇淋公升数", fontproperties=myfont)
    plt.grid(alpha=0.5)
    plt.show()

  • 效果展示

在这里插入图片描述

4 准备数据:归一化数值

  • 计算样本3和样本4之间的距离:

在这里插入图片描述

    • 问题:
      飞行常客里程数对于计算结果的影响将远远大于其他两个特征的影响
    • 解决方式:
      处理不同取值范围的特征值时,通常采用的方法是将数值归一化,如将取值范围处理为0到1或者-1到1之间。
    • 归一化公式: newValue = oldValue / max
    def autoNorm(dataSet):
        """
         归一化数值,
        :param dataSet:用户提供的每行数据信息,三列;
        :return:
            normDataSet: 归一化的特征信息;
            maxVals:每个特征数据的最大值;
        """
        # 获取每个特征数据的最大值;
        maxVals = dataSet.max(0)
        # 获取样本个数;
        m = dataSet.shape[0]
        # 根据公式生成归一化的特征信息;
        normDataSet = dataSet / np.tile(maxVals, (m, 1))
        return normDataSet, maxVals

    4 实施 kNN 算法

    对未知类别属性的数据集中的每个点依次执行以下操作, 与上一个案例代码相同:
    (1) 计算已知类别数据集中的点与当前点之间的距离;
    (2) 按照距离递增次序排序;
    (3) 选取与当前点距离最小的k个点;
    (4) 确定前k个点所在类别的出现频率;
    (5) 返回前k个点出现频率最高的类别作为当前点的预测分类。

    def classify(inX, dataSet, labels, k):
        """
        :param inX: 要预测的数据
        :param dataSet: 我们要传入的已知数据集
        :param labels:  我们要传入的标签
        :param k: KNN里的k, 也就是说我们要选几个近邻
        :return: 排序的结果
        """
        dataSetSize = dataSet.shape[0]  # (6,2) 6
        # tile会重复inX, 把他重复成(datasetsize, 1)型的矩阵
        # print(inX)
        # (x1 - y1), (x2- y2)
        diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
        # 平方
        sqDiffMat = diffMat ** 2
        # 相加, axis=1 行相加
        sqDistance = sqDiffMat.sum(axis=1)
        # 开根号
        distances = sqDistance ** 0.5
        # print(distances)
        # 排序 输出的是序列号index,并不是值
        sortedDistIndicies = distances.argsort()
        # print(sortedDistIndicies)
    
        classCount = {}
        for i in range(k):
            voteLabel = labels[sortedDistIndicies[i]]
            classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
            # print(classCount)
        sortedClassCount = sorted(classCount.items(), key=lambda d: float(d[1]), reverse=True)
        return sortedClassCount[0]
    

    5 测试算法:作为完整程序验证分类器

    如果分类器的正确率满足要求,就可以使用这个软件来处理约会网站提供的约会名单了。机器学习算法一个很重要的工作就是评估算法的正确率,通常我们只提供已有数据的90%作为训练样本来训练分类器,而使用其余的10%数据去测试分类器,检测分类器的正确率。

    def datingClassTest():
        """
        分类器针对约会网站的测试代码, 获取错误率;
        :return:
        """
        hoRatio = 0.10
        datingDataMat, datingLabels = file2matrix('data/datingTestSet2')
        normDataSet, maxVals = autoNorm(datingDataMat)
        # 样本个数
        m = normDataSet.shape[0]
        # 测试集个数;
        numTestVecs = int(m*hoRatio)
        errorCount = 0.0
    
        for i in range(numTestVecs):
            classiferResult = classify(normDataSet[i, :],
                                       normDataSet[numTestVecs:m, :],
                                       datingLabels[numTestVecs:m], 3)
            # print(classiferResult)
            if classiferResult != datingLabels[i]:
                errorCount += 1
                print("正确结果:", datingLabels[i])
                print("预测结果:", classiferResult)
    
        # print("错误个数:", errorCount)
        return  errorCount
    • 执行效果展示:

    在这里插入图片描述

    6 使用算法:构建完整可用的预测系统

    
    def classifyPerson(Person):
        """
        使用这个分类器为某APP用户来对人们分类。
        :param Person:
        :return:
        """
        datingDataMat, datingLabels = file2matrix('data/datingTestSet2')
        normDataSet, maxVals = autoNorm(datingDataMat)
        classiferResult = classify(Person / maxVals, normDataSet, datingLabels, 3)
        if classiferResult  == '1':
            print("不喜欢")
        elif classiferResult == '2':
            print("有一点喜欢")
        else:
            print("非常喜欢")

    完整代码

    
    # encoding:utf-8
    
    
    """
    KNN实现,基于KNN分类的约会网站配对改进算法
    """
    import numpy as np
    import matplotlib.pyplot as plt
    from matplotlib import font_manager
    
    
    def file2matrix(filename):
        """
    
        :param filename: APP用户收集的约会数据的文件名
        :return:
            returnMat: 用户提供的每行数据信息,三列,
                        分别是每年获得的飞行常客里程数,
                        玩视频游戏所耗时间百分比,
                        每周消费的冰淇淋公升数
            classLabelVetor:
                        用户的评价信息, 一般分为3类(1,2,3)
    
        """
        fr = open(filename)
        arrayOfLines = fr.readlines()
        # print(arrayOfLines)
        # 获得文件行数;
        numerOfLines = len(arrayOfLines)
        # 创建要返回的Numpy矩阵;
        returnMat = np.zeros((numerOfLines, 3))
        # 解析文件数据到矩阵中;
        classLabelVetor = []
        index = 0
        for line in arrayOfLines:
            line = line.strip()
            listFromLine = line.split('\t')
            returnMat[index, :] = listFromLine[0:3]
            classLabelVetor.append(listFromLine[-1])
            index += 1
        return returnMat, classLabelVetor
    
    
    def autoNorm(dataSet):
        """
        归一化数值,
        计算样本3和样本4之间的距离: [(0-67)**2 + (20000 - 32 000)**2 + (1.1 - 0.1)**2]**0.5
        问题:
                飞行常客里程数对于计算结果的影响将远远大于其他两个特征的影响
        解决方式:
                处理不同取值范围的特征值时,
                通常采用的方法是将数值归一化,如将取值范围处理为0到1或者-1到1之间。
                归一化公式: newValue = oldValue / max
        :param dataSet:用户提供的每行数据信息,三列;
        :return:
            normDataSet: 归一化的特征信息;
            maxVals:每个特征数据的最大值;
        """
        # 获取每个特征数据的最大值;
        maxVals = dataSet.max(0)
        # 获取样本个数;
        m = dataSet.shape[0]
        # 根据公式生成归一化的特征信息;
        normDataSet = dataSet / np.tile(maxVals, (m, 1))
        return normDataSet, maxVals
    
    
    def draw_pic(datingDataMat, datingLabels):
        """
        每年获取的飞行常客里程数与每周所消费的冰淇淋公升数”构成的散点图。
        :param datingDataMat:
        :param datingLabels:
        :return:
        """
        #  中文显示乱码问题;
        myfont = font_manager.FontProperties(fname="/usr/share/fonts/cjkuni-uming/uming.ttc", size=12)
        # 创建画布
        fig = plt.figure()
        ax = fig.add_subplot(111)
        ax.scatter(datingDataMat[:, 0], datingDataMat[:, 2],
                   15 * datingLabels, datingLabels)
    
        plt.xlabel("每年的飞行里程数", fontproperties=myfont)
        plt.ylabel("每周消费的冰淇淋公升数", fontproperties=myfont)
        plt.grid(alpha=0.5)
        plt.show()
    
    
    def classify(inX, dataSet, labels, k):
        """
        :param inX: 要预测的数据
        :param dataSet: 我们要传入的已知数据集
        :param labels:  我们要传入的标签
        :param k: KNN里的k, 也就是说我们要选几个近邻
        :return: 排序的结果
        """
        dataSetSize = dataSet.shape[0]  # (6,2) 6
        # tile会重复inX, 把他重复成(datasetsize, 1)型的矩阵
        # print(inX)
        # (x1 - y1), (x2- y2)
        diffMat = np.tile(inX, (dataSetSize, 1)) - dataSet
        # 平方
        sqDiffMat = diffMat ** 2
        # 相加, axis=1 行相加
        sqDistance = sqDiffMat.sum(axis=1)
        # 开根号
        distances = sqDistance ** 0.5
        # print(distances)
        # 排序 输出的是序列号index,并不是值
        sortedDistIndicies = distances.argsort()
        # print(sortedDistIndicies)
    
        classCount = {}
        for i in range(k):
            voteLabel = labels[sortedDistIndicies[i]]
            classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
            # print(classCount)
        sortedClassCount = sorted(classCount.items(), key=lambda d: float(d[1]), reverse=True)
        return sortedClassCount[0][0]
    
    def datingClassTest():
        """
        分类器针对约会网站的测试代码, 获取错误率;
        :return:
        """
        hoRatio = 0.10
        datingDataMat, datingLabels = file2matrix('data/datingTestSet2')
        normDataSet, maxVals = autoNorm(datingDataMat)
        # 样本个数
        m = normDataSet.shape[0]
        # 测试集个数;
        numTestVecs = int(m*hoRatio)
        errorCount = 0.0
    
        for i in range(numTestVecs):
            classiferResult = classify(normDataSet[i, :],
                                       normDataSet[numTestVecs:m, :],
                                       datingLabels[numTestVecs:m], 3)
            # print(classiferResult)
            if classiferResult != datingLabels[i]:
                errorCount += 1
                print("正确结果:", datingLabels[i])
                print("预测结果:", classiferResult)
    
        # print("错误个数:", errorCount)
        return  errorCount
    
    
    
    
    
    
    def classifyPerson(Person):
        """
        使用这个分类器为某APP用户来对人们分类。
        :param Person:
        :return:
        """
        datingDataMat, datingLabels = file2matrix('data/datingTestSet2')
        normDataSet, maxVals = autoNorm(datingDataMat)
        classiferResult = classify(Person / maxVals, normDataSet, datingLabels, 3)
        if classiferResult  == '1':
            print("不喜欢")
        elif classiferResult == '2':
            print("有一点喜欢")
        else:
            print("非常喜欢")
    
    
    if __name__ == '__main__':
        # personData = [30000, 10, 1.3]
        personData = [40920, 8.326976, 0.953952]
        classifyPerson(personData)
    
    
    • 执行结果

    在这里插入图片描述

    查看原文

    赞 0 收藏 0 评论 0

    lvah 发布了文章 · 2019-04-17

    机器学习(六)-基于KNN分类算法的自动划分电影的题材类型实现

    1 分类算法引言

    众所周知,电影可以按照题材分类,然而题材本身是如何定义的?由谁来判定某部电影属于哪个题材?也就是说同一题材的电影具有哪些公共特征?这些都是在进行电影分类时必须要考虑的问题。

    • 动作片中也会存在接吻镜头,爱情片中也会存在打斗场景,我们不能单纯依靠是否存在打斗或者亲吻来判断影片的类型。
    • 爱情片中的亲吻镜头更多,动作片中的打斗场景也更频繁,基于此类场景在某部电影中出现的次数可以用来进行电影分类。

    那么如何基于电影中出现的亲吻、打斗出现的次数,使用k-近邻算法构造程序,自动划分电影的题材类型。

    2 KNN算法及工作原理

    k-近邻(KNN)算法采用测量不同特征值之间的距离方法进行分类。

    • 存在一个样本数据集合,也称作训练样本集,并且样本集中每个数据都存在标签,即我们知道样本集中每一数据与所属分类的对应关系。
    • 输入没有标签的新数据后,将新数据的每个特征与样本集中数据对应的特征进行比较,然后算法提取样本集中特征最相似数据(最近邻)的分类标签。

    一般来说,我们只选择样本数据集中前k个最相似的数据,通常k是不大于20的整数。最后,选择k个最相似数据中出现次数最多的分类,作为新数据的分类。

    3 KNN的第一个实例:电影的分类

    3.1 项目介绍

    动作,爱情,喜剧,灾难…???

    在这里插入图片描述

    • 使用打斗和接吻镜头数分类电影

    在这里插入图片描述

    • 每部电影的打斗镜头数、接吻镜头数以及电影评估类型

    在这里插入图片描述

    • 已知电影与未知电影的距离

    得到了距离后,选择前k个电影来判断未知电影的类型
    在这里插入图片描述

    3.2 如何求距离?------欧氏距离公式

    • 二维空间

    在这里插入图片描述

    • 多维空间

    在这里插入图片描述

    3.3 k-近邻算法的一般流程

    (1) 收集数据:可以使用任何方法。
    (2) 准备数据:距离计算所需要的数值,最好是结构化的数据格式。
    (3) 分析数据:可以使用任何方法。
    (4) 训练算法:此步骤不适用于k-近邻算法。
    (5) 测试算法:计算错误率。
    (6) 使用算法:首先需要输入样本数据和结构化的输出结果,然后运行k-近邻算法判定输
    入数据分别属于哪个分类,最后应用对计算出的分类执行后续的处理。

    3.4 数据准备:使用 Python 导入数据

    import numpy as np
    def createDataSet():
        """创建数据集"""
        # 每组数据包含打斗数和接吻数;
        group = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
        # 每组数据对应的标签类型;
        labels = ['Roman', 'Roman', 'Roman', 'Action', 'Action', 'Action']
        return group, labels
    

    3.5 实施 KNN 算法

    对未知类别属性的数据集中的每个点依次执行以下操作:
    (1) 计算已知类别数据集中的点与当前点之间的距离;
    (2) 按照距离递增次序排序;
    (3) 选取与当前点距离最小的k个点;
    (4) 确定前k个点所在类别的出现频率;
    (5) 返回前k个点出现频率最高的类别作为当前点的预测分类。

    def classify(inx, dataSet, labels, k):
        """
        KNN分类算法实现
        :param inx:要预测电影的数据, e.g.[18, 90]
        :param dataSet:传入已知数据集,e.g. group 相当于x
        :param labels:传入标签,e.g. labels相当于y
        :param k:KNN里面的k,也就是我们要选择几个近邻
        :return:电影类新的排序
        """
        dataSetSize = dataSet.shape[0]  # (6,2) -- 6行2列 ===> 6 获取行数
        # tile会重复inx, 把它重复成(dataSetSize, 1)型的矩阵
        # (x1 - y1), (x2 - y2)
        diffMat = np.tile(inx, (dataSetSize, 1)) - dataSet
        # 平方
        sqDiffMat = diffMat ** 2
        # 相加, axis=1行相加
        sqDistance = sqDiffMat.sum(axis=1)
        # 开根号
        distance = sqDistance ** 0.5
        # 排序索引: 输出的是序列号index, 而不是值
        sortedDistIndicies = distance.argsort()
        # print(sortedDistIndicies)
    
        classCount = {}
        for i in range(k):
            # 获取排前k个的标签名;
            voteLabel = labels[sortedDistIndicies[i]]
            classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
    
        sortedClassCount = sorted(classCount.items(),
                                  key=lambda d: float(d[1]),
                                  reverse=True)
        return sortedClassCount[0]

    3.6 如何测试分类器

    • 分类器并不会得到百分百正确的结果,我们可以使用多种方法检测分类器的正确率。
    • 为了测试分类器的效果,我们可以使用已知答案的数据,当然答案不能告诉分类器,检验分类器给出的结果是否符合预期结果。

      • 完美分类器的错误率为0
      • 最差分类器的错误率是1.0

    完整代码

    import numpy as np
    
    
    def createDataSet():
        """创建数据集"""
        # 每组数据包含打斗数和接吻数;
        group = np.array([[3, 104], [2, 100], [1, 81], [101, 10], [99, 5], [98, 2]])
        # 每组数据对应的标签类型;
        labels = ['Roman', 'Roman', 'Roman', 'Action', 'Action', 'Action']
        return group, labels
    
    
    def classify(inx, dataSet, labels, k):
        """
        KNN分类算法实现
        :param inx:要预测电影的数据, e.g.[18, 90]
        :param dataSet:传入已知数据集,e.g. group 相当于x
        :param labels:传入标签,e.g. labels相当于y
        :param k:KNN里面的k,也就是我们要选择几个近邻
        :return:电影类新的排序
        """
        dataSetSize = dataSet.shape[0]  # (6,2) -- 6行2列 ===> 6 获取行数
        # tile会重复inx, 把它重复成(dataSetSize, 1)型的矩阵
        # (x1 - y1), (x2 - y2)
        diffMat = np.tile(inx, (dataSetSize, 1)) - dataSet
        # 平方
        sqDiffMat = diffMat ** 2
        # 相加, axis=1行相加
        sqDistance = sqDiffMat.sum(axis=1)
        # 开根号
        distance = sqDistance ** 0.5
        # 排序索引: 输出的是序列号index, 而不是值
        sortedDistIndicies = distance.argsort()
        # print(sortedDistIndicies)
    
        classCount = {}
        for i in range(k):
            # 获取排前k个的标签名;
            voteLabel = labels[sortedDistIndicies[i]]
            classCount[voteLabel] = classCount.get(voteLabel, 0) + 1
    
        sortedClassCount = sorted(classCount.items(),
                                  key=lambda d: float(d[1]),
                                  reverse=True)
        return sortedClassCount[0][0]
    
    
    if __name__ == '__main__':
        group, label = createDataSet()
        result = classify([3, 104], group, label, 5)
        print("[3, 104]的电影类型:",  result)
    • 效果展示

    在这里插入图片描述

    查看原文

    赞 0 收藏 0 评论 0

    lvah 发布了文章 · 2019-04-17

    机器学习(五)-保险保费的多元线性回归模型案例

    1. 项目描述

    保险公司对个人投保时或根据历史数据生成的模型来计算个人保费,那么本次我们就以这个模型的求解过程为例来实践下多元线性回归。

    2 数据与简单分析

    数据集下载
    数据信息如下图所示:
    在这里插入图片描述

    我们已经获取到保险公司部分数据,文件名为insurance.csv,文件内容如下。
    我们可以看出数据中共有六个维度:age(年龄),sex(性别),bmi(肥胖指数),children(孩子数量),smoker(是否吸烟),region(居住地)。charges则是当前数据人上年度在保险的额度。
    所以我们可以构建一个六维高维空间来求解这个模型。

    • 相对于年龄来说, 年龄越大, 购买保险的金额应该越大;
    • 相对于性别来说,整体女性的寿命大于男性寿命大约10年, 因此男性的保险额度应该更大。
    • 相对于肥胖指数来说, 肥胖指数越小, 身体状况越不好, 购买保险的金额应该越大;
    • 相对于孩子的数量来说, 孩子的数量越多, 压力越大, 越劳累, 购买保险的金额应该越大;
    • 相对于是否吸烟来说, 吸烟的人寿命远少于不吸烟的寿命, 因此 购买保险的金额应该越大;
    • 相对于地区来说, 地区环境越差, 有雾霾, 则越容易生病, 那么购买保险的金额应该越大;

    最后说明一下,本章中的数据来源主要是来自某保险公司内部的真实历史数据。

    3 项目实践

    完成本项目后,您将知道:

    • 如何从训练数据中估计统计量。
    • 如何从数据估计线性回归系数。
    • 如何使用线性回归预测新数据。
    import pandas as pd
    import numpy as np
    import  matplotlib.pyplot as plt
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    
    # 1). 读取csv文件数据;
    filename = 'data/insurance.csv'
    data = pd.read_csv(filename)
    
    # 2). 清洗数据
    reg = LinearRegression()
    x = data[['age', 'sex', 'bmi', 'children', 'smoker', 'region']]
    y = data['charges']
    # 转换数据类型为整形
    x = x.apply(pd.to_numeric, errors='corece')
    y = y.apply(pd.to_numeric, errors='coerce')
    # 填充空值
    x.fillna(0, inplace=True)
    y.fillna(0, inplace=True)
    
    print(x)
    print(y)
    
    
    # 3). 开始建模
    # degree: 多项式的阶数,一般默认是2;
    # interaction_only:如果值为true(默认是false),则会产生相互影响的特征集。
    # include_bias:是否包含偏差列
    poly_features = PolynomialFeatures(degree=2, include_bias=False)
    # 降维
    X_poly = poly_features.fit_transform(x)
    
    
    # 4). 用线性回归进行拟合
    reg.fit(X_poly, y)
    print(reg.coef_)
    print(reg.intercept_)
    
    # 5). 预测
    y_predict = reg.predict(X_poly)
    
    
    # 5). 真实的y值绘制:图形绘制显示
    plt.plot(x['age'], y, 'b.')
    # 预测的y值绘制
    plt.plot(X_poly[:, 0], y_predict, 'r.')
    plt.show()

    预测值与真实值的图像显示:
    在这里插入图片描述

    查看原文

    赞 0 收藏 0 评论 0

    lvah 发布了文章 · 2019-04-17

    机器学习(四)-多变量线性回归

    1 多变量线性回归应用场景

    目前为止,我们探讨了单变量/特征的回归模型,现在我们对房价模型增加更多的特征,例如房间数楼层等,构成一个含有多个变量的模型.。

    1.1 单变量线性回归案例

    • 模型: hθ(x) = θ0 + θ1x

    在这里插入图片描述

    1.2 多变量线性回归案例

    在这里插入图片描述

    • 模型:

    在这里插入图片描述

    • 新的概念

    在这里插入图片描述
    例如:

             x(1) = [40, 1, 1, 10]
            x(2) = [96, 2, 1, 5]    
            x(3) = [135, 3, 2, 20]
    

    在这里插入图片描述例如:

    x(1)1 = 40
    x(1)2 = 1
    .......
    
    

    2 多元梯度下降法

    • 模型:

    在这里插入图片描述

    • 参数:

    在这里插入图片描述

    • 损失函数:

    在这里插入图片描述

    • 梯度下降公式(重复执行):

    在这里插入图片描述

    2.1 一元梯度下降n=1, 重复执行,直到收敛

    在这里插入图片描述
    在这里插入图片描述

    2.2 多元梯度下降n>1

    在这里插入图片描述

    2.3 多元批梯度下降代码

    import numpy as np
    
    # 1). 模拟数据
    X1 = 2 * np.random.randn(100, 1)
    X2 = 4 * np.random.rand(100, 1)
    X3 = 6 * np.random.rand(100, 1)
    y = 4 + 3 * X1 + 4 * X2 + 5 * X3 + np.random.randn(100, 1)
    
    #  2). 实现梯度下降算法
    #  np.c_是将数据组合成向量格式: (n, 1) (n,1) = (n, 2)
    X_b = np.c_[np.ones((100, 1)), X1, X2, X3]
    # 初始化theta的值, 需要计算四个theta的值;
    theta = np.random.randn(4, 1)
    # 设置学习率和收敛次数
    learning_rate = 0.1
    n_iterations = 1000
    
    # 根据公式计算
    for iteration in range(n_iterations):
        # 梯度下降公式 = 1/样本数 * (预测值 - 真实值) *Xi
        gradients = 1 / 100 * X_b.T.dot(X_b.dot(theta) - y)
        # theta = theta - 学习率 * 梯度值
        theta = theta - learning_rate * gradients
    
    print(theta)
    • 代码执行结果:

    在这里插入图片描述

    3 梯度下降法实践一:特征缩放

    3.1 梯度下降法遇到的问题

    在我们面对多维特征问题的时候,我们要保证这些特征都具有相近的尺度,这将帮助梯度下降算法更快地收敛。而特征缩放是为了确保特征在一个数量级上。

    以房价问题为例,假设我们使用两个特征,房屋的尺寸和房间的数量,其中x1 = 房屋面积(0-400 m2), x2 = 卧室数量(1-5), 以两个参数分别为横纵坐标,绘制代价函数的等高线图能,看出图像会显得很扁,梯度下降算法需要非常多次的迭代才能收敛。

    在这里插入图片描述

    3.2 解决方法

    • 解决方法一:

      • 尝试将所有特征的尺度都尽量缩放到-1到1之间。比如:

    x1 = 房屋面积 / 400
    x2 = 卧室数量 / 5

    在这里插入图片描述

    • 解决方法二: 平方均值法
      在原来的基础上把特征 xi 替换成 xi – μ;
      在这里插入图片描述

    也可以把最大值换成标准差,或者最大值 – 最小值。

    4 梯度下降法实践二: 学习率

    4.1 梯度下降法遇到的问题

    梯度下降算法收敛所需要的迭代次数根据模型的不同而不同,我们不能提前预知,我们可以绘制迭代次数和代价函数的图表来观测算法在何时趋于收敛。
    在这里插入图片描述
    梯度下降算法的每次迭代受到学习率的影响,

    • 如果学习率过小,则达到收敛所需的迭代次数会非常高;
    • 如果学习率过大,每次迭代可能不会减小代价函数,可能会越过局部最小值导致无法收敛。

    4.2 解决方法

    • 自动测试是否收敛的方法,例如将代价函数的变化值与某个阀值(例如0.001)进行比较,但通常看上面这样的图表更好。

    尝试在如下的数值中选择α : …, 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1,…

    5 梯度下降算法补充

    5.1 三种梯度下降总结

    如何选择?

    • 训练集比较小: 使用批梯度下降(小于2000个)
    • 训练集比较大:使用Mini-bitch梯度下降 一般的Mini-batch size 是64,128,256, 512,1024, Mini-batch size要适用CPU/GPU的内存

    在这里插入图片描述

    5.2 随机梯度下降

    随机梯度下降思想:把m个样本分成m份,每次用1份做梯度下降;也就是说,当有m个样本时,批梯度下降只能做一次梯度下降,但是随机梯度下降可以做m次。

    • 实现代码
    import numpy as np
    import random
    X = 2 * np.random.rand(100, 1)
    Y = 4 + 3 * X + np.random.randn(100, 1)
    X_b = np.c_[np.ones((100, 1)), X]
    # 每轮epochs处理m个样本;
    n_epochs = 1000
    # 学习率
    a0 = 0.1
    # 定义衰减率
    decay_rate = 1
    
    def learning_schedule(epoch_num):
        """
        定义一个学习率衰减的函数
        """
        return (1.0 / (decay_rate * epoch_num + 1)) * a0
    
    
    # 初始化theta值
    theta = np.random.randn(2, 1)
    
    # 初始化随机值
    num = [i for i in range(100)]
    m = 100
    
    for epoch in range(n_epochs):
        rand = random.sample(num, 100)
        for i in range(m):
            random_index = rand[i]
            xi = X_b[random_index:random_index + 1]
            yi = Y[random_index:random_index + 1]
            # 随机梯度下降值
            gradients = xi.T.dot(xi.dot(theta) - yi)
            # 学习率
            learning_rate = learning_schedule(epoch+1)
            theta = theta - learning_rate * gradients
    
    print(theta)
    • 执行结果展示:

    在这里插入图片描述

    5.3 Mini-batch梯度算法

    随机梯度下降会丧失向量带来的加速,所以我们不会太用随机梯度下降。

    • 实现代码
    import numpy as np
    import random
    
    X = 2 * np.random.rand(100, 1)
    y = 4 + 3 * X + np.random.randn(100, 1)
    X_b = np.c_[np.ones((100, 1)), X]
    # print(X_b)
    
    n_epochs = 500
    a = 0.03
    m = 100
    num = [i for i in range(100)]
    
    
    
    theta = np.random.randn(2, 1)
    batch_num = 5
    batch_size = m // 5
    
    # epoch 是轮次的意思,意思是用m个样本做一轮迭代
    for epoch in range(n_epochs):
        # 生成100个不重复的随机数
        for i in range(batch_num):
            start = i*batch_size
            end = (i+1)*batch_size
            xi = X_b[start:end]
            yi = y[start:end]
            gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi)
            print(a)
            learning_rate = a
            theta = theta - learning_rate * gradients
    
    print(theta)
    • 执行结果展示:

    在这里插入图片描述

    5.4 Mini-batch梯度算法优化: 学习率衰减

    在做Mini-batch的时候,因为噪声的原因,可能训练结果不是收敛的,而是在最低点周围晃动,如果我们要解决这个问题,那我们就需要减少学习率,让他在尽量小的范围内晃动
    1 epoch = 1 次遍历所有的数据

    • 学习率衰减公式:

    在这里插入图片描述

    • 实现代码
    import numpy as np
    import random
    
    X = 2 * np.random.rand(100, 1)
    y = 4 + 3 * X + np.random.randn(100, 1)
    X_b = np.c_[np.ones((100, 1)), X]
    # print(X_b)
    
    n_epochs = 500
    t0, t1 = 5, 50
    
    m = 100
    num = [i for i in range(100)]
    
    def learning_schedule(t):
        return float(t0) / (t + t1)
    
    theta = np.random.randn(2, 1)
    
    batch_num = 5
    batch_size = m // 5
    
    # epoch 是轮次的意思,意思是用m个样本做一轮迭代
    for epoch in range(n_epochs):
        # 生成100个不重复的随机数
        for i in range(batch_num):
            start = i*batch_size
            end = (i+1)*batch_size
            xi = X_b[start:end]
            yi = y[start:end]
            gradients = 1/batch_size * xi.T.dot(xi.dot(theta)-yi)
            learning_rate = learning_schedule(epoch*m + i)
            theta = theta - learning_rate * gradients
    
    print(theta)
    • 执行结果展示:

    在这里插入图片描述

    6 特征和多项式回归

    6.1 过拟合的问题

    过拟合的问题出现在变量(θ)过多的时候,这时候我们没有更多的数据去拟合模型,虽然损失函数的值基本接近于0。

    在这里插入图片描述

    6.2 过拟合的解决方法:

    • 减少特征的数量(一般不用)
      1)手动选择特征数
      2)模型选择
    • 正则化(特征缩放)
      保留所有特征,但是减少量级或者参数θ_j的大小

    6.2 特征缩放

    房价预测时, 假设我们不知道房屋面积,但是知道房屋的长宽。

    在这里插入图片描述

    • 模型设计:
      hθ(x) = θ0 + θ1 x 房屋的长度 + θ2 x 房屋的宽度
    • 特征未缩放图形展示

    在这里插入图片描述

    • 特征缩放图形展示

    在这里插入图片描述
    注:如果我们采用多项式回归模型,在运行梯度下降算法前,特征缩放非常有必要。

    6.3 正则化

    • 如何不想要theta3和theta4?

    在这里插入图片描述
    首先, 我们可以在损失函数中,加入关于theta3和theta4的项, 迫使若损失函数想要最小化, 必须让theta3和theta4尽可能的小。
    在这里插入图片描述

    然后正则化, 公式如下图:

    在这里插入图片描述

    6.4 L1 正则和 L2 正则的区别

    • L1 会趋向于减少特征值
    • L2 会趋向于保留特征值

    在这里插入图片描述

    7 正则化算法与代码实现

    7.1 Ridge(岭)回归

    7.1.1 算法理解

    在这里插入图片描述

    7.1.2 实现公式

    在这里插入图片描述

    7.1.3 代码实现

    • 两种实现岭回归的方法:
    
    """
    岭回归
    方法一: 岭回归运用了L2正则化
    """
    import numpy as np
    from sklearn.linear_model import Ridge
    from sklearn.linear_model import SGDRegressor
    
    
    X = 2 * np.random.rand(100, 1)
    y = 4 + 3 * X + np.random.randn(100, 1)
    
    # alpha是惩罚项里的alpha, solver处理数据的方法,auto是根据数据自动选择,svd是解析解,sag就是随机梯度下降
    ridge_reg = Ridge(alpha=1, solver='auto')
    # 学习过程
    ridge_reg.fit(X, y)
    # 预测
    print(ridge_reg.predict([[1.5], [2], [2.5]]))
    # 打印截距
    print(ridge_reg.intercept_)
    # 打印系数
    print(ridge_reg.coef_)
    
    """
    方法二: 岭回归和sgd & penalty=2是等价的
    """
    sgd_reg = SGDRegressor(penalty='l2')
    sgd_reg.fit(X, y.ravel())
    print(sgd_reg.predict([[1.5], [2], [2.5]]))
    # 打印截距
    print("W0=", sgd_reg.intercept_)
    # 打印系数
    print("W1=", sgd_reg.coef_)
    
    

    7.2 Lasso(拉索)回归

    7.2.1 算法理解

    在这里插入图片描述

    7.2.2 实现公式

    在这里插入图片描述

    7.2.3 代码实现

    
    """
    Lasso 回归
    
    Lasso用的是l1的正则化
    """
    import numpy as np
    from sklearn.linear_model import Lasso
    from sklearn.linear_model import SGDRegressor
    
    X = 2 * np.random.rand(100, 1)
    y = 4 + 3 * X + np.random.randn(100, 1)
    
    lasso_reg = Lasso(alpha=0.15)
    lasso_reg.fit(X, y)
    print(lasso_reg.predict([[1.5]]))
    print(lasso_reg.coef_)
    
    sgd_reg = SGDRegressor(penalty='l1', n_iter=1000)
    sgd_reg.fit(X, y.ravel())
    print(sgd_reg.predict([[1.5]]))
    print(sgd_reg.coef_)
    

    7.3 Elastic Net回归

    7.3.1 算法理解

    在这里插入图片描述

    7.3.2 实现公式

    在这里插入图片描述

    7.3.3 代码实现

    
    import numpy as np
    from sklearn.linear_model import ElasticNet
    
    X = 2 * np.random.rand(100, 1)
    Y = 4 + 3 * X + np.random.randn(100, 1)
    
    elastic_reg = ElasticNet(alpha=0.15, l1_ratio=0.5)
    
    elastic_reg.fit(X, Y)
    print(elastic_reg.predict([[1.5]]))
    print(elastic_reg.coef_)
    print(elastic_reg.intercept_)
    
    
    from sklearn.linear_model import SGDRegressor
    elastic_reg = SGDRegressor(penalty='elasticnet')
    elastic_reg.fit(X, Y)
    print(elastic_reg.predict([[1.5]]))
    print(elastic_reg.coef_)
    

    8 正规方程和梯度下降比较

    梯度下降:

    • 需要选择合适的α
    • 需要多次迭代
    • 当n很大时,效果很好

    正规方程:

    • 不需要选择学习率a
    • 不需要迭代
    • 需要计算X的转置乘X整体的逆
    • 当n很大时,计算很慢

    总结:根据经验,当特征数量到10000的时候,是会换成梯度下降比较好

    8.1 多项式回归的梯度下降代码

    
    
    
    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    
    # 1). 数据准备;
    # 样本数
    m = 100
    X = 6 * np.random.randn(m, 1) - 3
    Y = 0.5 * X ** 2 + X + 2 + np.random.randn(m, 1)
    
    # 2). 处理
    # 2-1). 将一个高阶方程转化为一个一阶方程;(多元线性回归)
    # degree:用几维处理数据;
    poly_features = PolynomialFeatures(degree=2, include_bias=False)
    # fit_transform === fit() + transform(), 其中transform就是用来做归一化的;
    X_poly = poly_features.fit_transform(X, Y)
    
    # 2-2). 处理一阶方程
    line_reg = LinearRegression()
    line_reg.fit(X_poly, Y)
    
    print(line_reg.coef_)
    print(line_reg.intercept_)
    

    8.2 不同维度绘制的图形

    import numpy as np
    import matplotlib.pyplot as plt
    from sklearn.preprocessing import PolynomialFeatures
    from sklearn.linear_model import LinearRegression
    
    # 1). 数据准备;
    # 样本数
    m = 100
    X = 6 * np.random.randn(m, 1) - 3
    Y = 7 * X ** 2 + 5 *X + 2 + np.random.randn(m, 1)
    
    # plt.plot(X, Y, 'b.')
    # plt.show()
    
    
    # 设置图像维度及线条的字体显示
    d = {1: 'g-', 2: 'r.', 10: 'y*'}
    # d = {2: 'g-'}
    
    
    for i in d:
        # 2). 处理
        # 2-1). 将一个高阶方程转化为一个一阶方程;(多元线性回归)
        # degree:用几维处理数据;
        poly_features = PolynomialFeatures(degree=i, include_bias=False)
        # fit_transform === fit() + transform(), 其中transform就是用来做归一化的;
        X_poly = poly_features.fit_transform(X)
        print(X_poly)
    
        # 2-2). 处理一阶方程
        line_reg = LinearRegression()
        line_reg.fit(X_poly, Y)
    
        print(line_reg.coef_)
        print(line_reg.intercept_)
    
        y_predict = line_reg.predict(X_poly)
        plt.plot(X_poly[:, 0], y_predict, d[i])
    
    
    plt.show()
    
    
    查看原文

    赞 1 收藏 1 评论 0

    lvah 发布了文章 · 2019-04-17

    机器学习(三)-单变量线性回归算法

    @toc

    1 预测数值型数据:回归

    1.1 什么是回归?

    • 大自然让我们回归到一定的区间范围之内;反过来说就是,有一个平均的水平,可以让突出的事物能向他靠拢。
    • 回归是由达尔文(Charles Darwin)的表兄弟Francis Galton发明的。 Galton于1877年完成了第一次回归预测,目的是根据上一代豌豆种子(双亲)的尺寸来预测下一代豌豆种子(孩子)的尺寸。Galton在大量对象上应用了回归分析,甚至包括人的身高。他注意到,如果双亲的高度比平均高度高,他们的子女也倾向于比平均高度高,但尚不及双亲。孩子的高度向着平均高度回退(回归)。Galton在多项研究上都注意到这个现象,所以尽管这个英文单词跟数值预测没有任何关系,但这种研究方法仍被称作回归 2 。
    • 那些高个子的后代的身高,有种回归到大众身高的趋势。 eg: 姚明身高2米26,叶莉身高1米90, 但是他们后代的身高是会逐渐回归到正常的身高水平。

    在这里插入图片描述

    1.2 回归的目的是预测数值型的目标值。

    1.3 回归可以做什么事?

    回归可以做任何事情。然而大多数公司常常使用回归法做一些比较沉闷的事情,例如:

    • 销售量预测
    • 制造缺陷预测。

    当然也可以做有新意的应用,例如:

    • 预测名人的离婚率。
    • 预测所在地区的房价。

    2 线性回归模型表示

    2.1 线性回归的基本概念

    • 回归,一般都是指线性回归(linear regression).

    从我们最熟悉的开始, 已知两点,求直线公式设 y = ax+b, 带入两点,求得解析解为 y = 3x-60

    在这里插入图片描述

    • 回归方程 (regression equation): y = 3x-60
    • 回归系数 (regression weights): 3和-60可以称为回归系数
    • 回归: 求这些回归系数的过程

    2.2 西安高新区房价预测

    这个例子是预测住房价格的,我们要使用一个数据集,数据集包含西安市的住房价格。在这里,我要根据不同房屋尺寸所售出的价格,画出我的数据集。比方说,如果你朋友的房子是40平方米大小,你要告诉他们这房子能卖多少钱。那么,你可以做的一件事就是构建一个模型,也许是条直线,从这个数据模型上来看,也许你可以告诉你的朋友,他能以大约78万(人民币)左右的价格卖掉这个房子。这就是监督学习算法的一个例子。
    在这里插入图片描述

        m:表示训练集数据的总量
        x:表示输入变量
        y:表示输出变量
        (x,y): 表示一个训练样本
        (x(i),y(i)): 表示第i个训练样本

    在这里插入图片描述

    3 回归的一般方法

    3.1 线性回归的一般步骤

    在这里插入图片描述
    对于一元线性回归(单变量线性回归)来说,学习算法为 y = ax + b
    我们换一种写法: hθ(x) = θ0 + θ1x1

    3.2 利用Sklearn做线性回归的预测

    • 实现步骤
      1). 模拟数据
      2). 调用sklearn拟合数据, 把theta0 theta1求出来
      3). 预测
    
    from sklearn.linear_model import LinearRegression
    import numpy as np
    
    # 1).模拟数据
    X = np.random.rand(100, 1)
    Y = 4 + 2 * X + np.random.randn(100, 1)
    
    # 2). 调用sklearn拟合数据, 把theta0 theta1求出来
    # 导入线性回归类
    lin_reg = LinearRegression()
    # 让线性回归类做训练
    lin_reg.fit(X, Y)
    # 输出theta0 theta1; intercept_是截距, coef_是斜率系数;
    print("\ntheat0, theta1:", lin_reg.intercept_, lin_reg.coef_)
    
    # 3). 预测
    X_new = np.array([[0], [1]])
    print("\nx=0, x=1预测结果:\n", lin_reg.predict(X_new))
    • 测试结果:

    在这里插入图片描述

    3 损失/代价函数

    3.1 拟合

    • 线性回归实际上要做的事情就是: 选择合适的参数(θ0, θ1),使得hθ(x)方程,很好的拟合训练集。实现如何把最有可能的直线与我们的数据相拟合。
    • 拟合就是把平面上一系列的点,用一条光滑的曲线连接起来。因为这条曲线有无数种可能,从而有各种拟合方法。拟合的曲线一般可以用函数表示.

    下面的三张图, 展示了拟合的三种状态:

    • 图一是部分拟合
    • 图二是完全不拟合
    • 图三是完全拟合

    在这里插入图片描述

    3.2 损失函数: 均方误差MSE

    • 拟合过程中因为theta0和theta1的取值准确度, 预测的结果与训练集中的实际值有差距。
    我们选择的参数决定了我们得到的直线相对于我们的训练集的准确程度,模型所预测的值与训练集中实际值之间的差距(下图中蓝线所指)就是建模误差(modeling error)。

    在这里插入图片描述

    • 我们的目标便是选择出可以使得建模误差的平方和能够最小的模型参数。 即使得损函数最小。

    在这里插入图片描述

    3.3 均方误差MSE最小化

    • 二维空间求均方差

    在这里插入图片描述
    上图是参考吴恩达视频的图片, 我们会发现随着theta1的不断变化, 均方误差MSE会找到一个最小值。 如果从数学角度来看, 就是求解函数的导数,计算函数的最小值。

    • 三维空间求均方差

    在这里插入图片描述

    上图是参考吴恩达视频的图片, 我们会发现随着theta0和theta1的不断变化, 均方误差MSE会找到一个最小值。为了通过图形化看到最小的均方差, 三维图片并不直观。 通常使用等高线实现。如下图:
    在这里插入图片描述

    • 更高维空间

    我们会遇到更复杂、更高维度、更多参数的情况,而这些情况是很难画出图的,因此更无法将其可视化,因此我们真正需要的是编写程序来找出这些最小化代价函数的和的值,而梯度下降算法就是能够自动地找出能使代价函数最小化的参数和的值。

    4 梯度下降

    4.1 梯度下降的思想

    梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出代价函数的最小值。
    在这里插入图片描述

    梯度下降背后的思想是:开始时我们随机选择一个参数的组合,计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到到到一个局部最小值(local minimum),因为我们并没有尝试完所有的参数组合,所以不能确定我们得到的局部最小值是否便是全局最小值(global minimum),选择不同的初始参数组合,可能会找到不同的局部最小值。

    在这里插入图片描述

    4.2 梯度下降的分类

    想象一下你正站立在山的这一点上,站立在你想象的公园这座红色山上,在梯度下降算法中,我们要做的就是旋转360度,看看我们的周围,并问自己要在某个方向上,用小碎步尽快下山。这些小碎步需要朝什么方向?如果我们站在山坡上的这一点,你看一下周围,你会发现最佳的下山方向,你再看看周围,然后再一次想想,我应该从什么方向迈着小碎步下山?然后你按照自己的判断又迈出一步,重复上面的步骤,从这个新的点,你环顾四周,并决定从什么方向将会最快下山,然后又迈进了一小步,并依此类推,直到你接近局部最低点的位置。

    • 公式:

    在这里插入图片描述

    • 理解

      • a是学习率(learning rate),它决定了我们沿着能让代价函数下降程度最大的方向向下迈出的步子有多大;
      • 如果α太小的话,梯度下降会很慢
      • 如果α太大的话,梯度下降越过最小值,不仅不会收敛,而且有可能发散
      • 不论斜率正或负,梯度下降都会逐渐趋向最小值
      • 即使学习率α是固定不变的,梯度下降也会收敛到一个最低点
    • 梯度下降的两种更新方式:

    在这里插入图片描述

    4.2.1 “Batch” Gradient Descent 批梯度下降

    批梯度下降:指的是每下降一步,使用所有的训练集来计算梯度值

    • 在梯度下降中,在计算微分求导项时,我们需要进行求和运算,所以,在每一个单独的梯度下降中,我们最终都要计算这样一个东西,这个项需要对所有个训练样本求和。因此,批量梯度下降法这个名字说明了我们需要考虑所有这一"批"训练样本,
    • 代码实现
    """
    线性回归实现梯度下降的批处理(batch_gradient_descent )
    """
    import numpy as np
    
    X = 2 * np.random.rand(100, 1)
    y = 4 + 3 * X + np.random.randn(100, 1)
    X_b = np.c_[np.ones((100, 1)), X]
    # print(X_b)
    
    learning_rate = 0.1
    # 通常在做机器学习的时候,一般不会等到他收敛,因为太浪费时间,所以会设置一个收敛次数
    n_iterations = 100000
    m = 100
    
    # 1.初始化theta, w0...wn
    theta = np.random.randn(2, 1)
    count = 0
    
    # 4. 不会设置阈值,之间设置超参数,迭代次数,迭代次数到了,我们就认为收敛了
    for iteration in range(n_iterations):
        count += 1
        # 2. 接着求梯度gradient
        gradients = 1/m * X_b.T.dot(X_b.dot(theta)-y)
        # 3. 应用公式调整theta值, theta_t + 1 = theta_t - grad * learning_rate
        theta = theta - learning_rate * gradients
    
    print(count)
    print(theta)
    
    • 执行结果

    在这里插入图片描述

    4.2.2 “Stochastic” Gradient Descent 随机梯度下降

    随机梯度下降:指的是每下降一步,使用一条训练集来计算梯度值

    4.2.3 “Mini-Batch” Gradient Descent “Mini-Batch”梯度下降

    “Mini-Batch”梯度下降:指的是每下降一步,使用一部分的训练集来计算梯度值

    查看原文

    赞 1 收藏 1 评论 0

    lvah 发布了文章 · 2019-04-17

    机器学习(二)-基本概念

    1 数据集

    在机器学习和模式识别等领域中,一般需要将样本分成独立的三部分训练集(train set),验证集(validation set ) 和测试集(test set)。其中训练集用来估计模型,验证集用来调超参数,测试集用来测试模型准确度。

    1.1 训练集

    • 训练集用来估计模型;
    • 训练集占总样本的50%

    1.2 开发集(验证集)

    • 验证集用来确定网络结构或者控制模型复杂程度的参数
    • 验证集占总样本的25%

    1.3 测试集

    • 测试集则检验最终选择最优的模型的性能如何
    • 测试集占总样本的25%

    1.4 简单的机器学习流程

    在这里插入图片描述

    在这里插入图片描述

    在这里插入图片描述

    2 常用的机器学习算法介绍

    在这里插入图片描述

    • 分类算法:有监督, 举例:猫狗分类
    • 回归算法:有监督, 举例:房价预测
    • 聚类算法:无监督, 举例:新闻分类
    • 降维算法: 数据处理
    • 模型选择算法: 算法的选择和参数调试所用到的技术
    • 预处理算法: 特征提取和归一化

    3 有监督机器学习和无监督机器学习

    3.1 有监督机器学习

    • 我们要教会计算机做某些事情
    • 定义:我们给算法一个数据集,其中包含了正确答案,算法的目的就是给出更多的正确答案
    • 有监督机器学习例子:分类

    在这里插入图片描述

    3.2 无监督机器学习

    • 让计算机自己去做某些事情
    • 定义: 我们给算法一个数据集,但是不给他正确答案,而让计算机自己去学习
    • 无监督机器学习例子:聚类(预测鸢尾花卉)

    Iris(鸢尾花)数据集是多重变量分析的数据集。每行数据包含4个属性:Sepal Length(花萼长度)、Sepal Width(花萼宽度)、Petal Length(花瓣长度)和Petal Width(花瓣宽度)。可通过这4个属性预测鸢尾花卉属于种类(Setosa,Versicolour,Virginica)中的哪一类。具体分为几类, 分析前是不知道的。

    在这里插入图片描述

    4 机器学习与人类学习

    • 有了机器学习,我们还需要人为经验的干预吗?

    在这里插入图片描述

    查看原文

    赞 2 收藏 2 评论 0

    lvah 发布了文章 · 2019-04-17

    机器学习(一)-导论

    1 机器学习和人工智能的区别

    机器学习是现阶段人工智能的核心技术,是通过统计学原理,来对数据进行分析与建模.它们之间的关系图如下所示:

    在这里插入图片描述

    • 机器学习是核心技术,可以通过代码来实现;
    • 人工智能是一种思维方法;

    在这里插入图片描述

    1.1 什么是人工智能?

    1.1.1 通用人工智能AGI

    在这里插入图片描述
    通过人工智能的信息, 我们可以在很多的电影里面看到。

    • 《骇客帝国》
    • 《超严骇客》
    • 《西部世界》

    在这里插入图片描述

    1.1.2 人工智能AI

    在这里插入图片描述

    1.2 人工智能技术

    Google对人工智能技术的定义:

    • 只要能让计算机模拟人类行为的技术,都叫人工智能技术

    在这里插入图片描述

    2 机器学习的应用和缺点

    2.1 人工智能的分类领域

    在这里插入图片描述

    • 模式识别

    在这里插入图片描述

    • 语音识别

    在这里插入图片描述

    • 图像识别

    在这里插入图片描述

    • 自然语言处理

    在这里插入图片描述

    2.2 机器学习目前的缺点

    现在的安卓手机都有语音助手, 比如: 苹果手机的Siri等, 它们在语音识别时,可以获取语音信息并分割词语, 但是不能进行逻辑的处理与判断.

    • 比如, 语音描述不要日本菜, 但是会给你推荐日本菜;
    • 比如: 四川火锅和日料

      • A. “四川火锅比日料更好,因为它很辣”
      • B. “四川火锅比日料更好,因为它不辣”

    问题: “它“分别指的是谁?

    3 数学和机器学习的关系

    3.1 中心极限定理

    在自然界与生产中,一些现象受到许多相互独立的随机因素的影响,如果每个因素所产生的影响都很微小时,总的影响可以看作是服从正态分布的

    在这里插入图片描述

    3.2 导数

    在维度间描述趋势的语法, 比如: 从三维降到二维, 从二维降到一维。

    在这里插入图片描述

    4 机器学习的应用场景

    4.1 利用大数据预测H1N1在美国某小镇的爆发

    在这里插入图片描述

    4.2 预测世界杯比赛结果和点球方向

    在这里插入图片描述

    4.3 Alpha-Go

    在这里插入图片描述

    查看原文

    赞 1 收藏 1 评论 0

    lvah 发布了文章 · 2018-09-22

    02_01_创建最简单的web程序

    初始化

    所有的Flask程序都必须创建一个程序实例, 这个程序实例就是Flask类的对象。客户端把请求发送给Web服务器, 服务器再把请求发送给Flask程序实例, 然后由程序实例处理请求。

    • 创建程序实例:
    from flask import Flask
    
    app = Flask(__name__)
            
    注意: 此处的__name__是一个全局变量, 它的值是代码所处的模块或包的名字, Flask用这个参数决定程序的根目录, 以便稍后能找到相对于程序根目录的资源文件位置。

    路由和视图函数

        还是上面那句话——客户端把请求发送给Web服务器, 服务器再把请求发送给Flask程序实例, 然后由程序实例处理请求。

        那么程序实例如何处理请求, 答案是程序实例通过路由来处理请求——路由就是URL和处理请求的函数的映射——处理请求的函数就叫做视图函数。

        Flask定义路由最简便的方式, 是使用程序实例提供的app.route修饰器:

    @app.route('/'):
    def index():
        return '<h1>Hello world!<h1>'

           
           
    前例把index()函数注册为程序根地址的处理程序。 ( 如果部署程序的服务器域名为www.example.com, 在浏览器中访问http://www.example.com后, 会触发服务器执行index()函数。 )

             这个函数的返回值称为响应, 是客户端接收到的内容。

        地址中包含可变部分的路由:

            @app.route('/user/<name>')

             def user(name):

                 return '<h1>Hello, %s!</h1>' %name

            尖括号中的内容就是动态部分,任何能匹配静态部分的URL都会映射到这个视图函数, 调用视图函数时, Flask会将动态部分作为参数传入函数。

            注意:路由中的动态部分默认类型是字符串, 不过也可以使用别的类型如:/user/<int: id>只会匹配动态片段id为整数的url。除了整型, Flask还支持float, path类型, 其中path类型也是字符串, 不过其中的/不会被当做分隔符, 而是动态片段的一部分。

    3.启动服务器

        程序实例用run方法启动Flask集成的开发Web服务器:

            if name == '__main__': (只有直接运行该模块时条件才为真, 该模块被导入条件为假)

                app.run(debug=True)  #debug参数为True, 表示启用调试模式。

        服务器启动后会进入轮询, 等待并处理请求, 直到程序停止, 比如按Ctrl+C

    4.一个完整的程序

    from flask import Flask

    app = Flask(__name__)

    静态路由

    @app.route('/')

    def index():

        return '<h1>hello, world!<h1>'

    动态路由

    @app.route('/user/<name>')

    def index(name):

        return '<h1>hello, {}<h1>'.format(name)

    if name == '__main__':

        #服务器轮询

        app.run(debug=True)

    ————————————————————————实践—————————————————————————

    5.实践操作

    一.准备

    按上节所说, 

        &cd flasky     进入flasky文件夹

        &source venv/bin/activate    激活虚拟环境

    迁出新版本,

        &git checkout 2a      此命令迁出的是只含有静态路由的程序, 效果图如下:

            

             注意此时迁出的版本hello.py只有一个静态路由。 而且没有启动服务器的代码, 我们要手动修改加上, 然后:

    查看原文

    赞 0 收藏 0 评论 0

    lvah 发布了文章 · 2018-09-03

    python3与Excel的完美结合

    Excel 是 Windows 环境下流行的、强大的电子表格应用。openpyxl 模块让 Python 程序能读取和修改 Excel 电子表格文件。例如,可能有一个无聊的任务,需要从一个电子表格拷贝一些数据,粘贴到另一个电子表格中。或者可能需要从几千行中挑选几行,根据某种条件稍作修改。或者需要查看几百份部门预算电子表格,寻找其中的赤字。正是这种无聊无
    脑的电子表格任务,可以通过 Python 来完成。LibreOffice Calc, WPS 和 OpenOffice Calc 都能处理 Excel 的电子表格文件格式,这意味着 openpyxl 模块也能处理来自这些应用程序的电子表格。你可以从 https://www.libreoffice.org/和 http://www.openoffice.org/下载这些软件。即使你的计算机上已经安装了 Excel,可能也会发现这些程序更容易使用。

    1. Excel文档基本定义

    • 工作簿(workbook): 一个 Excel 电子表格文档;
    • 工作表(sheet): 每个工作簿可以包含多个表, 如: sheet1, sheet2等;
    • 活动表(active sheet): 用户当前查看的表;
    • 列(column): 列地址是从 A 开始的;
    • 行(row): 行地址是从 1 开始的;
    • 单元格(cell): 特定行和列的方格;

    2. 安装 openpyxl 模块

    Python 没有自带 openpyxl,所以必须安装。

    pip3 install openpyxl
    

    3. 读取 Excel 文档

    将使用一个电子表格 example.xlsx,你可以自己创建这个电子文档,内容如下:

    example.xlxs文件内容

    • 在导入 openpyxl 模块后,就可以使用 openpyxl.load_workbook()函数。打开 Excel 文档
    # 导入工作薄
    1. wb = openpyxl.load_workbook('excelDemo/example.xlsx')    # 加载工作薄
    2. wb.sheetnames                                       # 获取当前所有工作表的名称, 返回一个列表 
    3. wb.active                                           # 获取当前活跃的工作表 
    • 从工作簿中取得工作表
    4. sheet = wb['Sheet1']                # 工作表
    5. sheet.title                         # 获取当前活动表的名称
    6. sheet.cell(row=1, column=2)         #  获取单元格指定行和指定列的内容
    
    • 表中取得单元格

    Cell 对象有一个 value 属性,不出意外,它包含这个单元格中保存的值。Cell 对象也有 row、column 和 coordinate 属性,提供该单元格的位置信息。

    row属性给出的是整数 1,column 属性给出的是'B',coordinate 属性给出的是'B1'。

    6. cell = sheet['A1']
    7. cell_value = sheet['A1'].value
    8. cell.row, cell.column cell.coordinate

    4. 工作簿、工作表、单元格

    下面是从电子表格文件中读取单元格涉及的所有函数、方法和数据类型。一个完整的操作过程如下:

    • 导入 openpyxl 模块。
    • 调用 openpyxl.load_workbook()函数。
    • 取得 Workbook 对象。
    • 调用 wb.sheetnames和 wb.active 获取工作簿详细信息。
    • 取得 Worksheet 对象。
    • 使用索引或工作表的 cell()方法,带上 row 和 column 关键字参数。
    • 取得 Cell 对象。
    • 读取 Cell 对象的 value 属性

    一个完整的案例代码如下:

    import openpyxl
    
    
    # 1. 读取excel文档
    wb = openpyxl.load_workbook('excelDemo/example.xlsx')
    
    # # 返回一个workbook对象, 有点类似于文件对象;
    # print(wb, type(wb))
    
    
    
    # 2. 在工作薄中取得工作表
    # print(wb.get_sheet_names())
    # 返回一个列表, 存储excel表中所有的sheet工作表;
    print(wb.sheetnames)
    
    # 返回一个worksheet对象, 返回当前的活动表;
    # print(wb.get_active_sheet())
    # print(wb.active)
    
    
    
    # 3. 获取工作表中, 单元格的信息
    # wb.get_sheet_by_name('Sheet1')
    sheet = wb['example']
    print(sheet['A1'])
    print(sheet['B1'].value)
    
    cell = sheet['B1']
    print(cell.row, cell.column)
    
    
    print(sheet.cell(row=3, column=2))
    print(sheet.cell(row=3, column=2).value)
    print(sheet.cell(row=3, column=2, value='www'))
    
    
    # sheet的属性
    
    print(sheet.max_column)
    print(sheet.max_row)
    print(sheet.title)
    sheet.title = 'example'
    print(sheet.title)
    
    
    for row in sheet.rows:
        for cell in row:
            print(cell.value, end='\t')
        print('\n')
    
    wb.save(filename="excelDemo/example.xlsx")
    
    
    
    查看原文

    赞 7 收藏 3 评论 0

    认证与成就

    • 获得 14 次点赞
    • 获得 0 枚徽章 获得 0 枚金徽章, 获得 0 枚银徽章, 获得 0 枚铜徽章

    擅长技能
    编辑

    开源项目 & 著作
    编辑

    (゚∀゚ )
    暂时没有

    注册于 2017-11-26
    个人主页被 417 人浏览