ITPub博客

首页 > 应用开发 > IT综合 > 详解 | 如何用Python实现机器学习算法

详解 | 如何用Python实现机器学习算法

IT综合 作者:DicksonJYL560101 时间:2018-01-05 14:52:11 0 删除 编辑

详解 | 如何用Python实现机器学习算法

 

https://mp.weixin.qq.com/s/-iFP0u8QJHY8d1NPkfSNWQ

 

人生苦短,就用 Python。

 

在 Kaggle 最新发布的全球数据科学/机器学习现状报告中,来自 50 多个国家的 16000 多位从业者纷纷向新手们推荐 Python 语言,用以学习机器学习。

 

http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCWNMkcRTibh4HI0JmHaVNNCXG8bmEtg4icEfL2xBDEBhtjCfytmiaEgzgg/640?wx_fmt=png&wxfrom=5&wx_lazy=1



那么,用Python实现出来的机器学习算法都是什么样子呢?营长刚好在 GitHub 上发现了东南大学研究生“Lawlite”的一个项目——机器学习算法的Python实现,下面从线性回归到反向传播算法、从SVM到K-means聚类算法,咱们一一来分析其中的Python代码。

 

 

目录

  • 一、线性回归

    • 1、代价函数

    • 2、梯度下降算法

    • 3、均值归一化

    • 4、最终运行结果

    • 5、使用scikit-learn库中的线性模型实现

  • 二、逻辑回归

    • 1、代价函数

    • 2、梯度

    • 3、正则化

    • 4、S型函数(即)

    • 5、映射为多项式

    • 6、使用的优化方法

    • 7、运行结果

    • 8、使用scikit-learn库中的逻辑回归模型实现

  • 逻辑回归_手写数字识别_OneVsAll

    • 1、随机显示100个数字

    • 2、OneVsAll

    • 3、手写数字识别

    • 4、预测

    • 5、运行结果

    • 6、使用scikit-learn库中的逻辑回归模型实现

  • 三、BP神经网络

    • 1、神经网络model

    • 2、代价函数

    • 3、正则化

    • 4、反向传播BP

    • 5、BP可以求梯度的原因

    • 6、梯度检查

    • 7、权重的随机初始化

    • 8、预测

    • 9、输出结果

  • 四、SVM支持向量机

    • 1、代价函数

    • 2、Large Margin

    • 3、SVM Kernel(核函数)

    • 4、使用中的模型代码

    • 5、运行结果

  • 五、K-Means聚类算法

    • 1、聚类过程

    • 2、目标函数

    • 3、聚类中心的选择

    • 4、聚类个数K的选择

    • 5、应用——图片压缩

    • 6、使用scikit-learn库中的线性模型实现聚类

    • 7、运行结果

  • 六、PCA主成分分析(降维)

    • 1、用处

    • 2、2D-->1D,nD-->kD

    • 3、主成分分析PCA与线性回归的区别

    • 4、PCA降维过程

    • 5、数据恢复

    • 6、主成分个数的选择(即要降的维度)

    • 7、使用建议

    • 8、运行结果

    • 9、使用scikit-learn库中的PCA实现降维

  • 七、异常检测 Anomaly Detection

    • 1、高斯分布(正态分布)

    • 2、异常检测算法

    • 3、评价的好坏,以及的选取

    • 4、选择使用什么样的feature(单元高斯分布)

    • 5、多元高斯分布

    • 6、单元和多元高斯分布特点

    • 7、程序运行结果

       

      正文

       

      一、线性回归

       

      https://github.com/lawlite19/MachineLearning_Python/tree/master/LinearRegression

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LinearRegression/LinearRegression.py

       

      1、代价函数

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCLmic47cFhia9PJuOpC2icDx9ffMNagKcY7w8Tx4ibOnicQibUJBLKH24hWfg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      其中: http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCr8uOFVic7t8GvG6KHfCdFyuovwBDtP3DtVUtBhAjcOx198FRIWuwDNg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      下面就是要求出theta,使代价最小,即代表我们拟合出来的方程距离真实值最近

       

      共有m条数据,其中http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCaUczwowUAwmU4fQMB3iaSqSRlwAicldqlwHBkNiaCuMZIPsVaiaGxLBr3w/640?wx_fmt=png&wxfrom=5&wx_lazy=1代表我们要拟合出来的方程到真实值距离的平方,平方的原因是因为可能有负值,正负可能会抵消

       

      前面有系数2的原因是下面求梯度是对每个变量求偏导,2可以消去

       

      实现代码:

       

      # 计算代价函数

      def computerCost(X,y,theta):

          m = len(y)

          J = 0

          

          J = (np.transpose(X*theta-y))*(X*theta-y)/(2*m) #计算代价J

          return J

       

      注意这里的X是真实数据前加了一列1,因为有theta(0)

       

      2、梯度下降算法

       

      代价函数对http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCMaicW6l20ibloySAiaKfYgqEUrrQJgbQo6y6FLKWxKOuLJg8ZSHyUGcnw/640?wx_fmt=png&wxfrom=5&wx_lazy=1求偏导得到:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC18cA2q85X7YuVXgiaW6d7cLwU28jtz24cibaL65LNPKccGUlx9lQRsGA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      所以对theta的更新可以写为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC8FjaU1l0ia4yU8cqBicDJzuLzpDY7OElGb59efxaqeUvVicxqibC8Cln4Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      其中http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC0l9vpcaeLIGS8gMgkqTazY7F98btPvQg7qk93amslZakZleV8EbIHA/640?wx_fmt=png&wxfrom=5&wx_lazy=1为学习速率,控制梯度下降的速度,一般取0.01,0.03,0.1,0.3.....

       

      为什么梯度下降可以逐步减小代价函数?

       

      假设函数f(x)

       

      泰勒展开:f(x+△x)=f(x)+f'(x)*△x+o(△x),

       

      令:△x=-α*f'(x) ,即负梯度方向乘以一个很小的步长α

       

      将△x代入泰勒展开式中:f(x+x)=f(x)-α*[f'(x)]?+o(△x)

       

      可以看出,α是取得很小的正数,[f'(x)]?也是正数,所以可以得出:f(x+△x)<=f(x)

       

      所以沿着负梯度放下,函数在减小,多维情况一样。

       

      # 梯度下降算法

      def gradientDescent(X,y,theta,alpha,num_iters):

          m = len(y)      

          n = len(theta)

          

          temp = np.matrix(np.zeros((n,num_iters)))   # 暂存每次迭代计算的theta,转化为矩阵形式

          

          J_history = np.zeros((num_iters,1)) #记录每次迭代计算的代价值

          

          for i in range(num_iters):  # 遍历迭代次数    

              h = np.dot(X,theta)     # 计算内积,matrix可以直接乘

              temp[:,i] = theta - ((alpha/m)*(np.dot(np.transpose(X),h-y)))   #梯度的计算

              theta = temp[:,i]

              J_history[i] = computerCost(X,y,theta)      #调用计算代价函数

              print '.',      

          return theta,J_history  

       

      3、均值归一化

       

      目的是使数据都缩放到一个范围内,便于使用梯度下降算法http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCVRSR7icAR5nEGrUtbmTyZVkDZURuyJ5WDqtl8yrRiadEIONpaCGSkuIA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      其中  为所有此feture数据的平均值

       

      可以是最大值-最小值,也可以是这个feature对应的数据的标准差

       

      实现代码:

       

      # 归一化feature

      def featureNormaliza(X):

          X_norm = np.array(X)            #将X转化为numpy数组对象,才可以进行矩阵的运算

          #定义所需变量

          mu = np.zeros((1,X.shape[1]))   

          sigma = np.zeros((1,X.shape[1]))

          

          mu = np.mean(X_norm,0)          # 求每一列的平均值(0指定为列,1代表行)

          sigma = np.std(X_norm,0)        # 求每一列的标准差

          for i in range(X.shape[1]):     # 遍历列

              X_norm[:,i] = (X_norm[:,i]-mu[i])/sigma[i]  # 归一化

          

          return X_norm,mu,sigma

       

      注意预测的时候也需要均值归一化数据

       

      4、最终运行结果

       

      代价随迭代次数的变化

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCBkmAFHwMdf7bE9HZuuwQGAayrkNG4VuXrCW0xOwGfMlSELOdSdWnCQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      5、使用scikit-learn库中的线性模型实现

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LinearRegression/LinearRegression_scikit-learn.py

       

      导入包

      from sklearn import linear_model 

      from sklearn.preprocessing import StandardScaler    #引入缩放的包 

       

      归一化

      # 归一化操作    

      scaler = StandardScaler()        

      scaler.fit(X)     

      x_train = scaler.transform(X)     

      x_test = scaler.transform(np.array([1650,3])) 

       

      线性模型拟合

       # 线性模型拟合     

      model = linear_model.LinearRegression()     

      model.fit(x_train, y) 

       

      预测

      #预测结果     

      result = model.predict(x_test) 

       

       

      二、逻辑回归

       

      https://github.com/lawlite19/MachineLearning_Python/tree/master/LogisticRegression

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LogisticRegression/LogisticRegression.py

       

      1、代价函数

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCOfAebmqdUXicqtmV1LaLbYcuNOWMlHB8icMTLw1osrrKOHHDYbfVibrqA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      可以综合起来为: 

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCZJYoZsqGec9whV6vZpQhzv6kfu7zwDTRVEBzPaTTYWy7IFUe6cGfRg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

       其中:

       

       http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCwmjMqNBzn99M10qialHPV5XBwb5HB58icX2DR3DJ7Wekic3zmbuTVX7cQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      为什么不用线性回归的代价函数表示,因为线性回归的代价函数可能是非凸的,对于分类问题,使用梯度下降很难得到最小值,上面的代价函数是凸函数

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCooljsmCHZDiaYhHDGnXiaQjicPUssgfqkbviaW18HibcdCe2zzduib0Y4sSg/640?wx_fmt=png&wxfrom=5&wx_lazy=1的图像如下,即y=1时: 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCAALZaWpTRibKzDiay9k9B42FB9rv7QLGibydbiaeIwz2HgxiblmrGv6UzbA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      可以看出,当http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCSpBPLCanYWrGWzXUhicJwicdz9tXxAlzxxFJrGDy04mpoPkicibYZ1n0pQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1趋于1,y=1,与预测值一致,此时付出的代价cost趋于0,若http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCSpBPLCanYWrGWzXUhicJwicdz9tXxAlzxxFJrGDy04mpoPkicibYZ1n0pQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1趋于0,y=1,此时的代价cost值非常大,我们最终的目的是最小化代价值

       

      同理http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC1UF9EtJB1PmcwTQrFIq7Z3z5fkc2fdFN68FdUyMia86swdNibyUfW6Jw/640?wx_fmt=png&wxfrom=5&wx_lazy=1的图像如下(y=0):

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCgMkLSnic7GPgyEDrFqjEDsW094nEKdEPqQ5nY9aRDrFt1yONricc6ENg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      2、梯度

       

      同样对代价函数求偏导: 

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC18cA2q85X7YuVXgiaW6d7cLwU28jtz24cibaL65LNPKccGUlx9lQRsGA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      可以看出与线性回归的偏导数一致

       

      推导过程 

       

      https://mmbiz.qpic.cn/mmbiz_jpg/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC7iaYNAjwEHb0mLe8rXciaeOkO9JPS00eibq1AqbE0plib8kRHDdUzSSRIw/640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

       

      3、正则化

       

      目的是为了防止过拟合

       

      在代价函数中加上一项

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCiaicc23WiaQdicoeOjLVtwD4quJSj9TZpskM55PJRibwXGLwsOIs3TNozCw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      注意j是重1开始的,因为theta(0)为一个常数项,X中最前面一列会加上1列1,所以乘积还是theta(0),feature没有关系,没有必要正则化

       

      正则化后的代价:

       

      # 代价函数

      def costFunction(initial_theta,X,y,inital_lambda):

          m = len(y)

          J = 0

          

          h = sigmoid(np.dot(X,initial_theta))    # 计算h(z)

          theta1 = initial_theta.copy()           # 因为正则化j=1从1开始,不包含0,所以复制一份,前theta(0)值为0 

          theta1[0] = 0   

          

          temp = np.dot(np.transpose(theta1),theta1)

          J = (-np.dot(np.transpose(y),np.log(h))-np.dot(np.transpose(1-y),np.log(1-h))+temp*inital_lambda/2)/m   # 正则化的代价方程

          return J

       

      正则化后的代价的梯度

       

      # 计算梯度 

      def gradient(initial_theta,X,y,inital_lambda):

          m = len(y)

          grad = np.zeros((initial_theta.shape[0]))

          

          h = sigmoid(np.dot(X,initial_theta))# 计算h(z)

          theta1 = initial_theta.copy()

          theta1[0] = 0

       

          grad = np.dot(np.transpose(X),h-y)/m+inital_lambda/m*theta1 #正则化的梯度

          return grad  

       

      4、S型函数(即)

       

      实现代码:

      # S型函数

      def sigmoid(z):

          h = np.zeros((len(z),1))    # 初始化,与z的长度一置

       

          h = 1.0/(1.0+np.exp(-z))     return h 

       

      5、映射为多项式

       

      因为数据的feture可能很少,导致偏差大,所以创造出一些feture结合

       

      eg:映射为2次方的形式:

       

      实现代码:

       

      # 映射为多项式 

      def mapFeature(X1,X2):

          degree = 3;                     # 映射的最高次方

          out = np.ones((X1.shape[0],1))  # 映射后的结果数组(取代X)

          '''

          这里以degree=2为例,映射为1,x1,x2,x1^2,x1,x2,x2^2

          '''

          for i in np.arange(1,degree+1): 

              for j in range(i+1):

                  temp = X1**(i-j)*(X2**j)    #矩阵直接乘相当于matlab中的点乘.*

                  out = np.hstack((out, temp.reshape(-1,1)))

          return out

       

      6、使用scipy的优化方法

       

      梯度下降使用scipy中optimize中的fmin_bfgs函数

       

      调用scipy中的优化算法fmin_bfgs(拟牛顿法Broyden-Fletcher-Goldfarb-Shanno

      costFunction是自己实现的一个求代价的函数,

       

      initial_theta表示初始化的值,

       

      fprime指定costFunction的梯度

       

      args是其余测参数,以元组的形式传入,最后会将最小化costFunction的theta返回

       

      result = optimize.fmin_bfgs(costFunction, initial_theta, fprime=gradient, args=(X,y,initial_lambda))     

       

      7、运行结果

       

      data1决策边界和准确度

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCXQuycAicyh2E8zU68Zj8Lia2ibxZIKt2Fg7zzZvmhyXrQCEKjqfSTIatg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      data2决策边界和准确度

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCWx1EWUlZ2pjZ8DXG1wYt5KKrq0QJx1krXTGjk89U67zBhmNfqHUPNg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      8、使用scikit-learn库中的逻辑回归模型实现

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LogisticRegression/LogisticRegression_scikit-learn.py

       

      导入包

      from sklearn.linear_model import LogisticRegression 

      from sklearn.preprocessing import StandardScaler 

      from sklearn.cross_validation import train_test_split 

      import numpy as np 

       

      划分训练集和测试集

      # 划分为训练集和测试集     

      x_train,x_test,y_train,y_test = train_test_split(X,y,test_size=0.2) 

       

      归一化

      # 归一化     

      scaler = StandardScaler()     

      scaler.fit(x_train)     

      x_train = scaler.fit_transform(x_train)     

      x_test = scaler.fit_transform(x_test) 

       

      逻辑回归

      #逻辑回归     

      model = LogisticRegression()     

      model.fit(x_train,y_train) 

       

      预测

      # 预测     

      predict = model.predict(x_test)    

      right = sum(predict == y_test)          

      predict = np.hstack((predict.reshape(-1,1),y_test.reshape(-1,1)))   # 将预测值和真实值放在一块,好观察     

      print predict     

      print ('测试集准确率:%f%%'%(right*100.0/predict.shape[0]))       #计算在测试集上的准确度 

       

       

      逻辑回归_手写数字识别_OneVsAll

       

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LogisticRegression

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LogisticRegression/LogisticRegression_OneVsAll.py

       

      1、随机显示100个数字

       

      我没有使用scikit-learn中的数据集,像素是20*20px,彩色图如下 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCJWPPIycZaSkUZCskD2EbF8icduAZZU1094FKQicrKoMR0yZzhic9eb2Tg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      灰度图: 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCBEKGiabKlVJ5icrD97hoic6JORxLMK7DzrzdNT2b0P7Ilic7145bA4ndTQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      实现代码:

      # 显示100个数字

      def display_data(imgData):

          sum = 0

          '''

          显示100个数(若是一个一个绘制将会非常慢,可以将要画的数字整理好,放到一个矩阵中,显示这个矩阵即可)

          - 初始化一个二维数组

          - 将每行的数据调整成图像的矩阵,放进二维数组

          - 显示即可

          '''

          pad = 1

          display_array = -np.ones((pad+10*(20+pad),pad+10*(20+pad)))

          for i in range(10):

              for j in range(10):

                  display_array[pad+i*(20+pad):pad+i*(20+pad)+20,pad+j*(20+pad):pad+j*(20+pad)+20] = (imgData[sum,:].reshape(20,20,order="F"))    # order=F指定以列优先,在matlab中是这样的,python中需要指定,默认以行

                  sum += 1

                  

          plt.imshow(display_array,cmap='gray')   #显示灰度图像

          plt.axis('off')

          plt.show()

       

      2、OneVsAll

       

      如何利用逻辑回归解决多分类的问题,OneVsAll就是把当前某一类看成一类,其他所有类别看作一类,这样有成了二分类的问题了

       

      如下图,把途中的数据分成三类,先把红色的看成一类,把其他的看作另外一类,进行逻辑回归,然后把蓝色的看成一类,其他的再看成一类,以此类推... 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC6rUKgnqwh3IYkiaNtoNw6sbhRia4YSp7icnRPr7HKdPuMJVAzXkZ1n0BQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      可以看出大于2类的情况下,有多少类就要进行多少次的逻辑回归分类

       

      3、手写数字识别

       

      共有0-9,10个数字,需要10次分类

       

      由于数据集y给出的是0,1,2...9的数字,而进行逻辑回归需要0/1的label标记,所以需要对y处理

       

      说一下数据集,前500个是0,500-1000是1,...,所以如下图,处理后的y,前500行的第一列是1,其余都是0,500-1000行第二列是1,其余都是0.... 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCSjicPVk7micIhJeAXSjmwBaT6r8qYiabo3f0j3UWGaib071RKxo38Dxvqw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      然后调用梯度下降算法求解theta

       

      实现代码:

      # 求每个分类的theta,最后返回所有的all_theta    

      def oneVsAll(X,y,num_labels,Lambda):

          # 初始化变量

          m,n = X.shape

          all_theta = np.zeros((n+1,num_labels))  # 每一列对应相应分类的theta,共10列

          X = np.hstack((np.ones((m,1)),X))       # X前补上一列1的偏置bias

          class_y = np.zeros((m,num_labels))      # 数据的y对应0-9,需要映射为0/1的关系

          initial_theta = np.zeros((n+1,1))       # 初始化一个分类的theta

          

          # 映射y

          for i in range(num_labels):

              class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值

          

          #np.savetxt("class_y.csv", class_y[0:600,:], delimiter=',')    

          

          '''遍历每个分类,计算对应的theta值'''

          for i in range(num_labels):

              result = optimize.fmin_bfgs(costFunction, initial_theta, fprime=gradient, args=(X,class_y[:,i],Lambda)) # 调用梯度下降的优化方法

              all_theta[:,i] = result.reshape(1,-1)   # 放入all_theta中

              

          all_theta = np.transpose(all_theta) 

          return all_theta

       

      4、预测

       

      之前说过,预测的结果是一个概率值,利用学习出来的theta代入预测的S型函数中,每行的最大值就是是某个数字的最大概率,所在的列号就是预测的数字的真实值,因为在分类时,所有为0的将y映射在第一列,为1的映射在第二列,依次类推

       

      实现代码:

      # 预测

      def predict_oneVsAll(all_theta,X):

          m = X.shape[0]

          num_labels = all_theta.shape[0]

          p = np.zeros((m,1))

          X = np.hstack((np.ones((m,1)),X))   #在X最前面加一列1

          

          h = sigmoid(np.dot(X,np.transpose(all_theta)))  #预测

       

          '''

          返回h中每一行最大值所在的列号

          - np.max(h, axis=1)返回h中每一行的最大值(是某个数字的最大概率)

          - 最后where找到的最大概率所在的列号(列号即是对应的数字)

          '''

          p = np.array(np.where(h[0,:] == np.max(h, axis=1)[0]))  

          for i in np.arange(1, m):

              t = np.array(np.where(h[i,:] == np.max(h, axis=1)[i]))

              p = np.vstack((p,t))

          return p

       

      5、运行结果

       

      10次分类,在训练集上的准确度:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC7MTHYtq5zTH3jM6iaUujSGicpbNAtAia8LWhfJwAKsMPfbAicHw0P6oicaQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      6、使用scikit-learn库中的逻辑回归模型实现

      https://github.com/lawlite19/MachineLearning_Python/blob/master/LogisticRegression/LogisticRegression_OneVsAll_scikit-learn.py

       

      1、导入包

      from scipy import io as spio 

      import numpy as np 

      from sklearn import svm 

      from sklearn.linear_model import LogisticRegression 

       

      2、加载数据

      data = loadmat_data("data_digits.mat")      

      X = data['X']   # 获取X数据,每一行对应一个数字20x20px     

      y = data['y']   # 这里读取mat文件y的shape=(5000, 1)     

      y = np.ravel(y) # 调用sklearn需要转化成一维的(5000,)

       

      3、拟合模型

      model = LogisticRegression()     

      model.fit(X, y) # 拟合 

       

      4、预测

      predict = model.predict(X) #预测          

      print u"预测准确度为:%f%%"%np.mean(np.float64(predict == y)*100) 

       

      5、输出结果(在训练集上的准确度) 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCCnm8XAbZMjpLePuhgK5resnrqu4hYHZJvOcU9ibGkOFA9tSokc629GQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

       

      三、BP神经网络

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/NeuralNetwok/NeuralNetwork.py

       

      1、神经网络model

       

      先介绍个三层的神经网络,如下图所示

       

      输入层(input layer)有三个units(http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCvIcfQJUFDxPMfRCKNEt3yvpdpKK0C39D452DhjEMbME7MO1YCNkiasw/640?wx_fmt=png&wxfrom=5&wx_lazy=1为补上的bias,通常设为1)

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC4ialgJ1p6u3iaPNxibPe3ia77y1w6u2xP75CQDibuaERcdtHQiaYwSTcHxyA/640?wx_fmt=png&wxfrom=5&wx_lazy=1表示第j层的第i个激励,也称为为单元unit

       

      为第j层到第j+1层映射的权重矩阵,就是每条边的权重 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCiaZksTGhHDb0E6XOfhyfPlVWCnlx0jX4zlXZmKwb2qyI5NwduZc5E6g/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      所以可以得到:

       

      隐含层:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVChU6lt4uH3w0qekMZw8CKXYF8KyoXXGsfdbqWMxE1k2IFbelhgpxrtQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC9SvQZGoMHKvatnZrjOxzsU93dTWYnBCeESiasI45bYPmibJdYroSSJsQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCRayEGMN0BXrSI9ibCuooT7icTG32Xrr7dx5rVfQUXcNciczGpYwk6kaaw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      输出层http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCTojcF5FvhLeibl7kS7vGF1ticPWp8t5gAZDaThPp0iaxjS3Lr0T6mfLUQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1,

       

      其中,S型函数http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCNEAXEpQbah6W8sn7ZDeTpv582eiaFekYNxaicWMD8TYGMqg3aPpvzmIg/640?wx_fmt=png&wxfrom=5&wx_lazy=1,也成为激励函数

       

      可以看出http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC15WUZcTW6KC1pKoYlAYBqs8Amjib1dPNpFH3vjyHEe5tP9hau3ft1Pg/640?wx_fmt=png&wxfrom=5&wx_lazy=1 为3x4的矩阵,http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCib9oyw7MjBG9XFJQL4NFDyjNCEsSctPA4A0lEAQX3NwEicKDeKrtmPyw/640?wx_fmt=png&wxfrom=5&wx_lazy=1为1x4的矩阵

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCj9QWYQHOZZ7LYNUb8UwVoNO6tDVM33gVJkGbQgtHibY7wxO9xSYUAuw/640?wx_fmt=png&wxfrom=5&wx_lazy=1==》j+1的单元数x(j层的单元数+1)

       

      2、代价函数

       

      假设最后输出的http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCicQb9sZLaPWXHqiaVlMRPnIoKeqErZLImMW5X7bNeLMwxkb84geViaiaLA/640?wx_fmt=png&wxfrom=5&wx_lazy=1,即代表输出层有K个单元

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC6XZm3mRaJP4dvksnXqfv28grUwGL6aah9ZyH0d9ibRSzRiaMjVKzts1g/640?wx_fmt=png&wxfrom=5&wx_lazy=1,

       

       其中,http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCrzRFwdgC9eCJfW8uZpmea6zmtosnSBE7B7clzSAUACLTiaJnn8vcXBg/640?wx_fmt=png&wxfrom=5&wx_lazy=1代表第i个单元输出与逻辑回归的代价函数

       


       

      差不多,就是累加上每个输出(共有K个输出)

       

      3、正则化

       

      L-->所有层的个数

       

      -->第l层unit的个数

       

      正则化后的代价函数为

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCJ9BbyeNnVZeT28cCOUHBJWWslibNhkUnSk3owwaFw6L3Omb1KkRhyUw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCDrMustQYAJf2bhP5Q3yVVHmPvr51OQnZFlukgG7XZd1DueCC5wlE5A/640?wx_fmt=png&wxfrom=5&wx_lazy=1共有L-1层,然后是累加对应每一层的theta矩阵,注意不包含加上偏置项对应的theta(0)

       

      正则化后的代价函数实现代码:

       

      # 代价函数

      def nnCostFunction(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):

          length = nn_params.shape[0] # theta的中长度

          # 还原theta1和theta2

          Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1)

          Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1)

          

          # np.savetxt("Theta1.csv",Theta1,delimiter=',')

          

          m = X.shape[0]

          class_y = np.zeros((m,num_labels))      # 数据的y对应0-9,需要映射为0/1的关系

          # 映射y

          for i in range(num_labels):

              class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值

           

          '''去掉theta1和theta2的第一列,因为正则化时从1开始'''    

          Theta1_colCount = Theta1.shape[1]    

          Theta1_x = Theta1[:,1:Theta1_colCount]

          Theta2_colCount = Theta2.shape[1]    

          Theta2_x = Theta2[:,1:Theta2_colCount]

          # 正则化向theta^2

          term = np.dot(np.transpose(np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1)))),np.vstack((Theta1_x.reshape(-1,1),Theta2_x.reshape(-1,1))))

          

          '''正向传播,每次需要补上一列1的偏置bias'''

          a1 = np.hstack((np.ones((m,1)),X))      

          z2 = np.dot(a1,np.transpose(Theta1))    

          a2 = sigmoid(z2)

          a2 = np.hstack((np.ones((m,1)),a2))

          z3 = np.dot(a2,np.transpose(Theta2))

          h  = sigmoid(z3)    

          '''代价'''    

          J = -(np.dot(np.transpose(class_y.reshape(-1,1)),np.log(h.reshape(-1,1)))+np.dot(np.transpose(1-class_y.reshape(-1,1)),np.log(1-h.reshape(-1,1)))-Lambda*term/2)/m   

          

          return np.ravel(J)

       

      4、反向传播BP

       

      上面正向传播可以计算得到J(θ),使用梯度下降法还需要求它的梯度

       

      BP反向传播的目的就是求代价函数的梯度

       

      假设4层的神经网络,记为-->l层第j个单元的误差

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCAX1Mwn3mv5DOgdX7tkLGThUicgbiaq6XkUjlAPjVhXjyda81o7RibCHbw/640?wx_fmt=png&wxfrom=5&wx_lazy=1《===》http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCLHnSyQ63l06YVHiaViacT2LBCKdvdOvT6Gkb3Klibly39PyvZnQzBAXEw/640?wx_fmt=png&wxfrom=5&wx_lazy=1(向量化)

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCjkAkwDZGas5L87HMVkDtxG5bTO9hVZj3fahFibWn66mibxmabMn2KJPA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCP6LQTADHHTlGSkIgLldib3a3Ku21VnFVickOxK3CsLvb5iafwUyeGtyCw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      没有http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCibDNhRaTWCOHcd9t13JTmKWF0fttkRyuzIRBclImx39kQAJW8kImBIA/640?wx_fmt=png&wxfrom=5&wx_lazy=1,因为对于输入没有误差

       

      因为S型函数http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCaoAf5Flv7G2jHuMoUt51vbY7STVRPWY8juvoBNJgz7FIVzCv1UjQgQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1的倒数为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCAFOhwgxwasuI5GS2icYibbcS1ibhwohEOdcrdJUe2bevBBc89bMqhBUIQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1,

       

      所以上面的http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCm3iaGpfYpx3Z6KqZ1TunBA9iamKydEA3c3BSFiabtMIcsJdCRan26Am1A/640?wx_fmt=png&wxfrom=5&wx_lazy=1和http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCTtcYWQ3RMibUsx2uaa0KJ4V5cVszscluAj3gyMfgrJaPOSSD8NIL2hA/640?wx_fmt=png&wxfrom=5&wx_lazy=1可以在前向传播中计算出来

       

      反向传播计算梯度的过程为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC2xx5YynqusJiblrPfwZs1SIUbzlmJuKEUpDnUw3kmkWy1thEicYmkXXw/640?wx_fmt=png&wxfrom=5&wx_lazy=1(http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCZQL5Wic9UnxfTcuNRugkTTQdgKrib3JiaqQShhzqoypOBHicgIxETO4AKQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1是大写的http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCS5Y60DfCpc7Ic7BoOZgVIa6Dce59iaOIjdD1CElGjiauNoUIsURB0BKw/640?wx_fmt=png&wxfrom=5&wx_lazy=1)

       

      for i=1-m:-

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCKoqbRA9dwxBqGlNQicyuzxu5YAHvmwNvn9awWR4bKmLXFMr1JCNtncg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      -正向传播计算http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC6txCibRibQzQgZQZrznoFic3nhv7qBSfZb8oJyJJJibuV9dTexASeicOeaQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1(l=2,3,4...L)

       

      -反向计算http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCgjAsKlcmTPvXWnNlqlQQlATFHicvfEf5GWo63uJbsxmLhVftZpzJzaA/640?wx_fmt=png&wxfrom=5&wx_lazy=1、http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC4BTA8KEhhfmsyQiaxxxJ1Wzy6eptMUDssicUD6ONAYUZKicGImpr7tJ1w/640?wx_fmt=png&wxfrom=5&wx_lazy=1...http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCoqkdNGyDibWxxlTom3txicy8ZibARwYjvQRCIFg2qIChePGecm8RQgZrA/640?wx_fmt=png&wxfrom=5&wx_lazy=1;

       

      -http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCVCiciacJA0fILIAIb2lUEp5R5IvCB4s2RaPPhIklsCibY9TputwKV7kfA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      -http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC8etBv0SM9AR9GBcpml111LFIwGWRx2iaj51rXhsCm326ShAoQib93syg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC2SSLYHvG6hZBxttrmsMNnkhJuX5Uexw3QuhTfibKFGr1vmAC3EmFuBw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      最后http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCpe4d5YOWXteT25DzwfjIrz1fpdGqwbJFfThib9iaWOtWXASSIGNArR9w/640?wx_fmt=png&wxfrom=5&wx_lazy=1,即得到代价函数的梯度

       

      实现代码:

       

      # 梯度

      def nnGradient(nn_params,input_layer_size,hidden_layer_size,num_labels,X,y,Lambda):

          length = nn_params.shape[0]

          Theta1 = nn_params[0:hidden_layer_size*(input_layer_size+1)].reshape(hidden_layer_size,input_layer_size+1)

          Theta2 = nn_params[hidden_layer_size*(input_layer_size+1):length].reshape(num_labels,hidden_layer_size+1)

          m = X.shape[0]

          class_y = np.zeros((m,num_labels))      # 数据的y对应0-9,需要映射为0/1的关系    

          # 映射y

          for i in range(num_labels):

              class_y[:,i] = np.int32(y==i).reshape(1,-1) # 注意reshape(1,-1)才可以赋值

           

          '''去掉theta1和theta2的第一列,因为正则化时从1开始'''

          Theta1_colCount = Theta1.shape[1]    

          Theta1_x = Theta1[:,1:Theta1_colCount]

          Theta2_colCount = Theta2.shape[1]    

          Theta2_x = Theta2[:,1:Theta2_colCount]

          

          Theta1_grad = np.zeros((Theta1.shape))  #第一层到第二层的权重

          Theta2_grad = np.zeros((Theta2.shape))  #第二层到第三层的权重

          

          Theta1[:,0] = 0;

          Theta2[:,0] = 0;

          '''正向传播,每次需要补上一列1的偏置bias'''

          a1 = np.hstack((np.ones((m,1)),X))

          z2 = np.dot(a1,np.transpose(Theta1))

          a2 = sigmoid(z2)

          a2 = np.hstack((np.ones((m,1)),a2))

          z3 = np.dot(a2,np.transpose(Theta2))

          h  = sigmoid(z3)

          

          '''反向传播,delta为误差,'''

          delta3 = np.zeros((m,num_labels))

          delta2 = np.zeros((m,hidden_layer_size))

          for i in range(m):

              delta3[i,:] = h[i,:]-class_y[i,:]

              Theta2_grad = Theta2_grad+np.dot(np.transpose(delta3[i,:].reshape(1,-1)),a2[i,:].reshape(1,-1))

              delta2[i,:] = np.dot(delta3[i,:].reshape(1,-1),Theta2_x)*sigmoidGradient(z2[i,:])

              Theta1_grad = Theta1_grad+np.dot(np.transpose(delta2[i,:].reshape(1,-1)),a1[i,:].reshape(1,-1))

          

          '''梯度'''

          grad = (np.vstack((Theta1_grad.reshape(-1,1),Theta2_grad.reshape(-1,1)))+Lambda*np.vstack((Theta1.reshape(-1,1),Theta2.reshape(-1,1))))/m

          return np.ravel(grad)

       

      5、BP可以求梯度的原因

       

      实际是利用了链式求导法则

       

      因为下一层的单元利用上一层的单元作为输入进行计算

       

      大体的推导过程如下,最终我们是想预测函数与已知的y非常接近,求均方差的梯度沿着此梯度方向可使代价函数最小化。可对照上面求梯度的过程。 

       

      https://mmbiz.qpic.cn/mmbiz_jpg/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCTmW73EmjVHuiaXo082ImGroXM0g699mLQay8OJIWKQtfPkguQhXibApA/640?wx_fmt=jpeg&wxfrom=5&wx_lazy=1

       

      求误差更详细的推导过程: 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCdToZJC2XTM1U5jibf3CwACjNTJ1I8KiaMzEwDgRCPFMRGQEn5d44DCDA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      6、梯度检查

       

      检查利用BP求的梯度是否正确

       

      利用导数的定义验证: http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCuicOZ2DIR5czqiaHAFpVhp8BGbyWPB7AZm4v5uUQv0TT0FMP5iaHj518A/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      求出来的数值梯度应该与BP求出的梯度非常接近

       

      验证BP正确后就不需要再执行验证梯度的算法了

       

      实现代码:

       

      # 检验梯度是否计算正确

      # 检验梯度是否计算正确

      def checkGradient(Lambda = 0):

          '''构造一个小型的神经网络验证,因为数值法计算梯度很浪费时间,而且验证正确后之后就不再需要验证了'''

          input_layer_size = 3

          hidden_layer_size = 5

          num_labels = 3

          m = 5

          initial_Theta1 = debugInitializeWeights(input_layer_size,hidden_layer_size); 

          initial_Theta2 = debugInitializeWeights(hidden_layer_size,num_labels)

          X = debugInitializeWeights(input_layer_size-1,m)

          y = 1+np.transpose(np.mod(np.arange(1,m+1), num_labels))# 初始化y

          

          y = y.reshape(-1,1)

          nn_params = np.vstack((initial_Theta1.reshape(-1,1),initial_Theta2.reshape(-1,1)))  #展开theta 

          '''BP求出梯度'''

          grad = nnGradient(nn_params, input_layer_size, hidden_layer_size, 

                           num_labels, X, y, Lambda)  

          '''使用数值法计算梯度'''

          num_grad = np.zeros((nn_params.shape[0]))

          step = np.zeros((nn_params.shape[0]))

          e = 1e-4

          for i in range(nn_params.shape[0]):

              step[i] = e

              loss1 = nnCostFunction(nn_params-step.reshape(-1,1), input_layer_size, hidden_layer_size, 

                                    num_labels, X, y, 

                                    Lambda)

              loss2 = nnCostFunction(nn_params+step.reshape(-1,1), input_layer_size, hidden_layer_size, 

                                    num_labels, X, y, 

                                    Lambda)

              num_grad[i] = (loss2-loss1)/(2*e)

              step[i]=0

          # 显示两列比较

          res = np.hstack((num_grad.reshape(-1,1),grad.reshape(-1,1)))

          print res

       

      7、权重的随机初始化

       

      神经网络不能像逻辑回归那样初始化theta为0,因为若是每条边的权重都为0,每个神经元都是相同的输出,在反向传播中也会得到同样的梯度,最终只会预测一种结果。

       

      所以应该初始化为接近0的数

       

      实现代码

       

      # 随机初始化权重theta

      def randInitializeWeights(L_in,L_out):

          W = np.zeros((L_out,1+L_in))    # 对应theta的权重

          epsilon_init = (6.0/(L_out+L_in))**0.5

          W = np.random.rand(L_out,1+L_in)*2*epsilon_init-epsilon_init # np.random.rand(L_out,1+L_in)产生L_out*(1+L_in)大小的随机矩阵

          return W

       

      8、预测

       

      正向传播预测结果

       

      实现代码

       

      # 预测

      def predict(Theta1,Theta2,X):

          m = X.shape[0]

          num_labels = Theta2.shape[0]

          #p = np.zeros((m,1))

          '''正向传播,预测结果'''

          X = np.hstack((np.ones((m,1)),X))

          h1 = sigmoid(np.dot(X,np.transpose(Theta1)))

          h1 = np.hstack((np.ones((m,1)),h1))

          h2 = sigmoid(np.dot(h1,np.transpose(Theta2)))

          

          '''

          返回h中每一行最大值所在的列号

          - np.max(h, axis=1)返回h中每一行的最大值(是某个数字的最大概率)

          - 最后where找到的最大概率所在的列号(列号即是对应的数字)

          '''

          #np.savetxt("h2.csv",h2,delimiter=',')

          p = np.array(np.where(h2[0,:] == np.max(h2, axis=1)[0]))  

          for i in np.arange(1, m):

              t = np.array(np.where(h2[i,:] == np.max(h2, axis=1)[i]))

              p = np.vstack((p,t))

          return p 

       

      9、输出结果

       

      梯度检查:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVClGjKMBJsZm5ibydUNJBO7hgsIUpiamiaYCPjNJHR0FnCvqs0cscgRF7kg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      随机显示100个手写数字

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCvMfOMu3m9rRW8XgZicibySHGLEb1icHu00diaqhxFOwfibwx9mEfLmZaEdQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      显示theta1权重

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCJRqwlQqznyH3MuHx3NouXMjgLgOpc68BoYVK7GGqwZ4StqpBjzn4lg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      训练集预测准确度

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVChA7zrG6ibvlyjzECyGEkmqP66UOeDQmfTIibJvbdQof3lV8FYUah93kg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

      归一化后训练集预测准确度

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCct4N8t5wfeS5bYmcv2PZPgyH3ofVOxBlnJ2TTssfuGdGzzXdzOS3NA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

       

      四、SVM支持向量机

       

      1、代价函数

       

      在逻辑回归中,我们的代价为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCEJ2wl8vCGBJMU75fUFRicw0SuDyLy1yO6nbzbwl3AoGBdKkV7j27r2w/640?wx_fmt=png&wxfrom=5&wx_lazy=1,

       

      其中:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCaJMBMuk66xicfDB54Rib5icmq3rLLtQVC5QY5XcP7DPs5M1JGzy5XgFGA/640?wx_fmt=png&wxfrom=5&wx_lazy=1,http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCibgeLhBJ388hbJxg5QwH8ibCFXl2C5wibnkXsUXC741aqgiaQyQptVhEQg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      如图所示,如果y=1,cost代价函数如图所示

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCFn5DPuFWiaYGnb7WEmgwr8eLScSTicfHU81o6HicstocGMN8HLCV4S8Wg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      我们想让http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCBfQnWRu7dlqXkia4pfFnXYXyeMPw1ssHicTvQShByibP6Pw5l1Weo53iaQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1,即z>>0,这样的话cost代价函数才会趋于最小(这是我们想要的),所以用途中红色的函数http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCicRKMXAnbicXiaYWNJ0JCoLlXoWLzhR4BG3uO63MmjHYDcq9C9G4Y4Hicw/640?wx_fmt=png&wxfrom=5&wx_lazy=1代替逻辑回归中的cost

       

      当y=0时同样,用http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCicQ56cJtvr76q64ZUWfrs8TiczMyu22tvNHFRQhBSichnEP60yZcbM7icQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1代替 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCcreZAEwYxNq818YchrczhpcwNNADfEibV85nL6Iic4vUuE0adP12DBlw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      最终得到的代价函数为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCHYFFj7xSNYnb8QwTjOPZjveu8m01EjlGBTMmUrq9ymIP99rJ8TJZpQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      最后我们想要http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCEx07jRy4BVSTIN1lFIlibtoknA0qwQlGl3LuAoE1aIf40CxogGKibSWA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      之前我们逻辑回归中的代价函数为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCiaicc23WiaQdicoeOjLVtwD4quJSj9TZpskM55PJRibwXGLwsOIs3TNozCw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      可以认为这里的http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCXicXNcibwGhSfh0Mlgs9WzZ2znyeq6SAC0VsSgtdR3XYDWzfmzRLyyFA/640?wx_fmt=png&wxfrom=5&wx_lazy=1,只是表达形式问题,这里C的值越大,SVM的决策边界的margin也越大,下面会说明

       

      2、Large Margin

       

      如下图所示,SVM分类会使用最大的margin将其分开

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCq4QEk66fILTVwQar3eREAw8VxMzccgbScibatKZDmE5vEdOF9iaTNnlw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      先说一下向量内积

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC9frHcBic3guXW3aIEOarAF11Ypx9E9uVVzMQUQGnbktCMgWMUZFsGzg/640?wx_fmt=png&wxfrom=5&wx_lazy=1,http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCHib0xqemks5I8DQaRESiauOI4D41aYnBElrGicrOYkVLkEKv5AbDxIXJw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCyckgYuxpSm6yW3EB4YnSn8Libh2ptBjmRQEEhEibP8Xxygfk6S5icIdYQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1表示u的欧几里得范数(欧式范数),http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCeTeibicWiaFawNjD2usErLR5nZfm7uyQYaqzh2A0og0Q6fSRUCrnORbCw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      向量V在向量u上的投影的长度记为p,则:向量内积:

       


       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCwVSR9yFjic9k8eC7y7ib7SLGFbe4QP0XIvkG3I5kItMZvBj6e8nH3cXw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      根据向量夹角公式推导一下即可,http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCZiapzPIgLicXZQ6GoHLWnIqjSqMficibDek7wOotVOF5cRjS1YKhp7TKibg/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      前面说过,当C越大时,margin也就越大,我们的目的是最小化代价函数J(θ),当margin最大时,C的乘积项

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCcCe0b1rqk8XK78C2myLfXcd2nD9iccCXZt9kh34MrwQeXL3HEB1qia8Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      要很小,所以近似为:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCeGK3cwLw9LLE4P6Bgb83YNjUOnSW2lbkNI4KBI03cJlnCHo0PiciabicA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,

       

      我们最后的目的就是求使代价最小的θ

       

      由

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVClbnv43dVBchnVmPticoicALYzaholnFichkdLoQPOhAL3cUdcNLibAWgJg/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      可以得到:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCzsSN6m7af0KTnwQJcZPqUekunS6wriahgt6Hg8uVWyzcPw3OTaVBYlQ/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,

       

      p即为x在θ上的投影

       

      如下图所示,假设决策边界如图,找其中的一个点,到θ上的投影为p,则http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCIpCfWRmI0IIpeBmZeWErK0acgQGYZ4lMibmxFVH8w8MfP7qNM9NoWOw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1或者http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCQ23eOuZU1VjFFTEG6scBmOjbkgNLegLg9vIteibxpHibpXKYheuHtiaYQ/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,若是p很小,则需要http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCAfy2MVDjia0HFlJ1xqLrrxib8FVrJibvbs0E2EriaYPuocpniaBtEJo2dLg/640?wx_fmt=png&wxfrom=5&wx_lazy=1很大,这与我们要求的θ使http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCJMKylAqVuib6llu8qcGwWdpOLiasMwrXjmp794CKWDFF4EFh9aodzwvQ/640?wx_fmt=gif&wxfrom=5&wx_lazy=1最小相违背,所以最后求的是large margin

       

      http://mmsns.qpic.cn/mmsns/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC4lnVrWHyE3WaL9ZibdD6icYA/0?wx_lazy=1

       

      3、SVM Kernel(核函数)

       

      对于线性可分的问题,使用线性核函数即可

       

      对于线性不可分的问题,在逻辑回归中,我们是将feature映射为使用多项式的形式http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCzINtYJzYAyHkicvpsreIAMic5UK1xcHjUf08GgzULoVYkWm8triacsvvg/640?wx_fmt=png&wxfrom=5&wx_lazy=1,SVM中也有多项式核函数,但是更常用的是高斯核函数,也称为RBF核

       

      高斯核函数为:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCfV5IyeUTjqdLwU1KE5OWloZnAUWbf39AvManS0tVfAVoVXWtlrHqtA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      假设如图几个点, 

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC2LlwnhXRblRMhQnIOsHTlw6aQytrhpUKSNpIQ1DmcML0jq8tuae1ibg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       令:

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCAcB21jMa6CuWrhhMVetD5Ijhic4YxL5flnrMJVQjpcMV8Fx5Mib3fFhg/640?wx_fmt=png&wxfrom=5&wx_lazy=1,http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCuiaSark6fjdNgmfpuKnhDwZVK002dXNxiaB7e4WWbKGicjmScW1diaIxPw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       . . .

       

      可以看出,若是x与http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCkLgVakykAK6d3xtT55mViaFQiaaJOWXibQEwiaQecEQxPEZfgUqYkTCXzg/640?wx_fmt=png&wxfrom=5&wx_lazy=1距离较近,==》http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCmMu1IUibMWEiaCILEuriaaUOfqniaJicrfz8PFfSzq52KP9iaA0IOYlghz9g/640?wx_fmt=png&wxfrom=5&wx_lazy=1,(即相似度较大),若是x与http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCkLgVakykAK6d3xtT55mViaFQiaaJOWXibQEwiaQecEQxPEZfgUqYkTCXzg/640?wx_fmt=png&wxfrom=5&wx_lazy=1距离较远,==》http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCYA7q0d8wibuqficTm4EltUjtmIfxMjq6oWZDImibNycce36kib6mphuibTw/640?wx_fmt=png&wxfrom=5&wx_lazy=1,(即相似度较低)

       

      高斯核函数的σ越小,f下降的越快

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCzianoOr5zBI1SRt2ud1vX8oRfvk0jJbEicVqiaMgINVhGTJxETJmkbibIA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      如何选择初始的http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCuR4UTneAjhQnl1DMhWJdBobziaCQdT2drakXEBFJumh7o6RqC0u10Ww/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      训练集:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCDcrDZ84FpbI6ib0CcY87DrW4PjxQG7eiabcLHSWkiabrcTA4YgExBwPoA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      选择:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCunzCKZqZOBVtxx4TCnc0j26AtDnfXIQv36a4OiaWcFtMgm3GLbUlVdQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      对于给出的x,计算f,令:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCyx7ojicbLQkDd3vicj2N6GLiboJnCztd6zSfXfG50D0pXysXoZbjAj0hA/640?wx_fmt=png&wxfrom=5&wx_lazy=1,

       

      所以:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC2CeicsFGJn2AFHcdoZzNVzpLTjhuhrGvderePRVtC1oQKZ4fibhGEkkg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      最小化J求出θ,

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCiaiaF9AnAqib7ibTpG61ouvlS0nOA2icbVYCjA6OPBK3QTVSA4r1C6hoqmg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      如果http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCbEmF0QSkZbN0B9CNbiczlIV4gSPerCY6yickWPcPGicbDUfDr9YATfZoQ/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,==》预测y=1

       

      4、使用scikit-learn中的SVM模型代码

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/SVM/SVM_scikit-learn.py

       

      线性可分的,指定核函数为linear:

       

      '''data1——线性分类'''

      data1 = spio.loadmat('data1.mat')

      X = data1['X']

      y = data1['y']

      y = np.ravel(y)

      plot_data(X,y)

          

      model = svm.SVC(C=1.0,kernel='linear').fit(X,y) # 指定核函数为线性核函数

       

      非线性可分的,默认核函数为rbf

       

      '''data2——非线性分类'''

      data2 = spio.loadmat('data2.mat')

      X = data2['X']

      y = data2['y']

      y = np.ravel(y)

      plt = plot_data(X,y)

      plt.show()

          

      model = svm.SVC(gamma=100).fit(X,y)     # gamma为核函数的系数,值越大拟合的越好

       

      5、运行结果

       

      线性可分的决策边界:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC9xWcT3WEO97hgWwWNdOZb20sNaFyP8uWJPEeyR4gEMibicicLicQs8K2ag/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      线性不可分的决策边界:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCVkspKTaMSN57APNdacXicr0vNuo7s9hibFcmh8B5UJfHF2ydtTjQa3cw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

       

      五、K-Means聚类算法

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/K-Means/K-Menas.py

       

      1、聚类过程

       

      聚类属于无监督学习,不知道y的标记分为K类

       

      K-Means算法分为两个步骤

       

      第一步:簇分配,随机选K个点作为中心,计算到这K个点的距离,分为K个簇

       

      第二步:移动聚类中心:重新计算每个簇的中心,移动中心,重复以上步骤。

       

      如下图所示:

       

      随机分配的聚类中心

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC4GP5qasfloywx0pQerl4Dk34FFLzpJ0I61fR7jllEIW7VNnGrOiba8g/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      重新计算聚类中心,移动一次

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCiaagS6234HWyeJ2Sdic9gNu2iaicVFu19ebvXUpXEGckFhclPyVmp65Wqg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      最后10步之后的聚类中心

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCmXnKASiaTDDIJOj3ffElCJtJmUOHGIxtduMdB9WcCeQ2IyZ1A8d4z3g/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      计算每条数据到哪个中心最近实现代码:

       

      # 找到每条数据距离哪个类中心最近    

      def findClosestCentroids(X,initial_centroids):

          m = X.shape[0]                  # 数据条数

          K = initial_centroids.shape[0]  # 类的总数

          dis = np.zeros((m,K))           # 存储计算每个点分别到K个类的距离

          idx = np.zeros((m,1))           # 要返回的每条数据属于哪个类

          

          '''计算每个点到每个类中心的距离'''

          for i in range(m):

              for j in range(K):

                  dis[i,j] = np.dot((X[i,:]-initial_centroids[j,:]).reshape(1,-1),(X[i,:]-initial_centroids[j,:]).reshape(-1,1))

          

          '''返回dis每一行的最小值对应的列号,即为对应的类别

          - np.min(dis, axis=1)返回每一行的最小值

          - np.where(dis == np.min(dis, axis=1).reshape(-1,1)) 返回对应最小值的坐标

           - 注意:可能最小值对应的坐标有多个,where都会找出来,所以返回时返回前m个需要的即可(因为对于多个最小值,属于哪个类别都可以)

          '''  

          dummy,idx = np.where(dis == np.min(dis, axis=1).reshape(-1,1))

          return idx[0:dis.shape[0]]  # 注意截取一下

       

      计算类中心实现代码:

       

      # 计算类中心

      def computerCentroids(X,idx,K):

          n = X.shape[1]

          centroids = np.zeros((K,n))

          for i in range(K):

              centroids[i,:] = np.mean(X[np.ravel(idx==i),:], axis=0).reshape(1,-1)   # 索引要是一维的,axis=0为每一列,idx==i一次找出属于哪一类的,然后计算均值

          return centroids

       

      2、目标函数

       

      也叫做失真代价函数

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCLmCeTl6ZkWicVib72fa640BZgpiaZBNsW3MlJIAiaHp2HFrMsLurzCsY3w/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      最后我们想得到:https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCs9ShUQ39uTxNspxgYyd53MicD7zspsoCSHJSGk8g9vMpFgzU5VQichMA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      其中http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC4cd71hA7aqnO5wj8FhKQ7VjicnvNbydjG3lz1suZpMiaSAZjWJAUNPTA/640?wx_fmt=png&wxfrom=5&wx_lazy=1表示第i条数据距离哪个类中心最近,其中http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCtweBRRxVXWYTXCLXtR7UMvAPwLO8kDiaSQZo32qYKhJM1yVvfxc7N2Q/640?wx_fmt=png&wxfrom=5&wx_lazy=1即为聚类的中心

       

      3、聚类中心的选择

       

      随机初始化,从给定的数据中随机抽取K个作为聚类中心

       

      随机一次的结果可能不好,可以随机多次,最后取使代价函数最小的作为中心

       

      实现代码:(这里随机一次)

       

      # 初始化类中心--随机取K个点作为聚类中心

      def kMeansInitCentroids(X,K):

          m = X.shape[0]

          m_arr = np.arange(0,m)      # 生成0-m-1

          centroids = np.zeros((K,X.shape[1]))

          np.random.shuffle(m_arr)    # 打乱m_arr顺序    

          rand_indices = m_arr[:K]    # 取前K个

          centroids = X[rand_indices,:]

          return centroids

       

      4、聚类个数K的选择

       

      聚类是不知道y的label的,所以不知道真正的聚类个数

       

      肘部法则(Elbow method)

       

      作代价函数J和K的图,若是出现一个拐点,如下图所示,K就取拐点处的值,下图此时K=3 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCBCk5eakBoHpydk246KV1LDDYbUAibOvQuqOyPpy9c3icJAVtkibcUuIrg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      若是很平滑就不明确,人为选择。

       

      第二种就是人为观察选择

       

      5、应用——图片压缩

       

      将图片的像素分为若干类,然后用这个类代替原来的像素值

       

      执行聚类的算法代码:

       

      # 聚类算法

      def runKMeans(X,initial_centroids,max_iters,plot_process):

          m,n = X.shape                   # 数据条数和维度

          K = initial_centroids.shape[0]  # 类数

          centroids = initial_centroids   # 记录当前类中心

          previous_centroids = centroids  # 记录上一次类中心

          idx = np.zeros((m,1))           # 每条数据属于哪个类

          

          for i in range(max_iters):      # 迭代次数

              print u'迭代计算次数:%d'%(i+1)

              idx = findClosestCentroids(X, centroids)

              if plot_process:    # 如果绘制图像

                  plt = plotProcessKMeans(X,centroids,previous_centroids) # 画聚类中心的移动过程

                  previous_centroids = centroids  # 重置

              centroids = computerCentroids(X, idx, K)    # 重新计算类中心

          if plot_process:    # 显示最终的绘制结果

              plt.show()

          return centroids,idx    # 返回聚类中心和数据属于哪个类

       

      6、使用scikit-learn库中的线性模型实现聚类

      https://github.com/lawlite19/MachineLearning_Python/blob/master/K-Means/K-Means_scikit-learn.py

       

      导入包

      from sklearn.cluster import KMeans 

       

      使用模型拟合数据

      model = KMeans(n_clusters=3).fit(X) # n_clusters指定3类,拟合数据 

       

      聚类中心

      centroids = model.cluster_centers_  # 聚类中心 

       

      7、运行结果

       

      二维数据类中心的移动

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCsWXSZ26035xjqHpRVFibgpib0IUxDXZI6NicSUydoccSoWy7b6vYAbVWQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      图片压缩

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCQibhklxibOe3hemhVJ4k3edhk1dLbibalemUnIKdJh8e6LIia4XwiahVYww/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

       

      六、PCA主成分分析(降维)

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/PCA/PCA.py

       

      1、用处

       

      数据压缩(Data Compression),使程序运行更快

       

      可视化数据,例如3D-->2D等

      ......

       

      2、2D-->1D,nD-->kD

       

      如下图所示,所有数据点可以投影到一条直线,是投影距离的平方和(投影误差)最小 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCqAzNPCian1CT2YO90FbdU4KbRcXv3FSicJErBh0ZVBWpSuxC68ibsx8Zg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      注意数据需要归一化处理

       

      思路是找1个向量u,所有数据投影到上面使投影距离最小

       

      那么nD-->kD就是找k个向量http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCww1rlbQV8DcAhngwpQs5YggPiaqjtn5A34C6767p95ibjtJavLLKdnMA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,

       

      所有数据投影到上面使投影误差最小

       

      eg:3D-->2D,2个向量http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC2ajTqMlIE0n16709a2Q7Wddoa1KiaVprxYosgqFPZLE7X8NEmPlm7kw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      就代表一个平面了,所有点投影到这个平面的投影误差最小即可

       

      3、主成分分析PCA与线性回归的区别

       

      线性回归是找x与y的关系,然后用于预测y

       

      PCA是找一个投影面,最小化data到这个投影面的投影误差

       

      4、PCA降维过程

       

      数据预处理(均值归一化)

       

      公式:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC9Gbe9FWxjX7D3d5LcsCmooI2g0wbsbj3GGibgzIQ2bMEgianPhbnB5Ww/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      就是减去对应feature的均值,然后除以对应特征的标准差(也可以是最大值-最小值)

       

      实现代码:

       

      # 归一化数据

         def featureNormalize(X):

             '''(每一个数据-当前列的均值)/当前列的标准差'''

             n = X.shape[1]

             mu = np.zeros((1,n));

             sigma = np.zeros((1,n))

             

             mu = np.mean(X,axis=0)

             sigma = np.std(X,axis=0)

             for i in range(n):

                 X[:,i] = (X[:,i]-mu[i])/sigma[i]

             return X,mu,sigma

       

      计算协方差矩阵Σ(Covariance Matrix):

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCmbjp3RgwszibPkWsibaFTMwyGwwSKK5edj12qfempbXb94vE5Qux5SGg/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      注意这里的Σ和求和符号不同

       

      协方差矩阵对称正定(不理解正定的看看线代)

       

      大小为nxn,n为feature的维度

       

      实现代码:

      Sigma = np.dot(np.transpose(X_norm),X_norm)/m  # 求Sigma 

       

      计算Σ的特征值和特征向量

       

      可以是用svd奇异值分解函数:U,S,V = svd(Σ)

       

      返回的是与Σ同样大小的对角阵S(由Σ的特征值组成)[注意:matlab中函数返回的是对角阵,在python中返回的是一个向量,节省空间]

       

      还有两个酉矩阵U和V,且http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCdOjhBYMucag8NiaKtZDCcEU8eluljFZIR38g1MLRHKWfwH4DzDJyicaw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC8R1KeddhVrib2IfdzWTE4agQrlyhR5UGkK2p7IBxxZuwxFPdH6B3Nlg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      注意:svd函数求出的S是按特征值降序排列的,若不是使用svd,需要按特征值大小重新排列U

       

      降维

       

      选取U中的前K列(假设要降为K维)

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCd7ALof4jeVDsG8icfAJWF1CjJcbwHhTHkhib7VxW22AuP4xVM80oo4Iw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      Z就是对应降维之后的数据

       

      实现代码:

       

      # 映射数据

         def projectData(X_norm,U,K):

             Z = np.zeros((X_norm.shape[0],K))

             

             U_reduce = U[:,0:K]          # 取前K个

             Z = np.dot(X_norm,U_reduce) 

             return Z

       

      过程总结:

      Sigma = X'*X/m

      U,S,V = svd(Sigma)

      Ureduce = U[:,0:k]

      Z = Ureduce'*x

       

      5、数据恢复

       

      因为:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC8e69jfDsjmlanA6qGLnK9YAhnia6Qu0g7YHkUFnLX8OaicG31zf5fiaAw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,

       

      所以:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCQWtrjQ3WGd7Q9q1uwGA3ia7jmx5KeY5wP29kT7mfyLl2ZCU2mKoHic5w/640?wx_fmt=gif&wxfrom=5&wx_lazy=1 (注意这里是X的近似值)

       

      又因为Ureduce为正定矩阵,【正定矩阵满足:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC4EAdjV7A0zoSWzYWRwpDFcemJccFJLPiaaktIDua514EuTOfp2dUia0g/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,所以:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC5D2J2osGLrFTUFmPiaiaIk5DG1IzX0vD18ornibIiaux9mbFatKNnjKygQ/640?wx_fmt=gif&wxfrom=5&wx_lazy=1】,

       

      所以这里:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCMDGOb8M2TzZaKm84PnrX6KdOSDDQQRslYf5am3N5jO2nfMP34jZumw/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      实现代码:

      # 恢复数据 

          def recoverData(Z,U,K):

              X_rec = np.zeros((Z.shape[0],U.shape[0]))

              U_recude = U[:,0:K]

              X_rec = np.dot(Z,np.transpose(U_recude))  # 还原数据(近似)

              return X_rec

       

      6、主成分个数的选择(即要降的维度)

       

      如何选择

       

      投影误差(project error):http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCcg88YCgicibtxw0Paj4CEIYaB9eib78ayfd7jxooWuQyIw9odicObFOgBQ/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      总变差(total variation):http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC6fQoiavCIp6MFKic3VxQ8BjSlWnxTGJC3Mt4CgnqyYKOz8ibPzdDQwyVg/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      若误差率(error ratio):http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCC8j1sPp9KJGmwvxy4C3BcxLaqzeq6EjhJqyLdQtst6xrqZeGzMQUvA/640?wx_fmt=gif&wxfrom=5&wx_lazy=1,则称99%保留差异性

       

      误差率一般取1%,5%,10%等

       

      如何实现

       

      若是一个个试的话代价太大

       

      之前U,S,V = svd(Sigma),我们得到了S,这里误差率error ratio:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCPuaXppSibo6y1XLDic9KILFsadgUgXyXl380Ir7prXRqtw4xtMjI3c2g/640?wx_fmt=gif&wxfrom=5&wx_lazy=1

       

      可以一点点增加K尝试。

       

      7、使用建议

       

      不要使用PCA去解决过拟合问题Overfitting,还是使用正则化的方法(如果保留了很高的差异性还是可以的)

       

      只有在原数据上有好的结果,但是运行很慢,才考虑使用PCA

       

      8、运行结果

       

      2维数据降为1维

       

      要投影的方向

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCcv9TcgvlYicEFB5xWnE6Plibfe221RqbgyJD6jaNtQKQ5vkmjVvhTpxw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      2D降为1D及对应关系

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCVacpct3BfXUFyWFs87ibG4ia1DltUZuzVKG3LNevH3L39csK42KInytQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      人脸数据降维

       

      原始数据

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCpcXibZ7LMic3P528bohSo3KV5T42aKy1Pshl2RoJpSq7LloP2k5F3ic7w/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      可视化部分U矩阵信息

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCkU12k4ibSNP0FsEmI37UPXuTQhMiciasPzjYlRHw65eYAY8XRS6wgficeA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      恢复数据

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCUsJgIPEkLaGUnH6tZEyQC894TkY0CM8fNVuFsOlziahvs9TpZA18Q8A/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      9、使用scikit-learn库中的PCA实现降维

      https://github.com/lawlite19/MachineLearning_Python/blob/master/PCA/PCA.py_scikit-learn.py

       

      导入需要的包:

       

      #-*- coding: utf-8 -*-

      # Author:bob

      # Date:2016.12.22

      import numpy as np

      from matplotlib import pyplot as plt

      from scipy import io as spio

      from sklearn.decomposition import pca

      from sklearn.preprocessing import StandardScaler

       

      归一化数据

      '''归一化数据并作图'''     

      scaler = StandardScaler()     

      scaler.fit(X)    

       x_train = scaler.transform(X) 

       

      使用PCA模型拟合数据,并降维

       

      n_components对应要将的维度

      '''拟合数据'''

      K=1 # 要降的维度

      model = pca.PCA(n_components=K).fit(x_train)   # 拟合数据,n_components定义要降的维度

      Z = model.transform(x_train)    # transform就会执行降维操作

       

      数据恢复

       

      model.components_会得到降维使用的U矩阵

       

       '''数据恢复并作图'''     

      Ureduce = model.components_     # 得到降维用的Ureduce     

      x_rec = np.dot(Z,Ureduce)       # 数据恢复 

       

       

      七、异常检测 Anomaly Detection

       

      全部代码

      https://github.com/lawlite19/MachineLearning_Python/blob/master/AnomalyDetection/AnomalyDetection.py

       

      1、高斯分布(正态分布)Gaussian distribution

       

      分布函数:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCNdpkJ5uE1iaRaS11mA20EdRQtj3WyY6lW1g6ia8MqNFJzXC37K0bGd6g/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      其中,u为数据的均值,σ为数据的标准差

       

      σ越小,对应的图像越尖

       

      参数估计(parameter estimation)

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCdickR5AFib6AjN9FobxVFOFibnPWEsbYCBM6WJ0Jf3xgZn0iclunwbFMcw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCl7mqrhgFINPiaocROwauViaG0uLVUsTv77c5avQLSlEd0YPLY7APmFtA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      2、异常检测算法

       

      例子

       

      训练集:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCuDscVnlicd0Jgm0v81f65v20Ty8cwN3dlvUic3zVBFc05WHV8ZcZkxuQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1,其中http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCvkLJeDsejTeYEg2icfNnQ69QKV4Nw0wib8DMaxG6Prj75kdOMTuu949A/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      假设http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCqRk2t7FpKicxicnFXa3Ex7tsEzA10ic6KE7a9H4YMU8Y9asFkjVZmrgJw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      相互独立,建立model模型:

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCQV3CF5MkaShPOI2cPgCthUFN1EiajT0qUMksuqOlXm0GDahuG4ZrBpw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

      过程

       

      选择具有代表异常的feature:xi

       

      参数估计:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC6VfZuxlTsbcPeLOmyiahKbbMHTPBAgDr19ynv9TG3iatdL9RibgubxEkg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      计算p(x),若是P(x)<ε则认为异常,其中ε为我们要求的概率的临界值threshold

      这里只是单元高斯分布,假设了feature之间是独立的,下面会讲到多元高斯分布,会自动捕捉到feature之间的关系

       

      参数估计实现代码

       

      # 参数估计函数(就是求均值和方差)

      def estimateGaussian(X):

          m,n = X.shape

          mu = np.zeros((n,1))

          sigma2 = np.zeros((n,1))

          

          mu = np.mean(X, axis=0) # axis=0表示列,每列的均值

          sigma2 = np.var(X,axis=0) # 求每列的方差

          return mu,sigma2

       

      3、评价p(x)的好坏,以及ε的选取

       

      对偏斜数据的错误度量

       

      因为数据可能是非常偏斜的(就是y=1的个数非常少,(y=1表示异常)),所以可以使用Precision/Recall,计算F1Score(在CV交叉验证集上)

       

      例如:预测癌症,假设模型可以得到99%能够预测正确,1%的错误率,但是实际癌症的概率很小,只有0.5%,那么我们始终预测没有癌症y=0反而可以得到更小的错误率。使用error rate来评估就不科学了。

       

      如下图记录:

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCJM64b2Yp9c2LjqlUiaY4SNmXAYY4msms1W2kTYTSwu3sBibhMicr46TrA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      ,即:正确预测正样本/所有预测正样本

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC3GwH9LQdEs3bVhUTkaicWYyDebn3R70OhOu5V3aG2HAXfP9EY316iaSg/640?wx_fmt=png&wxfrom=5&wx_lazy=1,即:正确预测正样本/真实值为正样本

       

      总是让y=1(较少的类),计算Precision和Recall

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCFTG7wnb64jKxj7qOTu03ByB6icFUQtWjYRkwL7Gka3bpYHiceXhScc7w/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      还是以癌症预测为例,假设预测都是no-cancer,TN=199,FN=1,TP=0,FP=0,所以:Precision=0/0,Recall=0/1=0,尽管accuracy=199/200=99.5%,但是不可信。

       

      ε的选取

       

      尝试多个ε值,使F1Score的值高

       

      实现代码

       

      # 选择最优的epsilon,即:使F1Score最大    

      def selectThreshold(yval,pval):

          '''初始化所需变量'''

          bestEpsilon = 0.

          bestF1 = 0.

          F1 = 0.

          step = (np.max(pval)-np.min(pval))/1000

          '''计算'''

          for epsilon in np.arange(np.min(pval),np.max(pval),step):

              cvPrecision = pval<epsilon

              tp = np.sum((cvPrecision == 1) & (yval == 1)).astype(float)  # sum求和是int型的,需要转为float

              fp = np.sum((cvPrecision == 1) & (yval == 0)).astype(float)

              fn = np.sum((cvPrecision == 1) & (yval == 0)).astype(float)

              precision = tp/(tp+fp)  # 精准度

              recision = tp/(tp+fn)   # 召回率

              F1 = (2*precision*recision)/(precision+recision)  # F1Score计算公式

              if F1 > bestF1:  # 修改最优的F1 Score

                  bestF1 = F1

                  bestEpsilon = epsilon

          return bestEpsilon,bestF1

       

      4、选择使用什么样的feature(单元高斯分布)

       

      如果一些数据不是满足高斯分布的,可以变化一下数据,例如log(x+C),x^(1/2)等

       

      如果p(x)的值无论异常与否都很大,可以尝试组合多个feature,(因为feature之间可能是有关系的)

       

      5、多元高斯分布

       

      单元高斯分布存在的问题

       

      如下图,红色的点为异常点,其他的都是正常点(比如CPU和memory的变化)

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCRhTibTMRbBibziceTibYOZdoTXKyVe7AmX5VoKJZMFU4EyxrGvWuTFGWdg/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      x1对应的高斯分布如下:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCCCQ0OK5x6vayBZAp288RljIbptUyBFV4BQZYqDZh5w0d1kYdtn2TIA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      x2对应的高斯分布如下:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCrCcdZiaKknicgsB1hVx6YH2ibaJN1KJY58VyPgqhmIOfcJVMZ31zvLibnA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      可以看出对应的p(x1)和p(x2)的值变化并不大,就不会认为异常

       

      因为我们认为feature之间是相互独立的,所以如上图是以正圆的方式扩展

       

      多元高斯分布

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCvkLJeDsejTeYEg2icfNnQ69QKV4Nw0wib8DMaxG6Prj75kdOMTuu949A/640?wx_fmt=png&wxfrom=5&wx_lazy=1,并不是建立p(x1),p(x2)...p(xn),而是统一建立p(x)

       

      其中参数:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC1yqw8fKj3oy9xrJtZ8RMhXSEick5AfFOYyicE2odn0KxklgvRBWrENPQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1,Σ为协方差矩阵

       

      http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCwhOdTiaWMOWiaWp4Y24lVwUusVDsuCNOMdCYx2EGic42Hgian0gtYp88vA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      同样,|Σ|越小,p(x)越尖

       

      例如:

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCsHJDbqicmCBe3W2pLqh7SAm8TGCP0nUBTicKgicX7JmgkoJQErk9mdoPQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1,

       

      表示x1,x2正相关,即x1越大,x2也就越大,如下图,也就可以将红色的异常点检查出了 

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCM8gTx1f2JiazUkttiah6CHPDwicoKiaxTewDz4IK5gsbQrcGmJR8WZwiceQ/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      若:

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCWhAXianFVO004uM5eUMefZibD9QFBcfLSQ0vxPRJS7CX10rjibvnvt6Qw/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      表示x1,x2负相关

       

      实现代码:

       

      # 多元高斯分布函数    

      def multivariateGaussian(X,mu,Sigma2):

          k = len(mu)

          if (Sigma2.shape[0]>1):

              Sigma2 = np.diag(Sigma2)

          '''多元高斯分布函数'''    

          X = X-mu

          argu = (2*np.pi)**(-k/2)*np.linalg.det(Sigma2)**(-0.5)

          p = argu*np.exp(-0.5*np.sum(np.dot(X,np.linalg.inv(Sigma2))*X,axis=1))  # axis表示每行

          return p

       

      6、单元和多元高斯分布特点

       

      单元高斯分布

       

      人为可以捕捉到feature之间的关系时可以使用

       

      计算量小

       

      多元高斯分布

       

      自动捕捉到相关的feature

       

      计算量大,因为:http://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCky4bhuak38ybPl2SLvibc2rKLqKMEnFqicS0QUeCcDYgsAB1UhlejibiaA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      m>n或Σ可逆时可以使用。(若不可逆,可能有冗余的x,因为线性相关,不可逆,或者就是m<n)

       

      7、程序运行结果

       

      显示数据

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCumWYpfscVaicCzsQvjnASewEscrxMJ9LwHicibEaUYG3lHlXvDH9oH4EA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      等高线

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVC5GicUWicYtAtYmguicgbUiaqKIVZmElH5eEVf9GnV5iaKdwzoibM6cDVHW6w/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

      异常点标注

       

      https://mmbiz.qpic.cn/mmbiz_png/BnSNEaficFAZLoR9uKrmH4EccllgS1SVCfpAQynr6KmCjXPkwLCSulyJsYG0sAD4wJKVvt1iccOD4DZXEbcAEIxA/640?wx_fmt=png&wxfrom=5&wx_lazy=1

       

       

      原文地址

      https://github.com/lawlite19/MachineLearning_Python#

       

       

       

来自 “ ITPUB博客 ” ,链接:https://blog.itpub.net/29829936/viewspace-2149742/ ,如需转载,请注明出处,否则将追究法律责任。

请登录后发表评论 登录
全部评论
行万里路,读万卷书,阅无数人。 吃货一枚,爱吃湘菜,粤菜与杭帮菜,尝遍天下美食。 摄影爱好者,游遍名川大山,江河胡海,赏遍人间春色。 爱看电影,尤其是国产大片,好莱坞大片。英文名:Dickson Jin, 网名:风一样的BOY。精通SAP供应链咨询。2017年开始研习人工智能。

注册时间:2014-08-27

  • 博文量
    2598
  • 访问量
    4671468