【学习笔记】cs229机器学习笔记(二)



  • 机器学习 Day 2


    10/23 学习内容:
    1) python的基本语法
    2 ) 继续学习cs229机器学习


    多元线性回归

    • 多特征量下线性回归的假设形式可看作两个向量的乘积

      0_1540308694118_7381ccef-3bf1-46dc-8804-0ffc93afc207-image.png

    • 同样的,代价函数也可以看做关于θ的带有一个n+1维向量的函数

      0_1540308710565_56e7ad12-2de2-4d5d-9ee1-f3333cab82f6-image.png

    • 多元情况与单元情况下的梯度下降算法中的θ参数的更新方法是相同的

      0_1540308719749_68c69060-4e89-4a40-8b36-e49f9bdcec13-image.png


    梯度下降运算中的实用技巧

    • 特征缩放(fearture scaling)

      IEDA:将各个特征值的范围约束到大约-1~+1的范围内或大致相近的范围内,以便于使得梯度下降更快,收敛循环次数更少。

      METHOD:
      1) 将特征值的范围除以最大值
      2) 均值归一化
      x1x_1=:(x1μ1)/(maxxminx)(x_1-μ_1)/(max_x-min_x)

      0_1540312032925_86ed105a-9b1d-425b-a439-28fca7b5acbb-image.png


    如何确定梯度下降算法是否收敛?

    • 未收敛时,J(θ)J(θ)在每一次迭代后应当下降

    • 自动收敛测试判定:收敛后,相邻的两次代价函数值差小于一个阈值(如:0.001)

    • J(θ)J(θ)的变化图也可判断代价函数是否收敛

      0_1540311964517_8f534c8d-7a34-41e9-a1e1-f9023d5ab4e3-image.png


    多项式回归

    • 用一个新的特征代替多个特征,以获得更好的模型与数据的拟合效果
      eg: S=a*b;

      0_1540311921917_62063739-8ed1-411a-a5dc-0b0af313ec90-image.png
      补充:
      添加高阶项的时候,也增加了模型的复杂度。随着模型复杂度的升高,模型的容量以及拟合数据的能力增加,可以进一步降低训练误差,但导致过拟合的风险也随之增加。

      0_1540312692310_4c2f5750-c739-409c-9aef-7336062cc4ba-image.png

    过拟合例子:
    0_1540312793450_46c40edc-ebe6-432d-ada4-531a8b8e63a2-image.png

    • 此时函数图像穿过了每一个样本点,所有的训练样本都落在了拟合的曲线上,训练误差接近与0。 可以说是近乎完美的模型了。但是,这样的曲线与我们最开始数据的来源(一个二次方程加上一些随机误差)差异非常大。如果从相同来源再取一些样本点,使用该模型预测会出现非常大的误差。

    • 类似这种训练误差非常小,但是新数据点的测试误差非常大的情况,就叫做模型的过拟合。 过拟合出现时,表示模型过于复杂,过多考虑了当前样本的特殊情况以及噪音(模型学习到了当前训练样本非全局的特性),使得模型的泛化能力下降
      (术语"泛化"指的是一个假设模型能够应用到新样本的能力。)

    • 解决方式:

      • 降低模型复杂度,例如减小上面例子中的degree;
      • 降维,减小特征的数量;
      • 增加训练样本;
      • 添加正则化项.
        0_1540313048624_b02116c8-3455-43f5-9324-879c9615c732-image.png

    标准方程法

    • 提供一种求解θ的解析解法,相比于梯度下降算法的多次迭代收敛,可以一次性求解θ的最优值。
    • 当J(θ) (n+1维向量的函数)的偏导数为零时,即能够求得使得代价函数最小化的θ的值。


  • 正规方程normal equation和其不可逆性

    正规方程

    • 在前面我们学习了使用梯度下降法来计算参数最优解,其过程是对代价函数相对于每个参数求偏导数,通过迭代算法一步一步进行同步更新,直到收敛到全局最小值,从而得到最优参数值。而正规方程则是通过数学方法一次性求得最优解
      0_1540395859144_8ff401c4-8002-4db5-af95-01dde826cad7-image.png
    • 通过下面这个公式得出参数θ最优解。
      0_1540395980745_eafb28a5-7b4e-42e3-8e17-3e255c769cf0-image.png

    不可逆情况

    XTXX^TX不可逆
    原因:

    1. 多余特征(线性相关)
    2. 太多特征(例如:m<=n)
    • 删除一些特征,或者正则化

    正规方程与梯度下降法的比较

    0_1540396233472_f7d90ff1-40a4-4b8e-9307-2fa61de1cade-image.png

    • 可以将万作为一个界限,当数量小于10000时,直接选择正规方程,当大于10000时,就可以考虑是否换用梯度下降法


  • 分类问题

    逻辑回归(分类算法)
    想要预测的0,1二元分类问题
    sigmoid将分类的结果很好的映射成为[0,1]之间的概率
    0_1540396493940_77fe83b6-6c0a-4ebe-9bf8-cf1916eeafa2-image.png

    • 逻辑回归最大的优势在于它的输出结果不仅可以用于分类,还可以表征某个样本属于某类别的概率。
    • 逻辑斯谛函数将原本输出结果从范围(−∞,+∞)(−∞,+∞) 映射到(0,1),从而完成概率的估测。
    • 逻辑回归得判定的阈值能够映射为平面的一条判定边界,随着特征的复杂化,判定边界可能是多种多样的样貌,但是它能够较好地把两类样本点分隔开,解决分类问题。
    • 求解逻辑回归参数的传统方法是梯度下降,构造为凸函数的代价函数后,每次沿着偏导方向(下降速度最快方向)迈进一小部分,直至N次迭代后到达最低点。


  • 逻辑回归补充

    逻辑回归的损失函数

    • 如果采用线性回归的损失函数采用的平方损失函数
      0_1540820575062_fdfa1149-5a65-472c-b376-c66f3747a2c5-image.png
      则会导致成本函数sigmoid(J(w)J(w))是一个非凸函数,收敛于局部最低点而无法收敛在全局最低点上。
      如图0_1540820701980_1c9e3d01-78b5-4675-9bb6-e43877c853aa-image.png
      因此逻辑回归中在针对二分类问题上以下代价函数:
      0_1540821059075_0dbde1be-5fac-40f0-80a1-c840852d598f-image.png

      进而得到的损失函数能保证是凸函数:
      0_1540821932393_9c25ca89-c7b9-4bfb-b621-6244cf1514e5-image.png

    它保证了一种代价“惩罚机制”,随着预测值与实际值偏差越大,代价函数将激增。
    梯度下降找θ最小化J(θ)J(θ)
    同时更新所有的θ值,与线性回归的梯度下降规则完全相同。。
    但是假设h(θ)h(θ)两者不相同。

    • 实现方法上向量法便于所有θ的同步更新。

    比梯度下降更高效的优化算法
    优化逻辑回归的速度,主要考虑对于J(θ)和偏导项计算的效率优化。
    优点在于收敛速度更快并且学习速率α可以自动调整,缺点在于算法较为复杂。



  • 多分类问题(one-vs-all)
    主要思想:将二元分类问题拓展到n元分类问题中去。
    采用“一对余”方法,将其分解为n个二元分类问题,选定一个i类别的训练集hih_i为正样本(1),其它设定为负样本(0)。然后通过二元分类,得到hih_ixx)的逻辑回归分类器。
    其中hih_ixx)=P(y=i|x;θ).
    最后,在多类别分类时,在n个分类器中选取max{hih_ixx)}对应的i即可。



  • 过拟合overfitting(高方差)问题

    • 当函数的变量很多、训练集较小时,函数能够很高的拟合训练集的数据,而无法泛化到新的样本中去。
      e.g:线性回归下的三种情形:
      • 欠拟合(高偏差)
      • 恰好
      • 过拟合(高方差)
        0_1540825295671_6e072925-0949-42a3-b1a7-569c66a4ace1-image.png
        解决方案
      • 减少选取变量的数量(人工检查,模型选择算法)(问题:减少特征变量的同时也舍弃了问题中的一些信息)
      • 正则化(保留所有的特征变量但是减少参数值的大小或者是数量级)


  • 为什么通常Relu比sigmoid和tanh强,有什么不同?(收藏一下)
    0_1540829990111_e2fd49a2-85ae-4b76-87c8-1f48feaec984-image.png
      主要是因为它们gradient特性不同。sigmoid和tanh的gradient在饱和区域非常平缓,接近于0,很容易造成vanishing gradient的问题,减缓收敛速度。vanishing gradient在网络层数多的时候尤其明显,是加深网络结构的主要障碍之一。相反,Relu的gradient大多数情况下是常数,有助于解决深层网络的收敛问题。Relu的另一个优势是在生物上的合理性,它是单边的,相比sigmoid和tanh,更符合生物神经元的特征。
      而提出sigmoid和tanh,主要是因为它们全程可导。还有表达区间问题,sigmoid和tanh区间是0到1,或着-1到1,在表达上,尤其是输出层的表达上有优势。

    为什么引入Relu呢?
      第一,采用sigmoid等函数,算激活函数时(指数运算),计算量大,反向传播求误差梯度时,求导涉及除法,计算量相对大,而采用Relu激活函数,整个过程的计算量节省很多。
      第二,对于深层网络,sigmoid函数反向传播时,很容易就会出现梯度消失的情况(在sigmoid接近饱和区时,变换太缓慢,导数趋于0,这种情况会造成信息丢失,从而无法完成深层网络的训练。
      第三,Relu会使一部分神经元的输出为0,这样就造成了网络的稀疏性,并且减少了参数的相互依存关系,缓解了过拟合问题的发生
    copied from ReLu(修正线性单元)、sigmoid和tahh的比较



  • Tensorflow搭建神经网络初步实践(基础)

    (正好学习到了cs229的神经网络部分,开始跟着教程实践一下!)
    神经网络的基本模型是神经元,基本模型其实就是乘加运算。
    一些概念:

    • 基于TensorFlow的NN:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重,得到模型。

    • 张量是多维数组,用阶表示张量的维度。

      • 0阶张量称作标量,是一个单独的数

      • 1阶张量称作向量,是一维数组

      • 2阶张量称作矩阵,表示一个二维数组

      • n阶张量,表示为t[[[[[...]]]]](n 个)

    • 数据类型:主要有tf.float32,tf.int32

    • 计算图:搭建神经网络法人计算过程,只是承载一个或多个计算节点的一张图,只搭建网络,不运算。

    • 会话:执行计算图中的节点运算

    • 神经网络的参数:指的是神经网络线上的权重w,一般会先随机生成。生成参数方法是让w=tf.Variable(生成方式)
      神经网络中常见的生成随机数/数组的函数有:
      tf.random_normal()生成正态分布随机数
      tf.truncated_normal()生成去掉过大偏离点的正态分布随机数
      tf.random_uniform()生成均匀分布的随机数
      0_1540949599973_1940f5f0-0ae7-44e7-9323-a880c999261e-image.png

    补充(正态分布和均匀分布(高斯分布))
    0_1540949144036_380b1354-be34-4a95-b3e2-27978567434f-image.png

    Ex1:(张量加法)

    import tensorflow as tf
    a=tf.constant([1.0,2.0])
    b=tf.constant([3.0,4.0])
    result=a+b
    print(result)
    

    Output:

    Tensor("add:0",shape=(2,),dtype=float32)
    

    Ex2:(矩阵乘法)

        import tensorflow as tf
        #计算图的实现
        x=tf.constant([[1.0,2.0]])
        w=tf.constant([[3.0],[4.0]])
        y=tf.matmul(x,w)
        print(y)
        #会话的with结构实现
        with tf.Session() as sess:
         	print(sess.run(y))
    

    Output:

    Tensor("matmul1:0",shape(1,1),dtype=float32)
    [[11.]]
    


  • Tensorflow搭建神经网络初步实践(前向传播)

    神经网络的实现过程
    1.准备数据集、提取特征作为输入喂给神经网络(NN)
    2.搭建NN结构,从输入到输出(先搭建计算图再用会话执行)
    ( NN 前向传播算法计算输出)
    3.大量特征数据喂给NN,迭代优化NN参数
    (NN反向传播算法优化参数训练模型)
    4.使用训练好的模型预测和分类
    前向传播就是搭建模型的计算过程,让模型具有推理能力 可以针对一组输入给出相应的输出。
    EX1:

    #coding:utf-8
    import tensorflow as tf
    #输入层
    x=tf.constant([[0.7,0.5]])
    #w为待优化的权重
    #其中,stddev为标准差,seed为随机种子
    w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
    w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))
    #将每层输入乘以权重进行矩阵乘法,得到输出y
    a=tf.matmul(x,w1)
    y=tf.matmul(a,w2)
    with tf.Session() as sess:
    	init_op=tf.global_variables_initializer()
    #在sess.run中写入init_op实现对于所有变量的初始化
    	sess.run(init_op)
    #计算图运算,输出结果
    	print(sess.run(y))
    

    EX2:

    import tensorflow as tf
    #tf.placeholder给输入占位,以便一次喂入一组或者多组数据
    x=tf.placeholder(tf.float32,shape=(1,2))
    w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
    w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))
    #前向传播
    a=tf.matmul(x,w1)
    y=tf.matmul(a,w2)
    with tf.Session() as sess:
    	init_op=tf.global_variables_initializer()
    	sess.run(init_op)
    	print(sess.run(y,feed_dict={x:[[0.7,0.5]]}))#,feed_dict喂数据
    

    EX3:

    import tensorflow as tf
    x=tf.placeholder(tf.float32,shape=(None,2))
    w1=tf.Variable(tf.random_normal([2,3],stddev=1,seed=1))
    w2=tf.Variable(tf.random_normal([3,1],stddev=1,seed=1))
    a=tf.matmul(x,w1)
    y=tf.matmul(a,w2)
    with tf.Session() as sess:
    	init_op=tf.global_variables_initializer()
    	sess.run(init_op)
    	print(sess.run(y,feed_dict={x:[[0.7,0.5],[0.2,0.3],[0.3,0.4],[0.4,0.5]]}))
    	print(sess.run(w1))
    	print(sess.run(w2))
    


  • @xuxiaohao 建议尝试不用深度学习框架,只用numpy实现神经网络的前向传播和反向传播



  • @zkhust 谢谢学长!那我去学习一下numpy!



  • 深度学习算法学习

    神经网络前向传播递推矩阵递推公式(推导练习,加深对深度学习理解)
    0_1541167273219_aad7e73e-72f8-4717-bf4c-cfc3f7a4a2ee-image.png
    【温故知新】:

    • 神经元可以看做一个函数

    • 函数的梯度反映的是函数的最陡增长方向

    • 代价函数是以bias和weight为输入,大量带标记训练数据集为参数,以一个代价数为输出的函数

    • 梯度下降算法首先计算梯度值,然后每次沿着梯度向量的反方向行走一小步 ,不断重复可以收敛。

    • 梯度向量的相反数告诉我们如何微调权重偏置的值。变动大小与 |现值-目标值| 成正比。

    • 反向传播算法算的是单个训练样本想怎样修改权重与偏置,不仅是说每个参数应该变大还是变小,还包括了每个参数应该变大还是变小,才能够最快地降低代价。

    • 反向传播算法的微积分原理:
      如图:计算代价函数对于权重的敏感程度计算公式
      0_1541168199512_d8530750-049c-447a-a653-b81471782a9e-image.png



  • 深度学习反向传播算法学习

    • 反向传播,用于训练模型参数,在所有参数上采用梯度下降,使得NN模型在训练数据上的损失函数最小
    • 损失函数,是预测值与已知答案的差距
    • 采用sigmoid等激励函数是为了当权重与偏置有一定改变时,损失函数的变化较小(相比较,感知器的激活函数则是一个阶跃函数,损失函数的会因为权重的微小变化而发生突变)。
    • 学习率,决定了参数每一次更新的幅度。

    反向传播算法的方法:

    1.将输出层的误差按权重分配,反向传播给隐藏层
    2.链式求导,根据求得的误差来求各个误差值对权重的偏导
    0_1541255632640_c087c5d3-1633-40f7-b8f1-3e01d7063551-image.png
    其中:
    0_1541255899997_5d486160-c47d-40c1-a927-677641b5d72f-image.png
    3.将计算所得的偏导值代入梯度下降公式中,进一步对于每一层的参数进行更新。
    0_1541256021742_31f8109d-2781-4521-a211-019676b8e22c-image.png

    敲重点

    经典书籍《神经网络与深度学习》中对于delta的描述为在第l层第j个神经元上的误差,定义为误差对于当前带权输入求偏导,公式如下:
    0_1541256460796_0d66df4a-7f6b-4ea2-9ce2-2687971f08b1-image.png
    反向传播4大公式(矩阵化后便于利用矩阵乘法编程实现)
    0_1541256629890_a8615c12-c795-496d-b2eb-997d9c612395-image.png
    (看了一下Stanford上面的CS229的note和problem set,感觉自己看的吴恩达机器学习CS229的版本简单好多啊)



  • 用numpy实现最简单的NN
    写了一个没有bias,没有正则化,没有很多隐藏层的NN,
    后续不断优化吧。。
    (bug:一开始写了一个有问题的输入,导致输入矩阵不可逆,出现了函数没法收敛问题。)

    #-*- coding:utf-8 -*-
    import numpy as np
    #将变量映射到(0,1)区间
    def sigmoid(x):
        return 1/(np.exp(-x)+1)
    def deriv(x):
        return x*(1-x)
    #输入数据
    x=np.array([[0,0,1],
               [0,1,1],
               [1,0,1],
               [1,1,1]])
    #输出数据
    y=np.array([[0],
                [1],
                [1],
                [0]])
    #初始化随机种子,保证每一次生成的随机数相同
    np.random.seed(1)
    #权重随机初始化
    w0=2*np.random.random((3,4))-1
    w1=2*np.random.random((4,1))-1
    #训练
    for j in range(60000):
    #正向传播
        a0=x
        a1=sigmoid(np.dot(a0,w0))
        a2=sigmoid(np.dot(a1,w1))
    
        a2_error=(y-a2)
    
        if(j%10000)==0:
            print("Error:"+str(np.mean(np.abs(a2_error))))
    #反向传播误差值
        a2_delta=a2_error*deriv(a2)
        a1_error=a2_delta.dot(w1.T)
        a1_delta=a1_error*deriv(a1)
    #梯度下降更新权值
        w1+=(a1.T).dot(a2_delta)
        w0+=(a0.T).dot(a1_delta)    
    
    

    误差收敛情况:

    Error:0.4964100319027255
    Error:0.008584525653247157
    Error:0.005789459862507806
    Error:0.004629176776769983
    Error:0.003958765280273646
    Error:0.0035101225678616736


  • NUMPY学习

    (跟着教程走了一遍NUMPY的基本语法,待日后方便查询。。。)

    #NUMPY ARRAY BASIC
    import numpy as np
    
    ###########################3
    #part1:basis
    ############################
    a=np.array([[1,2],[0,3]],dtype=np.int64)
    a.dtype#dtype=np.int64
    a.dtype.name#int64
    a.size(4)
    a.shape#(2,2)
    a.ndim#dimension   2
    np.zeros((2,3))#all 0s
    np.ones(((3,4))#all 1s
    np.empty((4,5))#all numbers->0
    np.arange(12).reshape((3,4))#generate numbers ranging from 0-11
    #and shape is (3,4)
    np.arange(10,20,2)#step is 2
    np.linspace(1,10,20)#cut a line into 20 parts
    np.linspace(1,10,2).reshape(2,1)#change the vector into matrix
    
    ############################
    #part2:calculations1
    ###########################
    c=b**2#c=b^2
    b=np.array(4),print(b==3) #output:[False,False,False,True]
    c=a*b#output,ci=ai*bin
    np.dot(a,b)#matrix multi
    <=>a.dot(b)
    
    #########################
    #part3:random number 
    #########################
    a=np.random.random((2,4))#generate a (2,4) matrix whose values are in (0,1)
    np.max(a)
    np.min(a)
    np.sum(a)
    np.max(a,axis=0)#find max in rows
    np.min(a,axis=1)#find min in cals
    
    #########################
    #part4:calculations2
    ####################
    A=np.arange(2,14).reshape((2,6))
    indexOfMin=np.argmin(A)
    np.mean(A)#average1
    np.average(A)#average
    np.median(A)#zhong wei shu
    C=np.cumsum(A)#C[0]=A[i],C[i+1]=C[0]+A[i+1]
    D=np.diff(A)#D[i+1]=A[i+1]-A[i]
    np.nonzero(A)#find nonzero numbers
    np.sort(A)#sort for each rows
    np.transpose(A)#A.T
    (A.T).dot(A)=E
    np.clip(A,a_min,a_max)#{all numbers:<a_min}:=a_min,{all numbers:>a_max}:=a_max
    np.mean(A,axis=0)
    
    ############################
    #part5:Index
    #############################
    a[2]
    a[2,1]<=>a[2][1]
    a[2,:]# row vector 2
    a[:,1]# cal vector 1
    a[1,1:2]# number in row vector 1 and(cal index ranging from [1,2))
    for row in A:
        print(row)#output its rows
    for col in A.T:
        print(col)#output its columns
    A.flatten()#change A into one dimension list 
    for item in A.flat:#A.flat is a iteration
        
    ##############################
    #part7:Emerge
    ###############################
    A=np.array([1,1,1])
    B=np.array([2,2,2])
    np.vstack((A,B))# vertical stack
    np.hstack((A,B))   #horizontal stack,out put:[1 1 1 2 2 2]
    A[np.newaxis,:] #add a new dimension in front of original dimensions
    C=np.concatenate((A,A,B,B),axis=0)#Multi-Matrix emerge  in the vertical axis
    
    ##########################################
    #part8: Split
    ###########################################
    A=np.arange(12).reshape(3,4)
    np.split(A,2,axis=1)#split the array into equal  arrays
    np.array_split(A,3,axis=1)#unequal arrays
    np.vsplit(A,3) #vertical split
    np.hsplit(A,2) #horizontal split
    
    ##########################
    #copy&deep copy
    ##########################
    a=np.arange(4)#array([0,1,2,3])
    b=a#IN NUMPY b<=>a,when a[0]:=11,b[0]turns into 11!
    b is a# output:Ture
    
    b=a.cpoy#only copy numbers->deep copy
    b is a#output False


  • PANDAS学习(1)
    (大好时光,不如刷刷熊猫)

     #Series,一位数组,与numpy的array相类似
    In [6]: s=pd.Series([1,3,6,np.nan,5,6])
    In [7]: s                                                                                                             
    Out[7]: 
    0    1.0
    1    3.0
    2    6.0
    3    NaN
    4    5.0
    5    6.0
    dtype: float64
    
    
    #DataFrame,二维的表格型数据结构,每一个坐标轴都有自己的标签。是series的字典项。
    In [19]: df=pd.DataFrame(np.random.randn(6,4),index=dates,columns=['a','b','c','d'])         #index->hang suo ying ,columns->lie suoying                   
    
    In [20]: df                                                                                                           
    Out[20]: 
                       a         b         c         d
    2016-01-01  1.083966 -1.131710  0.515652  0.837967
    2016-01-02  0.950895 -0.100363  0.247957  0.753589
    2016-01-03  0.370636  0.375547 -1.069627  1.738645
    2016-01-04 -0.726578  1.390678 -0.309058  0.495773
    2016-01-05  0.869181 -0.497488  0.550426 -0.928189
    2016-01-06  1.330088  0.252316  0.272717 -1.151035
    
    
    
    In [22]: df1=pd.DataFrame(np.arange(12).reshape((3,4)))                                                               
    
    In [23]: df1                                                                                                          
    Out[23]: 
       0  1   2   3
    0  0  1   2   3
    1  4  5   6   7
    2  8  9  10  11
    
    
    In [9]: df2=pd.DataFrame({'A':[1.], 
       ...:                   'B':['C']})                                                                                 
    
    In [10]: df2                                                                                                          
    Out[10]: 
         A  B
    0  1.0  C
    
    
    In [15]: df2=pd.DataFrame({'A':np.arange(4), 
        ...:                   'B':pd.Categorical(["test","train","test","train"])})                                      
    
    In [16]: df2                                                                                                          
    Out[16]: 
       A      B
    0  0   test
    1  1  train
    2  2   test
    3  3  train
    
    #得到DataFrame的各列数据类型
    In [19]: df2.dtypes                                                                                                   
    Out[19]: 
    A       int64
    B    category
    dtype: object
    
    #列索引.index
    In [20]: df2.index                                                                                                    
    Out[20]: RangeIndex(start=0, stop=4, step=1)
    
    #行索引.column
    In [21]: df2.columns                                                                                                  
    Out[21]: Index(['A', 'B'], dtype='object')
    
    #DataFrame的数据部分.values
    In [23]: c=df2.values                                                                                                 
    
    In [24]: c                                                                                                            
    Out[24]: 
    array([[0, 'test'],
           [1, 'train'],
           [2, 'test'],
           [3, 'train']], dtype=object)
    
    
    
    #.describe()可以做一些number的分析,如个数、平均值、方差等。
    In [25]: df2.describe()                                                                                               
    Out[25]: 
                  A
    count  4.000000
    mean   1.500000
    std    1.290994
    min    0.000000
    25%    0.750000
    50%    1.500000
    75%    2.250000
    max    3.000000
    
    #看做矩阵,.T求转置
    In [26]: df2.T                                                                                                        
    Out[26]: 
          0      1     2      3
    A     0      1     2      3
    B  test  train  test  train
    
    #将行或者列(axis=0)进行升或降(ascending=False)序排列
    In [31]: df2.sort_index(axis=0,ascending=False)                                                                       
    Out[31]: 
       A      B
    3  3  train
    2  2   test
    1  1  train
    0  0   test
    
    Out[33]: 
       A      B
    0  0   test
    1  1  train
    2  2   test
    3  3  train
    
    #将某个索引下的values进行排序
    In [34]: df2.sort_values(by='B')                                                                                      
    Out[34]: 
       A      B
    0  0   test
    2  2   test
    1  1  train
    3  3  train
    


  • Sklearn.datasets探索

    1.boston数据集适合于Regression训练

    
     1 from sklearn.datasets import load_boston
     2 import numpy as np
     3 boston=load_boston()
     4 print(boston.data.shape)
    
     (506, 13)
    

    2.Iris数据集适合于multi-classifier训练

     
    In [12]: from sklearn.datasets import load_iris
    In [13]: iris=load_iris()         
    In [14]: print(iris.data.shape)       
    (150, 4)
    
    In [15]: print(iris.target.shape)                               
    (150,)
    
    In [16]: list(iris.target_names)                        
    Out[16]: ['setosa', 'versicolor', 'virginica']
    
    In [20]: data,target=load_iris(return_X_y=True)           
    
    In [21]: print(data.shape)                      
    (150, 4)
    
    In [22]: print(target.shape)                            
    (150,)
    
    

    3.digits手写数字数据集(8*8)
    +用matplotlib画图并保存图像

    Linux由于没有GUI,所以要以下面的方式导入matplotlib.pyplot

    import matplotlib                                                                       
    matplotlib.use('Agg')                                                                   
    import matplotlib.pyplot as plt   
    

    以matplotlib.pyplot.savefig( )函数保存图片后查看

    In [1]: from sklearn.datasets import load_digits                                                
    
    In [2]: digits=load_digits()                         
    
    In [3]: print(digits.data.shape)                                         
    (1797, 64)
    
    In [4]: print(digits.target.shape)  
    (1797,)
    
    In [5]: print(digits.images.shape)                                                              
    (1797, 8, 8)
    
    In [6]: import matplotlib                                                                       
    
    In [8]: matplotlib.use('Agg')                                                   
    
    In [9]: import matplotlib.pyplot as plt                          
    
    In [10]: plt.matshow(digits.images[0])                                    
    Out[10]: <matplotlib.image.AxesImage at 0x7ff5dce8c518>
    
    In [11]: plt.show()                                                                             
    /home/xxh/.local/lib/python3.7/site-packages/matplotlib/figure.py:445: UserWarning: Matplotlib is currently using agg, which is a non-GUI backend, so cannot show the figure.
      % get_backend())
    
    In [12]: plt.savefig('/home/xxh/tf/1.png')  
    
    

    0_1541837629134_b5b5bc8b-6648-42be-a760-8d339218c660-image.png



  • KNN

    • K-近邻是聚类的一种算法,用于数据分类。

    • KNN算法主要步骤
      1)计算测试数据与各个训练数据之间距离
      (一般使用欧氏距离或曼哈顿距离)
      2)按距离的递增关系进行排序
      3)选取距离最小的K个点
      4)确定前K个点所在类别的出现频率
      5)返回前K个点中出现频率最高的类别作为测试数据的预测分类

    from numpy import *
    import operator
    def createDataSet():
        data=array([[1.0,1.1],[1.0,0.9],[0.0,0.1],[0,0.1]])
        target=['A','A','B','B']
        return data,target
    def classify(test,data,target,k):
        datasize=data.shape[0]
        diff=tile(test,(datasize,1))-data#tile(,):test按照(x,y)方向复制datasize和1遍
        sq_diff=diff**2
        sq_dis=sq_diff.sum(axis=1)
        dis=sq_dis**0.5
        sorted_dis_index=dis.argsort()#argsort()得出索引排序结果,升序
        cnt={}
        for i in range(k):
            num=target[sorted_dis_index[i]]
            cnt[num]=cnt.get(num,0)+1#.get() 返回cnt[num]的值(如果 cnt[num]不存在,初始化cnt[num]=0)
        sorted_cnt=sorted(cnt.items(),key=operator.itemgetter(1),reverse=True)#operator.itemgetter(1),获取对象的第1个域的值
        return sorted_cnt[0][0]
    data,target=createDataSet()
    print(classify([1,1],data,target,3))
    
    

    KNN算法的缺陷
    (1) 样本不均衡
    采用权值的方法来改进。和该样本距离小的邻居权值大,和该样本距离大的邻居权值则相对较小
    (2) 计算非常耗时。为了提高kNN搜索的效率,可以考虑使用特殊的结构存储训练数据,以减小计算距离的次数。

    Solution:K Dimension Tree

    • kd树是是一种二叉树,表示对k维空间的一个划分,构造kd树相当于不断地用垂直于坐标轴的超平面将K维空间切分,构成一系列的K维超矩形区域。kd树的每个结点对应于一个k维超矩形区域。利用kd树可以省去对大部分数据点的搜索,从而减少搜索的计算量。

    KNN中的优化算法KD-tree



  • 机器学习实战--KNN分类器
    1.KNN聚类算法

    from numpy import *
    import operator
    def classify(test,data,target,k):
        datasize=data.shape[0]
        diff=tile(test,(datasize,1))-data#tile()
        sq_diff=diff**2
        sq_dis=sq_diff.sum(axis=1)
        dis=sq_dis**0.5
        sorted_dis_index=dis.argsort()
        cnt={}
        for i in range(k):
            num=target[sorted_dis_index[i]]
            cnt[num]=cnt.get(num,0)+1#get() return value of cnt[num](if cnt[num] doesn't exist cnt[num]=0)
        sorted_cnt=sorted(cnt.items(),key=operator.itemgetter(1),reverse=True)#itemgetter(1) 
        return sorted_cnt[0][0]
    #data,target=createDataSet()
    #print(classify([1,1],data,target,3))
    

    2.文件转矩阵形式

    def file2matrix(filename):
    	f=open(filename)
    	array_line=f.readlines()
    	len_line=len(array_line)
    	data=zeros((len_line,3))
    	tar=[]
    	index=0
    	for line in array_line:
    		line=line.strip()
    		line2list=line.split('\t')
    		data[index,:]=line2list[0:3]
    		tar.append(int(line2list[-1]))
    		index+=1
    	return data,tar
    
    
    dt,tar=file2matrix('datingTestSet2.txt')
    #print(dt)
    #print(tar)
    

    3.作图观察数据集两列特征值之间的关系

    import matplotlib as mlp
    mlp.use('Agg')
    import matplotlib.pyplot as plt
    fig=plt.figure()
    ax=fig.add_subplot(111)
    ax.scatter(dt[:,1],dt[:,2],15.0*array(tar),15.0*array(tar))
    
    #plt.savefig('/home/xxh/tf/KNN/datingTestPic.png')
    

    得到散点图:
    0_1541941780830_51854449-0003-413b-a9a6-6fcbffd0491d-image.png

    3.数据归一化

    def autoNorm(dataset):
    	minval=dataset.min(0)
    	maxval=dataset.max(0)
    	Range=maxval-minval
    	normdataset=zeros(shape(dataset))
    	m=dataset.shape[0]
    	normdataset=dataset-tile(minval,(m,1))
    	normdataset=normdataset/tile(Range,(m,1))
    	return normdataset,Range,minval
    
    #normdt,range,minval=autoNorm(dt)
    #print(normdt)
    #print(range)
    #print(minval)
    

    4.分类器测试(主函数)

    def datingClassTest():
    	errorList=[]
    	ratioList=[]
    	data,target=file2matrix('datingTestSet2.txt')
    	normdata,ranges,minval=autoNorm(data)
    	m=normdata.shape[0]	
    	for j in range(1,100):
    		ratioOfTrainingData=0.01*j
    		ratioList.append(ratioOfTrainingData)
    		numOfTrainingData=int(m*ratioOfTrainingData)
    		errorNum=0.0
    		for i in range(numOfTrainingData):
    			result=classify(normdata[i,:],normdata[numOfTrainingData:m,:],target[numOfTrainingData:m],3)
    			if(result!=target[i]):errorNum+=1.0
    		errorRate=errorNum/float(numOfTrainingData)
    		print(j,end=' ')
    		print(errorRate)
    		errorList.append(float(errorRate))
    		
    	figure=plt.figure()
    	axx=figure.add_subplot(111)
    	axx.scatter(ratioList[:],errorList[:])	
    	plt.savefig('/home/xxh/tf/KNN/KNN_TEST.png')
    datingClassTest()
    

    顺便画了一下测试集比例与准确率之间的关系图
    0_1541941937215_daf90642-ac49-43b5-b123-d9eb482f8702-image.png
    5.分类器使用

    def classifyPerson():
    	resultList=['not at all','in small doses','in large doses']
    	percent=float(input("percentage"))
    	ffm=float(input("frequence"))
    	icecream=float(input("ice-cream"))
    	data,target=file2matrix('datingTestSet2.txt')
    	normdata,ranges,minval=autoNorm(data)
    	inArr=array([ffm,percent,icecream])
    	result=classify((inArr-minval)/ranges,normdata,target,3)
    	print(resultList[result-1])
    
    classifyPerson()
    


  • 机器学习实战——KNN手写数字识别

    
    from numpy import*
    from os import listdir
    import operator
    

    1.基于KNN的分类器

    
    def classify(test,data,target,k):
        datasize=data.shape[0]
        diff=tile(test,(datasize,1))-data#tile(扩展行,扩展列)
        sq_diff=diff**2
        sq_dis=sq_diff.sum(axis=1)#axis=1->求列的和;axis=0->求行的和
        dis=sq_dis**0.5
        sorted_dis_index=dis.argsort()
        cnt={}
        for i in range(k):
            num=target[sorted_dis_index[i]]
            cnt[num]=cnt.get(num,0)+1
        sorted_cnt=sorted(cnt.items(),key=operator.itemgetter(1),reverse=True)#itemgetter(1) :0->index,1->key
        return sorted_cnt[0][0]
    #data,target=createDataSet()
    #print(classify([1,1],data,target,3))
    

    2.图片转向量

    def img2vec(filename):
    	returnVec=zeros((1,1024))
    	fr=open(filename)
    	for i in range(32):
    		lineStr=fr.readline()
    		for j in range(32):
    			returnVec[0,32*i+j]=int(lineStr[j])
    	return returnVec
    #testVector=img2vec("0_0.txt")
    

    3.手写数字识别主函数

    def digitRecognition():
    	hwLabels=[]
    	dataFileList=listdir('trainingDigits')
    	len_fileList=len(dataFileList)
    	data=zeros((len_fileList,1024))
    	for i in range(len_fileList):
    		fileNameStr=dataFileList[i]
    		fileStr=fileNameStr.split(',')[0]
    		classNumStr=int(fileStr.split('_')[0])
    		hwLabels.append(classNumStr)
    		data[i,:]=img2vec('trainingDigits/%s'% fileNameStr)
    	testFileList=listdir('testDigits')
    	errorCnt=0.0
    	len_testList=len(testFileList)
    	for i in range(len_testList):
    		fileNameStr=testFileList[i]
    		fileStr=fileNameStr.split(',')[0]
    		classNumStr=int(fileStr.split('_')[0])
    		testVector=img2vec('testDigits/%s'%fileNameStr)
    		classifierResult=classify(testVector,data,hwLabels,3)
    		print("classifier: %d, right: %d" %(classifierResult ,classNumStr))
    		if( classifierResult != classNumStr ): 
    			errorCnt+=1.0
    	errorRate=(errorCnt/float(len_testList))
    	#print(len_testList)
    	print(errorCnt)
    	print(errorRate)
    

    4.测试结果:(好慢啊)

    #errorCnt:11.0
    #errorRate:0.011627906976744186
    #timeCost:19.133 seconds
    

 

Copyright © 2018 bbs.dian.org.cn All rights reserved.

与 Dian 的连接断开,我们正在尝试重连,请耐心等待