当前位置:   article > 正文

Python与数据分析_.coef_

.coef_

python基础知识

python魔法用法:a, b = b, a + b
迭代器 生成器 Iterable

# coding:utf-8

# 生成器(iterator;代表无限大数据流 迭代器是生成器,调用next计算下一个,直到异常)
# 迭代器(generator):yield 和(i for i in range(10),调用next计算下一个,直到异常)
# iterable 可迭代对象 list str 可以用for循环的都是 生成器和迭代器都是iterable但不是iterator
# 获得iterable iterator对象iter()
# list存储容量有限但是iteriator存储容量无限

from collections import Iterable,Iterator,Generator

def o():
    print(1)
    yield 1
    print(2)
    yield 2
    print(2)
    yield 3

b=(i for i in range(0,10))

print(type(o()),type(b))
print('next b',next(b))


o=o()
# for x in o:
#     print('x',x)
if(isinstance(o,Generator)):
    while (True):
        try:
            print('o',next(o))
        except StopIteration as e:
            print(e.value)
            break

print('---------------')
for n in b:
    print(n)
print('---------------')
print(isinstance(o,Iterable))
print(isinstance(o,Iterator))
print(isinstance(o,Generator))
print(isinstance(b,Iterable))
print(isinstance(b,Iterator))
print(isinstance(b,Generator))

l=[2,3]
print('l',next(iter(l)))



  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51

python函数

# coding:utf-8

def test0(a,b=1,*m ):
    print(a,b,m)


def test(a,b=1,* ,d,**kw):
    print(a,b,d)
    for i in kw:
        print(i,kw.get(i))
# 位置参数和命名关键字参数(*后边的参数,符号和位置参数一样没有*,只是前边多了个'*,')必须有,默认参数a=
# 可变参数和关键字参数(**kw:传入值可以时a='2',也可以是**{'a':'2'})可以没有,如果已经组装的数组参数传入可变参数前边加*,*[1,2,3]
# ,可变参数后边的命名关键子参数可以不用加*;必选参数、默认参数、可变参数、命名关键字参数和关键字参数
def test1(a,*s,d,**kw):
    print(a,s,d)
    for i in kw:
        print(i,kw.get(i))

if __name__=='__main__':
    test0(1)
    print('-------')
    test(1,d=9)
    print('-------')
    test(1,d=9,s='4',m='8')
    print('-------')
    test1(1,6,d='4',m='8')
    print('-------')
    test1(1,*[6,9],d='4',m='8')
    print('-------')
    test1(1, *[6, 9],d='9',**{'l':'4', 'm':'8'})
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30

使用枚举类

#  coding:utf-8

from enum import Enum,unique

Month=Enum('Month',('Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'))

for name,member in Month.__members__.items():
    print(name,member,member.value,'--')
@unique
class WeekDay(Enum):
    Sun=0
    Mon = 1
    Tue = 2
    Wed = 3
    Thu = 4
    Fri = 5
    Sat = 6

print(WeekDay.Mon,WeekDay.Mon.value)

class Gender(Enum):
    Male = 0
    Female = 1

class Student(object):
    def __init__(self, name, gender):
        self.name = name
        self.gender = gender
s=Student('menghui',Gender.Male)
# 结果
------------------------------
Jan Month.Jan 1 --
Feb Month.Feb 2 --
Mar Month.Mar 3 --
Apr Month.Apr 4 --
May Month.May 5 --
Jun Month.Jun 6 --
Jul Month.Jul 7 --
Aug Month.Aug 8 --
Sep Month.Sep 9 --
Oct Month.Oct 10 --
Nov Month.Nov 11 --
Dec Month.Dec 12 --
WeekDay.Mon 1
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

面向对象:类的属性

# coding :utf-8

class Student(object):
    __slots__ = ('_Student__name','age','sex','score','hobby') # 限制必须只有几种属性

    country='China' #类属性,所有实例都可以访问
    def __init__(self,value): # 初始化变量必须有的值 __name是私有变量
        self.__name=value

    def get_name(self):
        return  self.__name

    def set_sex(self, value):
        self.sex = value
    @property
    def sscore(self):
        return self._score
    @sscore.setter
    def sscore(self,value):
        self._score= value
    pass

# 给类增加函数
def set_age(self,value):
    self.age=value



s=Student('menghui')
Student.set_age=set_age
#s.name='menghui'
s.hobby='basketball'  # 外部变量可以随便更改hobby变量

class Screen(object):
   # __slots__ = ('width','height','resolutio')

    @property
    def width(self):
        return self._width
    @width.setter
    def width(self,value):
        self._width=value

    @property
    def height(self):
        return self._height

    @height.setter
    def height(self,value):
        self._height=value

    @property
    def resolution(self):
        return  self.width*self.height
    pass


if __name__=='__main__':
    s.set_age(5)
    s.set_sex('male') # 不用
    s.score=89

    print(s.country,Student.country,s.age,s.get_name(),s._Student__name,s.sex,s.score,s.hobby)

    print('---------')
    # 测试:
    s = Screen()
    s.width = 1024
    s.height = 768
    print('resolution =', s.resolution)
    if s.resolution == 786432:
        print('测试通过!')
    else:
        print('测试失败!')
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

获取对象信息 type() isinstanceof(a,int)
面向对象的继承和多态,支持多继承class(object,Animal,Fly)

# coding:utf-8

class Animal(object):
    def run(self):
        print('animal ran')
    pass


class Cat(Animal):
    def run(self):
        print('cat ran')
    pass



class Dog(Animal):
    def run(self):
        print('dog ran')
    pass



def runTwice(animal):
    animal.run()
    animal.run()


if __name__ == '__main__':
    dog = Dog()
    cat = Cat()
    animal = Animal()
    # 多态
    runTwice(animal)
    print('---------')
    runTwice(cat)
    print('---------')
    runTwice(dog)

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38

进行数据分析

  • 常规使用python建立一个矩阵
  1. 建立一个两行三列的矩阵
    Arr=np.array([[1,2,3],[4,5,6]])
  2. 查看矩阵的大小,几行几列
    D=np.shape(Arr)
  • 矩阵的切片
    取出矩阵的第二行,第三列
    Arr1=Arr[1:2,2:3]

  • 对矩阵进行转置运算
    ArrT=Arr.T

  • 求矩阵的内积运算
    Arr2=np.dot(Arr.T,Arr)
    或者转化成mat直接相乘,mat就是矩阵,按矩阵的性质 Arr2=np.mat(Arr.T)*np.mat(Arr)

  • 两个矩阵进行合并
    A=np.array([[1,2,3],[2,3,4]])
    B=np.array([[5,6,7]])
    C=np.r_[A,B] #增补行
    得到C
    [1,2,3],
    [2,3,4],
    [5,6,7]

      arr1 = np.array([1, 2, 3])
      arr2 = np.array([4, 5, 6])
      print 'vstack:\n',np.vstack((arr1, arr2)) #按行向量处理增补行
      print 'c_:\n',np.c_[arr1,arr2] # 按列向量处理增补列
      print 'hstack:\n', np.hstack((arr1, arr2)) # 按行向量处理增补列
      print 'r_:\n',np.r_[arr1,arr2] # 按行向量处理增补列
      a1 = np.array([[1, 2], [3, 4], [5, 6]])
      a2 = np.array([[7, 8], [9, 10], [11, 12]])
      print 'vstack:\n',np.vstack((a1, a2))
      print 'c_:\n',np.c_[a1,a2]
      print 'hstack:\n', np.hstack((a1, a2))
      print 'r_:\n',np.r_[a1,a2]
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

得到结果

	vstack:
	[[1 2 3]
	 [4 5 6]]
	c_:
	[[1 4]
	 [2 5]
	 [3 6]]
	hstack:
	[1 2 3 4 5 6]
	r_:
	[1 2 3 4 5 6]
	vstack:
	[[ 1  2]
	 [ 3  4]
	 [ 5  6]
	 [ 7  8]
	 [ 9 10]
	 [11 12]]
	c_:
	[[ 1  2  7  8]
	 [ 3  4  9 10]
	 [ 5  6 11 12]]
	hstack:
	[[ 1  2  7  8]
	 [ 3  4  9 10]
	 [ 5  6 11 12]]
	r_:
	[[ 1  2]
	 [ 3  4]
	 [ 5  6]
	 [ 7  8]
	 [ 9 10]
	 [11 12]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 在指定位置插入矩阵
    A=np.array([[1,2,3],[3,4,5],[4,7,9]])
    S=np.insert(A,1,np.array([[2,2,2]]),0)
    得到矩阵
    [1, 2, 3],
    [2, 2, 2],
    [3, 4, 5],
    [4, 7, 9]

  • 花式索引 取出矩阵C的第三列和第一列组成新矩阵
    S[np.ix_([0,1,2,3],[2,0])]
    得到
    [[3, 1],
    [2, 2],
    [5, 3],
    [9, 4]])
    m=S[[0,1],[2,0]]
    得到一维数组:0行2列和1行0列的数组
    array([3,2])
    等效于下边
    m=np.array([S[0,2],S[1,0]])
    m=array([3, 2])
    一维数组的引用m[0]
    将一维数组变成二维数组m.reshape(1,3)
    变成一行三列
    试二维数组具有表的性质

  • 类表操作

假设下边是三个学生的成绩

score=np.array([[50,60,60],[80,82,90],[70,66,78]],dtype=np.float64)  
  • 1

三个学生矩阵

name=np.array(['xiaoming','xiaohong','xiaogang'],dtype=np.str_)  
  • 1

三门科目分别是

item=np.array(['yuwen','yingyu','shuxue'],dtype=np.str_)  
  • 1

现在取出小红的成绩

score[name=='xiaohong']  
  • 1
取出小红的英文成绩

score[name==’xiaohong’,item==’yuwen’]

  • 常用矩阵操作
    print np.ones_like(data4)
    print np.zeros_like(data4)
    print np.identity(5)
    print np.eye(5,5,-1)
如果求一个矩阵倒数3个数

np.a[:-(3+1):-1]


###python绘图

最基本绘图入门操作
 #引入对应的库函数
import matplotlib.pyplot as plt
from numpy import *

#绘图
fig = plt.figure()
ax = fig.add_subplot(349)
ax.plot(x,y)
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9

#######其中,参数349的意思是:将画布分割成3行4列,图像画在从左到右从上到下的第9块,如下图:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-ETfr9tpl-1591425060264)(http://image.codeweblog.com/upload/3/d7/3d7ccf7235b66a08_thumb.jpg)]

scatter的基本用法

######参见网址:http://www.cnblogs.com/shanlizi/p/6850318.html

#导入必要的模块 
import numpy as np 
import matplotlib.pyplot as plt 
#产生测试数据 
x = np.arange(1,10) 
y = x 
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
#设置标题 
ax1.set_title('Scatter Plot') 
#设置X轴标签 
plt.xlabel('X') 
#设置Y轴标签 
plt.ylabel('Y') 
#画散点图 
ax1.scatter(x,y,c = 'r',marker = 'o') 
#设置图标 
plt.legend('x1') 
#显示所画的图 
plt.show() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

#####如果要画出高阶函数Sigmoid

#导入必要的模块 
import numpy as np 
import matplotlib.pyplot as plt
import math 
#产生测试数据 
x = np.arange(-10,10,0.01) 
y=[]
for i in x:
	y.append(1/(math.exp(-i)+1))
fig = plt.figure() 
ax1 = fig.add_subplot(111) 
#设置标题 
ax1.set_title('Scatter Plot') 
#设置X轴标签 
plt.xlabel('X') 
#设置Y轴标签 
plt.ylabel('Y') 
#画散点图 
ax1.scatter(x,y,c = 'r',marker = 'o') 
#设置图标 
plt.legend('x1') 
#显示所画的图 
plt.show() 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

另一种画出该图形的方法

import numpy as np 
import matplotlib.pyplot as plt
	
def Sigmoid(x):
	  return 1/(np.exp(-x)+1) #矩阵每一个数据都进行这样计算
x=np.arange(-10,10,0.01)
y=Sigmoid(x)
	
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(x,y,marker='o',color='red')
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

画出三维图形

import matplotlib.pyplot as plt  # 绘图用的模块
from mpl_toolkits.mplot3d import Axes3D  # 绘制3D坐标的函数
import numpy as np

def fun(x, y):
    return np.power(x, 2) + np.power(y, 2)


fig1 = plt.figure()  # 创建一个绘图对象
ax = fig1.add_subplot(111, projection='3d')  # 用这个绘图对象创建一个Axes对象(有3D坐标)
X = np.arange(-2, 2, 0.1)
Y = np.arange(-2, 2, 0.1)  # 创建了从-2到2,步长为0.1的arange对象
# 至此X,Y分别表示了取样点的横纵坐标的可能取值
# 用这两个arange对象中的可能取值一一映射去扩充为所有可能的取样点
X, Y = np.meshgrid(X, Y)
Z = -X-Y-1  # 用取样点横纵坐标去求取样点Z坐标
plt.title("This is main title")  # 总标题
ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap=plt.cm.coolwarm)  # 用取样点(x,y,z)去构建曲面
ax.set_xlabel('x label', color='r')
ax.set_ylabel('y label', color='g')
ax.set_zlabel('z label', color='b')  # 给三个坐标轴注明
plt.show()  # 显示模块中的所有绘图对象
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22

PCA降维

降低维度的算法PCA:找出最大差异性、次大差异性,方差由大到小。
决策树可以构造简单的分类器,SVM可以构造更为精确的分类器,但是不容易解释。

基本概念与定理:

线性方称组与矩阵
https://blog.csdn.net/guoziqing506/article/details/80557920

结论
  • 任何线性方程组,只要满足r(A)=r(A¯),则一定有解;否则一定无解(这是判断有无解的唯一标准)
  • 对于齐次线性方程组,如果r(A)<n,则它有非零解,且线性无关的非零解的个数为n−r(A);否则只有零解
  • 对于非齐次线性方程组,如果它的导出组有非零解(r(A)<n),则它有无穷多解,每个解都是特解和导出组基础解系的线性组合;如果它的导出组只有零解,则它有唯一解

协方差与矩阵的关系https://blog.csdn.net/capecape/article/details/79162167 https://blog.csdn.net/h2026966427/article/details/79252011 https://blog.csdn.net/qq_29750461/article/details/81625470
特征值特征向量的几何含义https://blog.csdn.net/fuming2021118535/article/details/51339881
矩阵乘法对应了一个变换,是把任意一个向量变成另一个方向或长度都大多不同的新向量。在这个变换的过程中,原向量主要发生旋转、伸缩的变化。如果矩阵对某一个向量或某些向量只发生伸缩变换,不对这些向量产生旋转的效果,那么这些向量就称为这个矩阵的特征向量,伸缩的比例就是特征值。

定义的特征值和特征向量有什么实际用途呢?在这里我举个数据挖掘算法中重要的一个算法:PCA(主成分分析),如下图:
见网址:https://img-blog.csdn.net/20160718102203538?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
如果我们单独看某一个维度的话,比如看x1这个维度:
见网址:https://img-blog.csdn.net/20160718102217210?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center
可以看到将点投影到x1这个维度上看的话,图1的数据离散性最高,图3较低,图2数据离散性是最低的。数据离散性越大,代表数据在所投影的维度上具有越高的区分度,这个区分度就是信息量。如果我们用方差来形容数据的离散性的话,就是数据方差越大,表示数据的区分度越高,也就是蕴含的信息量是越大的。

基于这个知识,如果我们想对数据进行降维的话,比如图1的两个维度的数据降成一维,我们可以选择保留X1这个维度的数据,因为在这个维度上蕴含的信息量更多。

同理,图2就可以保留x2这个维度的数据。但是,问题来了,图3应该保留哪个维度的数据呢?答案是保留哪个维度都不好,都会丢失较大的信息量。但是,如果我们把图3的坐标轴旋转一下

见网址:https://img-blog.csdn.net/20160718102232898?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

比较容易看出,图3在新的坐标轴下就能进行降维了。所以选取正确的坐标轴,然后根据各个维度上的数据方差大小
,决定保留哪些维度的数据,这样的做法就是主成分分析的核心思想。

选取正确的坐标轴的过程中,我们需要一个矩阵变换,就类似于这样:

见网址:https://img-blog.csdn.net/20160718102249680?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center

也就是:

其实,经过数学上的推导的,我们就可以知道,特征值对应的特征向量就是理想中想取得正确的坐标轴,而特征值就等于数据在旋转之后的坐标上对应维度上的方差

也就是说,直接求出矩阵A的特征向量得出对应的特征向量。我们就能找到旋转后正确的坐标轴。这个就是特征值和特征向量的一个实际应用:得出使数据在各个维度区分度达到最大的坐标轴

所以,在数据挖掘中,就会直接用协方差矩阵的特征值来描述对应特征向量方向上包含的信息量,而某一特征值除以所有特征值的和的值就为:该特征向量的方差贡献率(方差贡献率代表了该维度下蕴含的信息量的比例。)

通常经过特征向量变换下的数据被称为变量的主成分,当前m个主成分累计的方差贡献率达到一个较高的百分数(如85%以上)的话,就保留着这m个主成分的数据。实现了对数据进行降维的目的。整个主成分分析的算法原理也就是这个。


第一种经典算法:KNN算法

####### KNN算法又叫K-最近邻算法是最简单的一种分类算法,输入是数值型输出是标量型数据,优点是算法简单,缺点是算法效率低,无法解释算法结果,根据两点距离越近越相似的思想进行编写。

代码如下:

# -*- coding:UTF-8 -*-

from numpy import *
import operator
from os import listdir

# KNN算法
def classify0(inX, dataSet, labels, k):
    '''
    :param inX: 输入某个样本数据,一行输入数据(1*n)
    :param dataSet:样本数据矩阵
    :param labels:样本数据每条数据对应的标签
    :param k: k近邻算法对应的数量,一般取常数值
    :return:返回标签值最多的标签
    '''
    dataSetSize = dataSet.shape[0]  #获取样本数据的行数
    # 数组求差,相同行列数的数据对应位置求差:
    # tile是将一个数组扩展成一个 和样本数据同行数,只有一列的二维数组,详细见htlp(tile)
    diffMat = tile(inX, (dataSetSize,1)) - dataSet
    sqDiffMat = diffMat**2  #每个位置求平方
    sqDistances = sqDiffMat.sum(axis=1) #对每一行将所有列加起来求和
    distances = sqDistances**0.5  #对矩阵中每个数据开根号
    sortedDistIndicies = distances.argsort()     #argsort()函数是将x中的元素从小到大排列,提取其对应的index(索引),然后输出到y
    classCount={}          
    for i in range(k):
        voteIlabel = labels[sortedDistIndicies[i]]  #k个依次距离最近的标签值
        classCount[voteIlabel] = classCount.get(voteIlabel,0) + 1 #如果标签在字典中就返回当前标签在字典中的值,否则返回0,其实就是计数功能
        # classCount.iteritems()返回一个可以迭代的对象,将字典转化成可迭代 {'hh': 1, 'bb': 2}=》<dictionary-itemiterator object at 0x000000000AD45AE8>
        #可以理解为{'hh': 1, 'bb': 2}=》[(hh', 1),('bb',2)]用for循环可以print打印, key=operator.itemgetter(1)按第一个作用域排序即1 2,倒序
        # 见https://blog.csdn.net/dongtingzhizi/article/details/12068205
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0] #返回标签值最多的标签

# 使用KNN算法的例子
def createDataSet():
    group = array([[1.0,1.1],[1.0,1.0],[0,0],[0,0.1]]) #样本
    labels = ['A','A','B','B'] #标签值
    return group, labels
group,labels=createDataSet();
print classify0([0.0],group,labels,3)

def file2matrix(filename):
    '''
    读取文件,将文件转化为矩阵,比如txt类型的文件
    :param filename: 带有文件路径的文件名
    :return:返回矩阵 返回标签
    '''
    fr = open(filename)
    numberOfLines = len(fr.readlines())         #文件行数
    returnMat = zeros((numberOfLines,3))        #准备‘返回矩阵’
    classLabelVector = []                       #准备‘返回标签’
    fr = open(filename)
    index = 0
    for line in fr.readlines():
        line = line.strip()
        listFromLine = line.split('\t')
        returnMat[index,:] = listFromLine[0:3] #取出数组的前3个每赋值给‘返回矩阵’
        classLabelVector.append(int(listFromLine[-1])) #数组的最后一列的值赋值给‘返回标签classLabelVector’
        index += 1
    return returnMat,classLabelVector

def autoNorm(dataSet):
    '''
    数据归一化,为了消除不同维度的数据单位不一样带来的误差
    :param dataSet: 输入矩阵
    :return: normDataSet:归一化后的矩阵 ranges 矩阵范围 minVals 矩阵每列的最小值
    '''
    minVals = dataSet.min(0) # 获取每列的最小值 min(1)获取每行的最大值
    maxVals = dataSet.max(0) # 获取每列的最大值
    ranges = maxVals - minVals # 获取每列的数据范围,最大-最小组成一行
    normDataSet = zeros(shape(dataSet)) #要返回的归一化后的矩阵
    m = dataSet.shape[0] # 输入矩阵行数
    normDataSet = dataSet - tile(minVals, (m,1)) # 每一行减去最小值
    normDataSet = normDataSet/tile(ranges, (m,1))   # 然后再乘以最大值减去最小值
    return normDataSet, ranges, minVals

# 求分类器的错误率
def datingClassTest():
    hoRatio = 0.50      #hold out 10%
    datingDataMat,datingLabels = file2matrix('datingTestSet2.txt')       #load data setfrom file
    normMat, ranges, minVals = autoNorm(datingDataMat)
    m = normMat.shape[0]
    numTestVecs = int(m*hoRatio) #测试数据的数量numTestVecs
    errorCount = 0.0
    # 选择前numTestVecs的数量作为测试样本,剩下的样本为训练样本。
    for i in range(numTestVecs):
        classifierResult = classify0(normMat[i,:],normMat[numTestVecs:m,:],datingLabels[numTestVecs:m],3)
        print "the classifier came back with: %d, the real answer is: %d" % (classifierResult, datingLabels[i])
        if (classifierResult != datingLabels[i]):
            errorCount += 1.0
    print "the total error rate is: %f" % (errorCount/float(numTestVecs))
    print errorCount
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92

第二种经典算法:决策树算法

适用范围:条件因素特征和结果因素特征是标称型数据。优点:可以清晰的看出数据划分的过程 ,缺点:无法直接处理数值型数据,容易出现过度匹配问题,需要剪枝

信息增益和熵的概念:待分类的事务可能划分在多个分类之中,Xi 是一个分类,则符号分类 Xi 的 信息定义为: -log2p(xi),其中p(xi)是选择该分类的概率。
熵定义为信息的期望值

H=-\Sigma^n_{i=1}p(x_i)log_2p(x_i)
  • 1

关于熵和决策树的理解:http://www.cnblogs.com/muzixi/p/6566803.html

信息增益 = entroy(前) - entroy(后) 对于待划分的数据集D,其 entroy(前)是一定的,但是划分之后的熵 entroy(后)是不定的,entroy(后)越小说明使用此特征划分得到的子集的不确定性越小(也就是纯度越高),因此 entroy(前) - entroy(后)差异越大,信息增益越大,说明使用当前特征划分数据集D的话,其纯度上升的更快,越能快速的划分数据集。

决策树核心代码:

tree.py

'''
Decision Tree Source Code for Machine Learning in Action Ch. 3
@author: 
'''
from math import log
import operator

# 简单的测试数据集产生
def createDataSet():
    dataSet = [[1, 1, 'yes'],
               [1, 1, 'yes'],
               [1, 0, 'no'],
               [0, 1, 'no'],
               [0, 1, 'no']]
    labels = ['no surfacing','flippers']
    #change to discrete values
    return dataSet, labels

def calcShannonEnt(dataSet):
    '''
    求一个矩阵的信息熵,熵越高,信息越复杂越无序,则混合的数据也越多,我们可以在数据集中添加更多的分类
    :param dataSet:标量型矩阵,计算原始数据集的信息熵,按最后一列计算,最后一列是标签
    :return: 所有类别的信息熵
    '''
    numEntries = len(dataSet) #计算矩阵行数
    labelCounts = {} # 存放每一个标签及数量
    for featVec in dataSet: # 对于矩阵的每一行数据
        currentLabel = featVec[-1] #每一行数据的标签
        if currentLabel not in labelCounts.keys(): labelCounts[currentLabel] = 0
        labelCounts[currentLabel] += 1
    shannonEnt = 0.0
    for key in labelCounts:
        prob = float(labelCounts[key])/numEntries
        # 求期望=∑(每个类别概率*每个类别信息) log值表示这个分类对应的信息
        shannonEnt -= prob * log(prob,2)
    return shannonEnt
    
def splitDataSet(dataSet, axis, value):
    '''
    根据某一列的值来划分数据集
    :param dataSet:待划分的数据集
    :param axis: 列号,划分数据集的特征在哪一列
    :param value:某列对应值
    :return:retDataSet 去除了划分特征的那一列剩下的数据
    '''
    retDataSet = []
    for featVec in dataSet:
        if featVec[axis] == value:
            reducedFeatVec = featVec[:axis]     #chop out axis used for splitting
            reducedFeatVec.extend(featVec[axis+1:]) # extend 组成的list里边没有list,list全部展开
            retDataSet.append(reducedFeatVec) # extend 组成的list里边有list,list保持
    return retDataSet
    
def chooseBestFeatureToSplit(dataSet):
    '''
    给定一个数据集,(带有条件和结果特征的数据集合),得到最佳的分类是第几个特征,从0开始
    :param dataSet:最后一列是结果特征,前几列是条件列特征,其他列是标量型的数据,数据集都是标量型
    :return:
    '''
    numFeatures = len(dataSet[0]) - 1      #特征的个数,减1是因为数据集的最后一列是标签
    baseEntropy = calcShannonEnt(dataSet) #计算原始数据集的信息熵,按最后一列计算
    bestInfoGain = 0.0; bestFeature = -1
    for i in range(numFeatures):        #遍历所有的数据特征
        featList = [example[i] for example in dataSet]# 该特征的所有值
        uniqueVals = set(featList)       #该特征所有值去重
        newEntropy = 0.0
        for value in uniqueVals: #对于每个没有重复的数值
            subDataSet = splitDataSet(dataSet, i, value) #对于某一个特征,分别对特征的每个取值得到划分后的数据集
            prob = len(subDataSet)/float(len(dataSet)) #计算概率
            newEntropy += prob * calcShannonEnt(subDataSet)  #无序度
        infoGain = baseEntropy - newEntropy     #信息增益等于原始数据集的熵减去新的熵(无需度的减少)
        if (infoGain > bestInfoGain):       #比较当前信息增益和最佳增益的大小
            bestInfoGain = infoGain         #if better than current best, set to best
            bestFeature = i
    return bestFeature                      #得出最佳增益应该是第几个特征,从0开始

def majorityCnt(classList):
    '''
    投票表决代码,选出出现最多的结果
    :param classList:
    :return:
    '''
    classCount={}
    for vote in classList:
        if vote not in classCount.keys(): classCount[vote] = 0
        classCount[vote] += 1
    sortedClassCount = sorted(classCount.iteritems(), key=operator.itemgetter(1), reverse=True)
    return sortedClassCount[0][0]

def createTree(dataSet,labels):
    '''
    构造决策树,生成嵌套字典
    :param dataSet:对应的含有条件和结果特征的数据集,都是标量型
    :param labels:labels是特征列名
    :return:
    '''
    classList = [example[-1] for example in dataSet] #结果特征集合
    if classList.count(classList[0]) == len(classList): 
        return classList[0]#如果所有的结果特征值都相同,停止生成决策树,返回这个结果特征
    if len(dataSet[0]) == 1: #如果只有一个结果特征列了,停止生成决策树,返回比较多的结果特征
        return majorityCnt(classList)
    bestFeat = chooseBestFeatureToSplit(dataSet) #找到最佳的划分条件特征是哪一个特征,列数
    bestFeatLabel = labels[bestFeat] #最佳的条件特征标签
    myTree = {bestFeatLabel:{}}
    del(labels[bestFeat]) #删除最佳条件标签剩下的特征标签
    featValues = [example[bestFeat] for example in dataSet] #最佳特征标签对应的一列数据的值
    uniqueVals = set(featValues) #没有重复的最佳特征标签对应的一列数据的值
    for value in uniqueVals: # 对每个值生成决策树
        subLabels = labels[:]       #拷贝所有标签,为了不与其他标签混淆
        myTree[bestFeatLabel][value] = createTree(splitDataSet(dataSet, bestFeat, value),subLabels) #递归调用,对于每个树分支的值还是一颗树
    return myTree                            
    
def classify(inputTree,featLabels,testVec):
    '''
    ID3决策树分类器
    :param inputTree:字典树
    :param featLabels:条件特征列表
    :param testVec:测试样本列表
    :return:结果特征值
    '''
    firstStr = inputTree.keys()[0]
    secondDict = inputTree[firstStr]
    featIndex = featLabels.index(firstStr)
    key = testVec[featIndex]
    valueOfFeat = secondDict[key]
    if isinstance(valueOfFeat, dict): 
        classLabel = classify(valueOfFeat, featLabels, testVec)
    else: classLabel = valueOfFeat
    return classLabel

def storeTree(inputTree,filename):
    '''
    持久化存储
    :param inputTree:
    :param filename:
    :return:
    '''
    import pickle
    fw = open(filename,'w')
    pickle.dump(inputTree,fw)
    fw.close()
    
def grabTree(filename):
    '''
    从文件获取树字典
    :param filename:
    :return:
    '''
    import pickle
    fr = open(filename)
    return pickle.load(fr)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151

画出决策树的程序

treePlotter.py

# -*- coding: utf-8 -*
'''
Created on Oct 14, 2010

@author: Peter Harrington
'''
import matplotlib.pyplot as plt

decisionNode = dict(boxstyle="sawtooth", fc="0.8")
leafNode = dict(boxstyle="round4", fc="0.8")
arrow_args = dict(arrowstyle="<-")

def getNumLeafs(myTree):
    '''
    获取叶节点的数目
    :param myTree:字典结构的树
    :return:
    '''
    numLeafs = 0
    firstStr = myTree.keys()[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes
            numLeafs += getNumLeafs(secondDict[key])
        else:   numLeafs +=1
    return numLeafs

def getTreeDepth(myTree):
    '''
    获取树的最大深度
    :param myTree:字典结构的树
    :return:
    '''
    maxDepth = 0
    firstStr = myTree.keys()[0]
    secondDict = myTree[firstStr]
    for key in secondDict.keys():
        if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes
            thisDepth = 1 + getTreeDepth(secondDict[key])
        else:   thisDepth = 1
        if thisDepth > maxDepth: maxDepth = thisDepth
    return maxDepth

def plotNode(nodeTxt, centerPt, parentPt, nodeType):
    createPlot.ax1.annotate(nodeTxt, xy=parentPt,  xycoords='axes fraction',
             xytext=centerPt, textcoords='axes fraction',
             va="center", ha="center", bbox=nodeType, arrowprops=arrow_args )

#❶ (以下四行)在父子节点间填充文本信息
def plotMidText(cntrPt, parentPt, txtString):
    xMid = (parentPt[0]-cntrPt[0])/2.0 + cntrPt[0]
    yMid = (parentPt[1]-cntrPt[1])/2.0 + cntrPt[1]
    createPlot.ax1.text(xMid, yMid, txtString, va="center", ha="center", rotation=30)

def plotTree(myTree, parentPt, nodeTxt):#if the first key tells you what feat was split on
    # ❷(以下两行)计算宽和高
    numLeafs = getNumLeafs(myTree)  #this determines the x width of this tree
    depth = getTreeDepth(myTree)
    firstStr = myTree.keys()[0]     #the text label for this node should be this
    cntrPt = (plotTree.xOff + (1.0 + float(numLeafs))/2.0/plotTree.totalW, plotTree.yOff)
    # ❸ 标记子节点属性值
    plotMidText(cntrPt, parentPt, nodeTxt)
    plotNode(firstStr, cntrPt, parentPt, decisionNode)
    secondDict = myTree[firstStr]
    plotTree.yOff = plotTree.yOff - 1.0/plotTree.totalD
    for key in secondDict.keys():
        if type(secondDict[key]).__name__=='dict':#test to see if the nodes are dictonaires, if not they are leaf nodes   
            plotTree(secondDict[key],cntrPt,str(key))        #recursion
        else:   #it's a leaf node print the leaf node
            plotTree.xOff = plotTree.xOff + 1.0/plotTree.totalW
            plotNode(secondDict[key], (plotTree.xOff, plotTree.yOff), cntrPt, leafNode)
            plotMidText((plotTree.xOff, plotTree.yOff), cntrPt, str(key))
    plotTree.yOff = plotTree.yOff + 1.0/plotTree.totalD
#if you do get a dictonary you know it's a tree, and the first element will be another dict

def createPlot(inTree):
    fig = plt.figure(1, facecolor='white')#画出来图形figure1 背景色白色
    fig.clf() #清除屏幕
    axprops = dict(xticks=[], yticks=[]) #定义字典
    createPlot.ax1 = plt.subplot(111, frameon=False, **axprops)    #no ticks
    #createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses 
    plotTree.totalW = float(getNumLeafs(inTree)) #叶节点
    plotTree.totalD = float(getTreeDepth(inTree))#深度
    plotTree.xOff = -0.5/plotTree.totalW; plotTree.yOff = 1.0;
    plotTree(inTree, (0.5,1.0), '')
    plt.show()
#测试画出决策树的点
#def createPlot():
#    fig = plt.figure(1, facecolor='white')
#    fig.clf()
#    createPlot.ax1 = plt.subplot(111, frameon=False) #ticks for demo puropses 
#    plotNode('a decision node', (0.5, 0.1), (0.1, 0.5), decisionNode)
#    plotNode('a leaf node', (0.8, 0.1), (0.3, 0.8), leafNode)
#    plt.show()

def retrieveTree(i):
    listOfTrees =[{'no surfacing': {0: 'no', 1: {'flippers': {0: 'no', 1: 'yes'}}}},
                  {'no surfacing': {0: 'no', 1: {'flippers': {0: {'head': {0: 'no', 1: 'yes'}}, 1: 'no'}}}}
                  ]
    return listOfTrees[i]

#createPlot(thisTree)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102

第三种经典算法:回归算法(Logistic)

算法适用类型:输入输出是标称型或者数值型
结合最优化算法,梯度下降法。梯度是当前函数在当前自变量X=(x0,y0),(x1,y1)(x2,y2)…),因变量Z上升最快的方向,本质上是一个向量(梯度的方向实际就是函数在此点上升最快的方向)

梯度下降法的详细解释见https://www.jianshu.com/p/c7e642877b0e
最通俗的公式:

α在梯度下降算法中被称作为学习率或者步长,梯度前加一个负号,就意味着朝着梯度相反的方向前进!

###多变量函数的梯度下降
我们假设有一个目标函数!

现在要通过梯度下降法计算这个函数的最小值。我们通过观察就能发现最小值其实就是 (0,0)点。但是接下来,我们会从梯度下降算法开始一步步计算到这个最小值!
我们假设初始的起点为:

初始的学习率为:

函数的梯度为:

进行多次迭代:

我们发现,已经基本靠近函数的最小值点

基本概念
步长(Learning rate): 步长决定了在梯度下降迭代的过程中,每一步沿梯度负方向前进的长度。
特征(feature): 指的是样本中输入部分

比如2个单特征(一个条件一个结果)的样本

(x^{(0)},y^{(0)}),(x^{(1)},y^{(1)}),(x^{(2)},y^{(2)}),...,(x^{(m)},y^{(m)})
  • 1

则第一个样本特征为

(x^{(0)})  
  • 1

第一个样本输出为

(y^{(0)})
  • 1

假设函数(hypothesis function):
在监督学习中,为了拟合输入样本,而使用的假设函数,记为

h_{(\Theta)}(x)
  • 1

比如对于单个特征的m个样本
(x(i),y(i))(i=1,2,…m),可以采用拟合函数如下:

h^{(\Theta)}(x)=\Theta_0+\Theta_1x
  • 1

损失函数(loss function):为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。在线性回归中,损失函数通常为样本输出和假设函数的差取平方。比如对于m个样本(x(i),y(i))(i=1,2,…m),采用线性回归,损失函数为:

J(\Theta_0,\Theta_1)=\Sigma^m_{i=1}(h_0x^{(i)}-y^{(i)})^2
  • 1

其中xi表示第i个样本特征,yi表示第i个样本对应的输出,

h_{(\Theta)}(x)
  • 1

为假设函数。


以两个变量为例的推导过程:

我们需要定义一个代价函数,在此我们选用均方误差代价函数
image
此公示中
m是数据集中点的个数
½是一个常量,这样是为了在求梯度的时候,二次方乘下来就和这里的½抵消了,自然就没有多余的常数系数,方便后续的计算,同时对结果不会有影响
y 是数据集中每个点的真实y坐标的值,h 是我们的预测函数,根据每一个输入x,根据Θ 计算得到预测的y值,即

我们可以根据代价函数看到,代价函数中的变量有两个,所以是一个多变量的梯度下降问题,求解出代价函数的梯度,也就是分别对两个变量进行微分
image
明确了代价函数和梯度,以及预测的函数形式。我们就可以开始编写代码了。但在这之前,需要说明一点,就是为了方便代码的编写,我们会将所有的公式都转换为矩阵的形式,python中计算矩阵是非常方便的,同时代码也会变得非常的简洁。

为了转换为矩阵的计算,我们观察到预测函数的形式
image
我们有两个变量,为了对这个公式进行矩阵化,我们可以给每一个点x增加一维,这一维的值固定为1,这一维将会乘到Θ0上。这样就方便我们统一矩阵化的计算
image
然后我们将代价函数和梯度转化为矩阵向量相乘的形式
image


在python中的梯度下降法代码:

import numpy as np

# Size of the points dataset.
m = 20

# Points x-coordinate and dummy value (x0, x1).
X0 = np.ones((m, 1))
X1 = np.arange(1, m+1).reshape(m, 1)
X = np.hstack((X0, X1))

# Points y-coordinate
y = np.array([
    3, 4, 5, 5, 2, 4, 7, 8, 11, 8, 12,
    11, 13, 13, 16, 17, 18, 17, 19, 21
]).reshape(m, 1)

# The Learning Rate alpha.
alpha = 0.01

# 求误差函数
def error_function(theta, X, y):
    '''Error function J definition.'''
    diff = np.dot(X, theta) - y #参数矩阵,是一个n行一列的矩阵,n是特征维度个数
    return (1./2*m) * np.dot(np.transpose(diff), diff)

# 求梯度
def gradient_function(theta, X, y):
    '''Gradient of the function J definition.'''
    diff = np.dot(X, theta) - y #误差
    return (1./m) * np.dot(np.transpose(X), diff) #梯度

# 梯度下降法求梯度
def gradient_descent(X, y, alpha):
    '''Perform gradient descent.'''
    theta = np.array([1, 1]).reshape(2, 1) #参数矩阵
    gradient = gradient_function(theta, X, y) #梯度
    while not np.all(np.absolute(gradient) <= 1e-5):
        theta = theta - alpha * gradient
        gradient = gradient_function(theta, X, y) #求梯度
    return theta

optimal = gradient_descent(X, y, alpha)
print('optimal:', optimal)
print('error function:', error_function(optimal, X, y)[0,0])
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

运行代码,计算得到的结果如下
image
得出拟合曲线
image

自己编写的代码:

#!/usr/bin/python
# -*- coding: UTF-8 -*-
import numpy as np
import matplotlib.pyplot as plt

# 特征样本,结果样本
def createData(m):
    X0=np.ones((m,1))
    X1=np.arange(1,m+1).reshape(m,1) #两列实际上是单变量
    factor=np.hstack((X0,X1))
    label=np.array([
    3, 4, 5, 5, 2, 4, 7, 8, 11, 8, 12,
    11, 13, 13, 16, 17, 18, 17, 19, 21
    ]).reshape(m, 1)
    return factor,label,X1

#误差函数矩阵
def erroFunction(theta,X,Y): #theta是参数矩阵
    return np.array((1.0/2*X.shape[0])*np.dot(np.dot(X,theta)-Y).T,(np.dot(X,theta)-Y))


# 梯度矩阵
def gradFunction(theta,X,Y):
    return (1.0/X.shape[0])*np.dot(np.transpose(X),(np.dot(X,theta)-Y))

# 梯度下降法求梯度
def gradientDescent(theta,X,Y,alpha=0.01):#alpha是学习率
    gradient=gradFunction(theta,X,Y)
    while not np.all(np.absolute(gradient))<=1e-5:
        theta=theta-alpha*gradient #让参数矩阵尽快达到最值
        gradient=gradFunction(theta,X,Y)
    return theta

X, Y,X1 = createData(20)
theta=np.array([1,1]).reshape(2,1) #初始参数矩阵
fig=plt.figure()
ax=fig.add_subplot(111)
ax.scatter(X1,Y,marker='o',color='red')
theta=gradientDescent(theta,X,Y)
pridict=np.dot(X,theta)
ax.scatter(X1,pridict,color='b',marker='^')
print '估计参数;\n'+str(theta)
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43

Logistic算法是在梯度算法的基础上引入Sigmoid函数,这个函数是一个类似脉冲的函数,如果结果只有两个标签,输入一个值后超过0.5的被认为是标签1,否则是标签0

def sigmoid(inX):
return 1.0/(1+exp(-inX))

#!/usr/bin/python
# -*- coding: utf-8 -*-
import numpy as np

'''
逻辑回归代码:输入是数值型,输出是1 0数值标签
'''

# 定义Sigmoid函数,预测值函数
def Sigmoid(x):
    return 1.0/(np.exp(-x)+1)

# 从文件中加载数据,输出是np.arr矩阵,条件样本在每行增加一列,每个数都是1
def LoadData():
    fr=open('D:\\PythonProject\\PythonVSTest\\test\\Ch05\\testSet.txt','r')
    X=[]
    Y=[]

    for line in fr.readlines(): 
        lineArr=line.strip().split() #数组list 3
        X.append([1.0,float(lineArr[0]),float(lineArr[1])]) #list
        Y.append([float(lineArr[2])]) #list

    inputX=np.array(X)
    outputY=np.array(Y)
    return inputX,outputY

inputX,outputY=LoadData()

def GetGrad(X,Y,weight):
    #预测值矩阵(m*1) Sigmoid(X*weight)
    h=Sigmoid(np.dot(X,weight)) #np.dot(X,weight)是预测值矩阵(m*1),预测值经过Sigmoid函数得到预测标签
    #误差矩阵(m*1)error=(X*weight-Y)
    error=h-Y
    #daijiaFunction=(1.0/2*X.shape[0])*np.dot(error.T,error)
    #求梯度矩阵(n*1)  X.T*error*(1/m)
    grad=(1.0/X.shape[0])*np.dot(X.T,error)
    return grad

# 梯度逻辑回归算法,求参数矩阵weight(n*1)
def gradDescentLogics(X,Y,alpha=0.001):
    m,n=X.shape
    #参数矩阵(n*1)
    weight=np.ones((n,1)) #n行1列参数(权重)矩阵
    #求梯度矩阵(n*1)  X.T*error*(1/m)
    grad=GetGrad(X,Y,weight)
    # grad=np.dot(X.T,error)
    #梯度求最值
    while not np.all(np.absolute(grad))<1e-2:
        #求梯度矩阵(n*1)  X.T*error*(1/m)
        grad=GetGrad(X,Y,weight)
        weight=weight-alpha*grad
    return weight
    
    #另一种循环固定次数
    #cycle=500
    #i=0

    #while i<=cycle:
    #    error=Sigmoid(np.dot(X,weight))-Y
    #    weight=weight-alpha*np.dot(X.T,error)
    #    i=i+1
    #return weight
weight=gradDescentLogics(inputX,outputY)
print (weight)


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70

第四种经典算法:聚类算法(KMEANS)

#!/usr/local/python3/python
# -*-coding:utf-8-*-
import os
import sys
from numpy import *
import time
import matplotlib.pyplot as plt

##kmeans算法的实现:
#伪代码
# 创建k个点作为初始的质心点(随机选择)
# 当任意一个点的簇分配结果发生改变时
#        对数据集中的每一个数据点
#               对每一个质心
#                      计算质心与数据点的距离
#               将数据点分配到距离最近的簇
#        对每一个簇,计算簇中所有点的均值,并将均值作为质心


##数据加载,将数据转化成矩阵

def loadDataSet(filename):
    dataMat=[]
    #加载数据
    fr=open(filename)
    for line in fr.readlines():
        #字符串去掉开头和结尾的空格,并以'\t'为分割,变成list(列表)
        newline=line.strip().split('\t')
        newLine=list(map(float,newline))
        #不是扩展,而是append,扩展和追加的区别
        dataMat.append(newLine)
    return mat(dataMat)
# print(loadDataSet(r'C:\Users\Administrator\Desktop\text.txt'))
dataSet=loadDataSet(r'C:\Users\Administrator\Desktop\text.txt')
# print(dataSet)

##计算欧式距离

def oushiJuli(A,B):
    return sqrt(sum(power(A-B,2)))

##构建初始化聚集中心矩阵也就是求取k个质心,一共有k个分类,对应k个聚集中心,k个质心

def randCent(dataSet,k):
    #求取要分析矩阵(还不是矩阵是array列表)的行列,并取出其中的列n
    #其中行数是数据的总数目,列数是点坐标的维数
    n=shape(dataSet)[1]
    #初始化矩阵(用mat方法),k行,n列
    centroids=mat(zeros((k,n)))
    for j in range(n):
        ##求取原始数据每一列的最大和最小值
        minJ=min(dataSet[:,j])
        maxJ=max(dataSet[:,j])
        rangeJ=float(maxJ-minJ)
        ##矩阵相加,求取质心
        centroids[:,j]=minJ+rangeJ*random.rand(k,1)
    return centroids

##kmens算法主函数

def kMeans(dataSet,k,distMeans=oushiJuli,createCent=randCent):
    #球数据的总数目m
    m=shape(dataSet)[0]
    #族类矩阵(所有样本的质心归属矩阵):存放每一个数据属于哪类及距离
    clusterAssment=mat(zeros((m,2)))
    #初始化质心
    centroids=createCent(dataSet,k)
    #群族改变

    clusterChanged=True
    while clusterChanged:
        #族群改变标志设为假
        clusterChanged=False

        #对每一个数据集中的数据点
        for i in range(m):
            #初始化欧式距离的最小值,及最小距离对应的类
            minDist=inf
            minIndex=-1
            #对每一个质心
            for j in range(k):
            #计算每个点到质心的距离
                distJ=distMeans(centroids[j,:],dataSet[i,:])
                #如果计算出的欧氏距离比最小距离还小
                if distJ<minDist:
                    #把最小距离赋值为计算的欧式距离,顺带的把质心的标记j赋值给minIndex
                    minDist=distJ
                    minIndex=j
            #如果族类矩阵记录的样本归属质心不是距离最小的j
            if clusterAssment[i,0]!=minIndex:
            #把群族的变化标志位变成真,预示着族类矩阵还要优化
                clusterChanged=True
            #重新记录群族样本的质心归属,和对应的欧式距离
                clusterAssment[i,:]=minIndex,minDist**2
        #族群改变前,打印质心
        # print(centroids)
        #群族改变,重新计算质心
        for cent in range(k):
            #nonzero是求不是零(为真)的索引,clusterAssment记录所有样本中质心的归属j(0<j<k),A是将矩阵中numpy的matrix转化成array
            #matrix具有array的所有属性。nonzero(clusterAssment[:, 0].A == cent(这是个tuple对象)如果是对第一个质心cent=0,那么这个式子就是表示
            #从记录样本质心标记中找出所有该类质心的点的位置, 用dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]
            # (tuple第一个值nonzero(clusterAssment[:, 0].A == cent)[0]表示可以取出来1第一行,如果不加[0],就是4,5表示4行5列,表示一个具体的行列值)
            # 可以取出来所有属于该质心的行,如果后边不加[0],就只可以可以取出第一列,样本的横坐标。可以试一下
            ptsInClust = dataSet[nonzero(clusterAssment[:, 0].A == cent)[0]]
            #axis=0代表对列求平均值
            centroids[cent, :] = mean(ptsInClust, axis=0)
    #返回质心,族类矩阵
    return centroids, clusterAssment
#如果将样本分成4类打印结果
# print(kMeans(dataSet,4)[1])
centRoids,assment = kMeans(dataSet,4)
fig = plt.figure()
ax = fig.add_subplot(111)
ax.scatter(dataSet[:, 0].tolist(), dataSet[:, 1].tolist(), c='blue')
ax.scatter(centRoids[:, 0].tolist(), centRoids[:, 1].tolist(), c='red', marker='+', s=70)
plt.show()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116

使用sklearn算法的选择路径

image

# coding:utf-8
from sklearn import linear_model
import svmMLiA as svm
import numpy as np

#线性回归,输入输出都是数值型的
linear = linear_model.LinearRegression(normalize=False) #归一标准化化

x_train_list,y_train_list=svm.loadDataSet('testSet.txt')
x_train=np.array(x_train_list)
y_train=np.array(y_train_list)

linear.fit(x_train,y_train)
print linear.score(x_train,y_train) #分类器得分
# 斜率和截距
print('Coefficient: \n', linear.coef_)
print('Intercept: \n', linear.intercept_)
#预测输出
predicted= linear.predict(np.array([[2,1]]))
print predicted

#逻辑回归解决2分类问题,输入是数值型,输出是0或者1标签

from sklearn.linear_model import LogisticRegression

x_train_list,y_train_list=svm.loadDataSet('testLogistic.txt')
x_train=np.array(x_train_list)
y_train=np.array(y_train_list)
model = LogisticRegression()
model.fit(x_train, y_train)
print model.score(x_train, y_train)

#Equation coefficient and Intercept
print('Coefficient: \n', model.coef_)
print('Intercept: \n', model.intercept_)

#Predict Output
predicted= model.predict(np.array([[-1,8]]))
print predicted

# coding:utf-8
from sklearn import linear_model
import svmMLiA as svm
import numpy as np

#线性回归,输入输出都是数值型的
linear = linear_model.LinearRegression(normalize=False) #归一标准化化

x_train_list,y_train_list=svm.loadDataSet('testSet.txt')
x_train=np.array(x_train_list)
y_train=np.array(y_train_list)

linear.fit(x_train,y_train)
print linear.score(x_train,y_train) #分类器得分
# 斜率和截距
print('Coefficient: \n', linear.coef_)
print('Intercept: \n', linear.intercept_)
#预测输出
predicted= linear.predict(np.array([[2,1]]))
print predicted

#逻辑回归解决2分类问题,输入是数值型,输出是0或者1标签

from sklearn.linear_model import LogisticRegression

x_train_list,y_train_list=svm.loadDataSet('testLogistic.txt')
x_train=np.array(x_train_list)
y_train=np.array(y_train_list)
model = LogisticRegression()
model.fit(x_train, y_train)
print model.score(x_train, y_train)

#Equation coefficient and Intercept
print('Coefficient: \n', model.coef_)
print('Intercept: \n', model.intercept_)

#Predict Output
predicted= model.predict(np.array([[-1,8]]))
print predicted

# 使用sklearn加载数据集
from distutils.version import LooseVersion as Version
from sklearn import __version__ as sklearn_version
from sklearn import datasets
import numpy as np

iris = datasets.load_iris()
iris.data  # 查看数据
X = iris.data[:, [2, 3]]
y = iris.target

print('Class labels:', np.unique(y))

# 取百分之70做训练,剩下百分30做预测
if Version(sklearn_version) < '0.18':
    from sklearn.cross_validation import train_test_split
else:
    from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.3, random_state=0)

print X_train.shape, X_test.shape, y_train.shape, y_test.shape

# 对特征做标准化
from sklearn.preprocessing import StandardScaler

sc = StandardScaler()
sc.fit(X_train)


print sc.scale_
X_train_std = sc.transform(X_train)
X_test_std = sc.transform(X_test)


#sklearn中的线性分类器
from sklearn.linear_model import Perceptron

# ppn = Perceptron(n_iter=40, eta0=0.1, random_state=0)
ppn = Perceptron()

ppn.fit(X_train_std, y_train)

ppn.coef_

ppn.intercept_

y_pred = ppn.predict(X_test_std)
y_pred

y_test

y_pred == y_test

print('Misclassified samples: %d' % (y_test != y_pred).sum())

from sklearn.metrics import accuracy_score

print('Accuracy: %.2f' % accuracy_score(y_test, y_pred))


# 逻辑回归
from sklearn import datasets
import numpy as np
iris = datasets.load_iris()
X = iris.data[:,[2,3]]
y = iris.target

# 训练数据和测试数据分为7:3
x_train,x_test,y_train,y_test =train_test_split(X,y,test_size=0.3,random_state=0)

# 标准化数据
from sklearn.preprocessing import StandardScaler
sc = StandardScaler()
sc.fit(x_train)
x_train_std = sc.transform(x_train)
x_test_std = sc.transform(x_test)

# 绘制决策边界
from matplotlib.colors import ListedColormap
import matplotlib.pyplot as plt
import warnings

def versiontuple(v):
    return tuple(map(int, (v.split("."))))

def plot_decision_regions(X,y,classifier,test_idx=None,resolution=0.02):
    # 设置标记点和颜色
    markers = ('s','x','o','^','v')
    colors = ('red', 'blue', 'lightgreen', 'gray', 'cyan')
    cmap = ListedColormap(colors[:len(np.unique(y))])

    # 绘制决策面
    x1_min, x1_max = X[:, 0].min() - 1, X[:, 0].max() + 1
    x2_min, x2_max = X[:, 1].min() - 1, X[:, 1].max() + 1
    xx1, xx2 = np.meshgrid(np.arange(x1_min, x1_max, resolution),
                         np.arange(x2_min, x2_max, resolution))
    Z = classifier.predict(np.array([xx1.ravel(), xx2.ravel()]).T)
    Z = Z.reshape(xx1.shape)
    plt.contourf(xx1, xx2, Z, alpha=0.4, cmap=cmap)
    plt.xlim(xx1.min(), xx1.max())
    plt.ylim(xx2.min(), xx2.max())

    for idx, cl in enumerate(np.unique(y)):
        plt.scatter(x=X[y == cl, 0], y=X[y == cl, 1],
                    alpha=0.8, c=cmap(idx),
                    marker=markers[idx], label=cl)

    # 高粱所有的数据点
    if test_idx:
        # 绘制所有数据点
        if not versiontuple(np.__version__) >= versiontuple('1.9.0'):
            X_test, y_test = X[list(test_idx), :], y[list(test_idx)]
            warnings.warn('Please update to NumPy 1.9.0 or newer')
        else:
            X_test, y_test = X[test_idx, :], y[test_idx]
        plt.scatter(X_test[:, 0], X_test[:, 1], c='b',
                alpha=1.0, linewidth=1, marker='o',
                s=55, label='test set')

# 应用Logistics回归模型
from sklearn.linear_model import LogisticRegression
lr = LogisticRegression(C=1000.0,random_state=0)
lr.fit(x_train_std,y_train)

X_combined_std = np.vstack((x_train_std, x_test_std))
y_combined = np.hstack((y_train, y_test))
plot_decision_regions(X_combined_std, y_combined,
                      classifier=lr, test_idx=range(105,150))
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
plt.show()

if Version(sklearn_version) < '0.17':
    lr.predict_proba(X_test_std[0, :])
else:
    lr.predict_proba(X_test_std[0, :].reshape(1, -1))

lr.predict_proba(X_test_std[0, :])

#来谈谈过拟合/overfitting 与 正则化/regularization
#正则化L1 和L2    L1截断,会产生很多0,使矩阵稀疏;L2是缩放,把权重缩放到很小。

from sklearn.svm import SVC

svm = SVC(kernel='linear', C=1.0, random_state=0)
svm.fit(X_train_std, y_train)
X_combined_std = np.vstack((x_train_std, x_test_std))
y_combined = np.hstack((y_train, y_test))

plot_decision_regions(X_combined_std, y_combined,
                      classifier=svm, test_idx=range(105, 150))
plt.xlabel('petal length [standardized]')
plt.ylabel('petal width [standardized]')
plt.legend(loc='upper left')
plt.tight_layout()
# plt.savefig('./figures/support_vector_machine_linear.png', dpi=300)
plt.show()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132
  • 133
  • 134
  • 135
  • 136
  • 137
  • 138
  • 139
  • 140
  • 141
  • 142
  • 143
  • 144
  • 145
  • 146
  • 147
  • 148
  • 149
  • 150
  • 151
  • 152
  • 153
  • 154
  • 155
  • 156
  • 157
  • 158
  • 159
  • 160
  • 161
  • 162
  • 163
  • 164
  • 165
  • 166
  • 167
  • 168
  • 169
  • 170
  • 171
  • 172
  • 173
  • 174
  • 175
  • 176
  • 177
  • 178
  • 179
  • 180
  • 181
  • 182
  • 183
  • 184
  • 185
  • 186
  • 187
  • 188
  • 189
  • 190
  • 191
  • 192
  • 193
  • 194
  • 195
  • 196
  • 197
  • 198
  • 199
  • 200
  • 201
  • 202
  • 203
  • 204
  • 205
  • 206
  • 207
  • 208
  • 209
  • 210
  • 211
  • 212
  • 213
  • 214
  • 215
  • 216
  • 217
  • 218
  • 219
  • 220
  • 221
  • 222
  • 223
  • 224
  • 225
  • 226
  • 227
  • 228
  • 229
  • 230
  • 231
  • 232
  • 233
  • 234
  • 235
  • 236
  • 237
  • 238
  • 239
  • 240
  • 241
  • 242

常用的sklearn操作

加载数据集

# coding: utf-8
from sklearn.datasets import load_iris,fetch_20newsgroups,load_boston
from sklearn.model_selection import train_test_split 

iris_data = load_iris()
x_train,x_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,test_size=0.3)
#print(x_train,x_test,y_train,y_test)
boston = load_boston()
newsData = fetch_20newsgroups(data_home='D:\data',subset='all')
#print(boston.data,boston.target)
#print(newsData.data,newsData.target)
print(len(newsData.data))
print(newsData.data[0])
print(newsData.filenames)
print(newsData.target)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

特征工程:sklearn对特征进行提取 文本特征抽取

# coding:utf-8

import pandas as pd
import numpy as np

from sklearn.feature_extraction import DictVectorizer #字典特征抽取  
from sklearn.feature_extraction.text import CountVectorizer #文本特征抽取  
from sklearn.feature_extraction.text import TfidfVectorizer  #tf idf特征提取
import jieba

def DictVec():
    '''
    字典数据抽取,将标称型转化成数值型的数据表
    :return None
    '''
    instances = [{'city': '北京','temperature':100},{'city': '上海','temperature':60}, {'city': '深圳','temperature':30}]
    dict=DictVectorizer(sparse=False) #不用sparse矩阵
    data=dict.fit_transform(instances) #返回sparse矩阵 scipy中的矩阵 节约内存 方便读取处理 而在numpy中式ndarray的矩阵
    print(dict.get_feature_names()) #打印特征名
    print(dict.inverse_transform(data)) # 返回原来数据
    print(data) #打印提取的特征数据,采用ONE-hot编码,将类别编码转化成one-hot编码
    return None

def CountTextEnVec():
    '''
    对文本进行提取特征,用于文本分类,情感分析,只能用于英文。中文的话先要进行分词用空格分隔,统计步骤:
    1.统计所有文章中所有的词,重复的次不计数,只算一次,次的列表,单个字母不统计 
    2 对步骤1词的列表统计次数
    '''
    cv=CountVectorizer()
    data =cv.fit_transform(["life is short,i like python hehe haha hehe","life is too long,i dislike python"])
    print(cv.get_feature_names())
    print(data.toarray()) 
    return None

def CutWord():
    '''
    中文分词
    '''
    c1=jieba.cut('今天很残酷,明天更残酷,后天很美好,但绝对大部分是死在明天晚上,所以每个人不要放弃今天。')
    c2=jieba.cut('我们看到的从很远星系来的光是在几百万年之前发出的,这样当我们看到宇宙时,我们是在看它的过去。')
    c3=jieba.cut('如果只用一种方式了解某样事物,你就不会真正了解它。了解事物真正含义的秘密取决于如何将其与我们所了解的事物相联系。')
    
    lc1=list(c1)
    lc2=list(c2)
    lc3=list(c3)

    rc1=' '.join(lc1)
    rc2=' '.join(lc2)
    rc3=' '.join(lc3)
    return rc1,rc2,rc3

def CountTextZhVec():
    '''
    中文分词的特征值提取
    '''
    cv=CountVectorizer()
    rc1,rc2,rc3=CutWord()
    print (rc1,rc2,rc3)
    data =cv.fit_transform([rc1,rc2,rc3])
    print(cv.get_feature_names())
    print(data.toarray()) 
    return None

def TfIdf():
    '''
    使用log(tf*idf)的大小作为词的重要程度的判定 ,tf叫term frequency 词语出现频率 
    idf inverse document frequency 反向文档频率=总文档数/该词文档数。原理如果一个
    词在一个文档出现频繁,而在另一个文档出现不频繁,那么该词重要度高,用于文本分类
    '''
    tf=TfidfVectorizer()
    rc1,rc2,rc3=CutWord()
    print (rc1,rc2,rc3)
    data =tf.fit_transform([rc1,rc2,rc3])
    print(tf.get_feature_names())
    print(data.toarray()) 
    return None

if __name__=="__main__":
    #DictVec()
    #CountTextEnVec()
    #CountTextZhVec()
    TfIdf()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83

sklearn数据预处理:标准化和归一化数据

# coding:utf-8
'''
@auter;menghui.zhao
@description:
1.归一化数据,主要利用sklearn.preprocessing
中的MinMaxScaler最大最小缩放,MinMaxScaler(feature_range(0,1)...)
feature_range指定缩小范围,目的是使一个特征不会对结果产生影响
min是样本中最小值,max是样本中最大值,注意在数据流场景下最大值
最小值是变化的,另外,最大值与最小值非常容易受异常点影响,
所以这种方法鲁棒性较差,只适合传统精确小数据场景X​′=(x-min)/(max-min) 
2.标准化数据:X′=(x-μ)/​σ,将原始数据的每一列变成均值为0,标准差为1的数据
​​其中\μ是样本的均值,σ是样本的标准差,它们可以通过现有的样本进行估计,
在已有的样本足够多的情况下比较稳定,适合嘈杂的数据场景,有一定的数据量
3.缺失值根据实际情况进行删除(如果每列或者每行缺失值达到一定比例)或者插补还可以使用pandas
(中位数、平均值等,按列) Imputer(missing_values='NaN',strategy='mean',axix=0)
Imputer.fit_transfornm(),数据类型必须是np.nan float 将特殊字符替换成Nan
cancelData.replace(to_replace='?',value=np.nan)
去掉nan值cancelData.dropna()
'''

import numpy as np

from sklearn.preprocessing import MinMaxScaler #最大最小缩放,归一化
from sklearn.preprocessing import StandardScaler #标准化
from sklearn.preprocessing import Imputer #缺失值处理

def normalization():
    '''
    归一化数据
    '''
    mm=MinMaxScaler(feature_range=(2,3))
    data=mm.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]])
    print (data)   
    return None

def standard():
    '''
    标准化数据
    '''
    std=StandardScaler()
    data=std.fit_transform([[90,2,10,40],[60,4,15,45],[75,3,13,46]])
    print (data)   
    return None

def dealNanData():
    '''
    缺失数据处理
    '''
    im=Imputer(missing_values='NaN',strategy='mean',axis=0)
    data=im.fit_transform([[np.nan,2,10,40],[60,4,15,45],[75,3,13,46]])
    print (data)   
    return None

if __name__=='__main__':
    #normalization()
    #standard()
    dealNanData()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57

sklearn数据降维

# coding:utf-8
'''
1.方差特征过滤
2.PCA:特征数量上百的时候,考虑数据的简化,数据会改变,特征会减少
n_components 0.9-0.95 经验信息保存的百分比 如果是整数 表示减少到的特征数量
3.神经网络
4.其他方法
'''

from sklearn.feature_selection  import VarianceThreshold #方差过滤的方式选择特征
from sklearn.decomposition import PCA

def VarFeatureFilter():
    var=VarianceThreshold(threshold=0.0) #将方差小于该阈值的一列特征去掉
    data=var.fit_transform([[1,2,3],[1,4,5],[1,2,4]])
    print data
    return None

def PcaFeatureFilter():
    pca=PCA(n_components=0.9)
    data=pca.fit_transform([[4,2,3,9],[5,4,5,3.3],[1,2,4,7]])
    print data
    return None

if __name__=='__main__':
    #VarFeatureFilter()
    PcaFeatureFilter()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27

使用PCA进行降维的例子

# coding : utf-8
import pandas as pd
from sklearn.decomposition import PCA
'''
多个表利用pandas串表,然后利用PCA进行分析
'''

#读取数据表
priror = pd.read_csv('./data/priror.csv') 
products = pd.read_csv('./data/products.csv') 
order = pd.read_csv('./data/order.csv')
ailes = pd.read_csv('./data/ailes.csv') 
# 利用pandas合并表
_mg = pd.merge(priror,products,open=['product_id','product_id'])
_mg = pd.merge(_mg,order,open=['order_id','order_id'])
mdata = pd.merge(_mg,ailes,open=['ailes_id','ailes_id'])
print(mdata.head(10))

#建立行列数据,交叉表(特殊的分组)
cross = pd.crosstab(mdata['user_id'],mdata['ailes'])

pca = PCA(n_components=0.9)
finalData = pca.fit_transform(cross)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
sklearn的数据集
  • 数据集的获取

sklearn.datasets
datasets.load()
获取小规模数据集
datasets.fetch(data_home=None)
需要从a网络上获取大规模,data_home是数据集下载目录,默认是~/scikit_learn_data/
load和fetch默认的返回类型是datasets.base.Bunch(字典形式)
data 是特征数据,是numpy.ndarray二维数组;
target是标签数组,是numpy.ndarray一维数组
DESCR: 数据描述
feature_names:特征名
target_names:标签名

  • 数据集的分割

sklearn.model_section.train_test_split(*arrays,**options)
*array是可变列表,数据特征值和数据目标值:即datasets.data,datasets.target目标值list
**options是数据参数,test_size=0.25(测试数据的占比)
返回数据(x_train,y_train,x_test,y_test)

# coding: utf-8
from sklearn.datasets import load_iris,fetch_20newsgroups,load_boston
from sklearn.model_selection import train_test_split 

iris_data = load_iris()
x_train,x_test,y_train,y_test = train_test_split(iris_data.data,iris_data.target,test_size=0.3)
#print(x_train,x_test,y_train,y_test)
boston = load_boston()
newsData = fetch_20newsgroups(data_home='D:\data',subset='all')
#print(boston.data,boston.target)
#print(newsData.data,newsData.target)
print(len(newsData.data))
print(newsData.data[0])
print(newsData.filenames)
print(newsData.target)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
转换器与评估器
  • 转换器:fit(x_train,y_train),fit()计算平均值,方差等,transform最终计算,fit_transform()直接计算
  • 估计器:
    y_pridict=predict(x_test) # 预测结果
    score(x_test,y_test) # 计算得分
算法分类
  • 监督算法(预测,特征值和目标值):分类算法包括K-NN、贝叶斯、决策树与随机森林、逻辑回归、神经网络;回归算法包括线性回归、岭回归。
  • 非监督学习:特征值 K-MEANS 分类算法:适用于离散型数据
第一种算法:KNN

K近邻,k个最近的大多属于哪一类就算哪一类,欧式距离,这种算法是需要进行标准化处理的,优点简单,对k敏感,性能需求高,数据集的knn算法

#!/usr/bin/python
# -*- coding: UTF-8 -*-

from sklearn.neighbors import KNeighborsClassifier #导入knn分类器
from sklearn.preprocessing import StandardScaler #标准化
import pandas as pd
from sklearn.model_selection import train_test_split

def knn():
    # 读取数据
    datasets=pd.read_csv('E:\\人工智能教程\\knnDatasets\\train.csv')
    print (datasets.head(10))
    # 处理数据
    data=datasets.query('x>1.0&x<1.5&y>2.5&y<2.75') #缩小x y
    time_value=pd.to_datetime(data['time'],unit='s') # 处理时间
    #print(time_value)
    # 把日期转化成字典格式
    time_value=pd.DatetimeIndex(time_value)
    #print(time_value)
    # 构造新特征
    data['day']=time_value.day
    data['hour'] = time_value.hour
    data['weekday'] = time_value.weekday
    print(data.head(10))
    # 把时间特征删除
    data=data.drop(['time'],axis=1)
    #data = data.drop(['row_id'], axis=1)
    # 把小于n个目标的位置删除
    place_count=data.groupby('place_id').count()
    tf=place_count[place_count.row_id>3].reset_index()
    data=data[data['place_id'].isin(tf.place_id)]
    # 去除无关的row_id
    data = data.drop(['row_id'], axis=1)
    #取出特征值和目标值
    y=data['place_id']
    x=data.drop(['place_id'],axis=1)
    # 标准化数据
    std=StandardScaler()

    # 进行分割
    x_train,x_test,y_train,y_test=train_test_split(x,y,test_size=0.25)
    # 对训练集和测试集的特征值进行标准化
    x_train=std.fit_transform(x_train)
    x_test=std.fit_transform(x_test)
    print(data.head(10))


    #k近邻算法
    knn=KNeighborsClassifier(n_neighbors=5)
    knn.fit(x_train, y_train)
    # 预测值
    y_pridict=knn.predict(x_test)
    # 准确度
    print(knn.score(x_test,y_test))
    return None

if __name__=='__main__':
    knn()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
第二种算法:朴素贝叶斯

朴素的含义是条件独立的意思。

  • |理论基础| 联合概率P(A,B)是事件A B同时发生的概率。条件概率P(A/B)是在B发生的条件下,A发生的概率。朴素贝叶斯公式:P(C/W)=P(W/C)*P©/P(W)。
  • |优点| 分类效率好,速度快,对缺失数据不太敏感,算法简单,常用于文本分类
  • |缺点| 如果训练集误差大的话,误差就大,不需要调参,拉普拉斯平滑系数默认是1。基于条件独立的假设,效果比神经网络效果差
# coding:utf-8

from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import TfidfVectorizer  # 文本特特征抽取
from sklearn.naive_bayes import MultinomialNB # 朴素贝叶斯算法
from sklearn.metrics import classification_report #指标

def bayes():
    '''
    朴素贝叶斯算法
    :return:
    '''
    news = fetch_20newsgroups(data_home='D:\data', subset='all')
    x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.3)
    # 对数据集进行特征抽取
    tf = TfidfVectorizer()
    # 训练集和测试集中的词按重要性进行统计
    x_train = tf.fit_transform(x_train)
    # print(tf.get_feature_names())
    x_test = tf.transform(x_test)
    # 进行朴素贝叶斯算法的预测,拉普拉斯平滑系数默认设置为1
    mlt=MultinomialNB(alpha=1.0)
    mlt.fit(x_train,y_train)
    y_pridict=mlt.predict(x_test)
    print('预测的文章列表:',y_pridict)
    # 得出准确率
    print('准确率:',mlt.score(x_test,y_test))
    print('每个类别的精确率和召回率:\n',classification_report(y_test,y_pridict,target_names=news.target_names))
    return None


if __name__ == '__main__':
    bayes()


  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36

分类模型评估指标:

  • 准确率:Acc=(TP+TN)/(TP+TN+FP+FN)=(TP+TN)/(P+N)
  • 混淆矩阵: 预测结果与正确标签之间有四种组合构成混淆矩阵
    TP(预测为正,实际也为正个数)
    FN(预测为负,实际为正个数)
    FP(预测为正,实际为负个数)
    TN(预测为负,实际也为负个数)
    P=TP+FNP=TP+FN, N=TN+FP
    Acc=(TP+TN)/(TP+TN+FP+FN)=(TP+TN)/(P+N)
    (真正率)=正样本预测结果数 / 正样本实际数,
    (假反率)=被预测为负的正样本结果数 / 正样本实际数,
    (假正率)=被预测为正的负样本结果数 /负样本实际数,
    (真反率)=负样本预测结果数 / 负样本实际数
  • 精确率和召回率:
    精确率 precision是预测结果为正例的样本中为真实正例的比例
    召回率 recall:真实正例的样本中预测结果为正例的比例,应用中考虑的比较多
  • F1-score=2TP/(2TP+FN+FP),说明分类模型越稳健
  • ROC 曲线

recall 体现了分类模型HH对正样本的识别能力,recall 越高,说明模型对正样本的识别能力越强,precision 体现了模型对负样本的区分能力,precision越高,说明模型对负样本的区分能力越强。F1-score 是两者的综合。F1-score 越高,说明分类模型越稳健。比如我们常见的雷达预警系统,我们需要对雷达信号进行分析,判断这个信号是飞行器(正样本)还是噪声 (负样本), 很显然,我们希望系统既能准确的捕捉到飞行器信号,也可以有效地区分噪声信号。所以就要同时权衡recall 和 precision这两个指标,如果我们把所有信号都判断为飞行器,那 recall 可以达到1,但是precision将会变得很低(假设两种信号的样本数接近),可能就在 0.5 左右,那F1-score 也不会很高。

模型的选择与调优
  • 交叉验证:将数据n等分,将数据分为测试数据和验证数据进行n轮替换,分别得出准确率,求平均准确率的结果。为了使模型更加准确。
  • 网格搜索:算法中手动调节的参数叫超参数,每组超参数都采用交叉验证来进行评估。如果含有多个超参数,就采用两两组合的方式,对每组进行交叉验证。网格搜索包含交叉验证,训练模型,所以行了交叉验证就不需要训练模型

接口:ssklearn.model_selection.GridSearchCV(estimator,param_grid=None,cv=None)

输入参数:

  • estimator:估计器
  • param_grid:估计器参数{dict}{‘n_neighborrs’:{1,3,5}}
  • cv:指定几折交叉验证
  • fit:输入训练数据
  • score:准确率

结果

  • best_score:在交叉验证中验证最好的结果
  • besst_estimator—_:最好的参数模型
  • cv_results:每次交叉验证后的验证集准确率和训练集准确率结果
# coding:utf-8

from sklearn.datasets import fetch_20newsgroups
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.feature_extraction.text import TfidfVectorizer  # 文本特特征抽取
from sklearn.naive_bayes import MultinomialNB  # 朴素贝叶斯算法
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import classification_report  # 指标


def Gridcv():
    '''
    网格搜索
    :return:
    '''
    news = fetch_20newsgroups(data_home='D:\data', subset='all')
    x_train, x_test, y_train, y_test = train_test_split(news.data, news.target, test_size=0.3)
    # 对数据集进行特征抽取
    tf = TfidfVectorizer()
    # 训练集和测试集中的词按重要性进行统计
    x_train = tf.fit_transform(x_train)
    # print(tf.get_feature_names())
    x_test = tf.transform(x_test)
    # knn算法
    knn = KNeighborsClassifier(n_neighbors=5)
    # 进行网格搜索
    # 构造参数值进行搜索
    param = {'n_neighbors': [3, 5, 10]}
    # 一般cv=10
    gc = GridSearchCV(knn, param_grid=param, cv=2)
    gc.fit(x_train,y_train)
    y_pridict=gc.predict(x_test)
    # 预测准确率
    print('在测试集上的准确率:',gc.score(x_test,y_test))
    print('预测输出:',y_pridict)
    print('在交叉验证上的最好的结果:',gc.best_score_)
    print('最好的参数模型:',gc.best_estimator_)
    print('每个超参数每次交叉验证的结果:',gc.cv_results_)
    return None


if __name__ == '__main__':
    Gridcv()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
决策树和随机森林

信息熵:

E = -Σp(x)logp(x)
  • 1

信息熵越大不确定性越强
信息增益:表示信息不确定性减少的程度,信息增益越大作为最新的决策节点。ID3是信息增益最大的原则,C4.5是信息增益比最大,CART 1. 回归树:平方误差最小 2. 分类树:基尼系数最小原则,划分更加细致,sklearn默认划分依据
优点:企业可视化,需要较少的数据,不需要归一标准化
缺点:树过于复杂,过拟合

  • 改进:
  1. 剪枝cart算法(决策树api中已经实现)
  2. 随机森林

接口:sklearn.tree.DecisionClassifer(criterion=‘gini’,max_depth=None,random_state=None,min_samples_split=2,min_samples_leaf=1)
输入参数:

  • criterion:默认是’gini’系数,也可以是熵’entropy’
  • max_depth:树深度的大小
  • random_state:随机树种子
  • min_samples_split,min_samples_leaf 剪枝
  • mathod:
  • decision_path:返回决策树的路径
  • 决策树的保存
    sklearn.tree.export_graphviz() 导出DOT格式,tree.export_graphviz(estimator,fout_file=‘tree.dot’,feature_names=[","])
  • 工具:将dot转化成pdf,png
# coding : utf-8

import pandas as pd
from sklearn.feature_extraction.dict_vectorizer import DictVectorizer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier,export_graphviz

def decision_tree():
    # 读取泰坦尼克号数据
    rawData = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt')
    # 处理数据找出特征值和目标值
    target = rawData['survived']
    data = rawData[['pclass', 'age', 'sex']]
    # 缺失值处理
    data['age'].fillna(data['age'].mean(),inplace=True)
    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25)
    dicVect = DictVectorizer(sparse=False)
    x_train = dicVect.fit_transform(x_train.to_dict(orient='records'))
    x_test = dicVect.transform(x_test.to_dict(orient='records'))
    # 使用决策树
    tree=DecisionTreeClassifier(max_depth=5)
    print(dicVect.get_feature_names())
    # 导出决策树的结构
    tree.fit(x_train,y_train)
    export_graphviz(tree,out_file='./tree.dot',feature_names=list(dicVect.get_feature_names()))
    print('预测值:',tree.predict(x_test))
    print('准确度:',tree.score(x_test,y_test))
    return None


if __name__ == '__main__':
    decision_tree()

  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34

安装graphviz

集成学习:建立几个模型组合来解决单一预测问题,生成多个分类器/模型,各自独立学习和做出预测,最后在结合,优于任何一个单分类做出的预测

随机森林是包含多个决策树的分类器,效果优于单个树,输出类别是由多个树输出类别的众数决定

  • 假设有N个样本,M个特征,算法步骤:
  1. 随机从N个样本中选出一个,重复N次(有放回的抽取,所以有可能重复)
  2. 随机选m<M个特征,建立决策树
  3. 采用bootstrap抽样

随机森林是比较好的机器学习方法,可以用于特征数和样本数的数据集上,不需要降维

api接口:
sklearn.ensemble.RandomForestClassifier(n_estimators=10,criterion=‘gini’,max_depth=None,bootstrap=True,random_state=None)

  • n_estimators:决策树的数量
  • criterion:分割特征的测量方法,默认是’gini’
  • max_depth:树的最大深度 5,8,15,25,30
  • max_features=‘auto’ 每个决策树的最大特征数量
    ‘sqrt’ ‘auto’:sqrt(n_features)
    ‘log2’:log2(n_features)
    None:n_features
    bootstrap:是否在构建树时使用放回抽样
# coding:utf-8

from sklearn.tree import DecisionTreeClassifier
from sklearn.ensemble import RandomForestClassifier
from sklearn.feature_extraction import DictVectorizer
from sklearn.model_selection import train_test_split,GridSearchCV
import pandas as pd


def random_forest():
    # 读取泰坦尼克号数据
    rawData = pd.read_csv('http://biostat.mc.vanderbilt.edu/wiki/pub/Main/DataSets/titanic.txt')
    # 处理数据找出特征值和目标值
    target = rawData['survived']
    data = rawData[['pclass', 'age', 'sex']]
    # 缺失值处理
    data['age'].fillna(data['age'].mean(), inplace=True)
    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25)
    dicVect = DictVectorizer(sparse=False)
    x_train = dicVect.fit_transform(x_train.to_dict(orient='records'))
    x_test = dicVect.transform(x_test.to_dict(orient='records'))
    # 使用随机森林
    rf=RandomForestClassifier()
    params={'n_estimators':[100,120,300,500,800,1200],'max_depth':[5,8,15,30]}
    # 网格搜索与交叉验证
    gc=GridSearchCV(rf,param_grid=params,cv=2)
    gc.fit(x_train,y_train)
    print('准确率',gc.score(x_test,y_test))
    print('选择的参数模型',gc.best_params_)
    return None

if __name__=='__main__':
    random_forest()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
回归算法

目标值是连续型的数据就用回归算法
回归性能评估:采用均方误差评价

Δ = \frac{1}{m}Σ^m_{i=1}(y^i-\overline{y})
  • 1
  • API
    sklearn.metrics.mean_squared_error(y_true,y_pred)

  • 算法的过拟合和欠拟合

  • 欠拟合:模型误差大,算法复杂度小,考虑因素小,在训练集和训练集外均不能获得好的拟合效果,可以增加数据的特征数量

  • 过拟合:模型误差大,算法复杂度大,考虑太多因素,本来不是分类的因素考虑了,在训练集上效果好,在训练集以外不能很好拟合数据,过拟合。可以去消除一些关联性强的数据特征(过滤低方差特征 嵌入式如正则化 减少高次项的影响,缩小高次项的权重; 决策树和神经网络)。网格搜索交叉验证的结果即训练集和测试集的结果

第一种回归算法:线性回归算法

针对算法优化策略,使误差(损失)函数最小

  • 最小二乘法:寻找最优化的w 公式1
w= (X^TX)^{-1}X^Ty    
  • 1

其中X为特征值矩阵,y为目标值矩阵。速度太慢

  • 梯度下降
    指定α是学习速率,和方向寻找最优化目标,一般采用这个算法去寻找最优化方法

API
sklearn.linear_model.LinearRegression
正规方程:coef 回归系数 容易出现过拟合
sklearn.linear_model.SGDRegression
梯度下降 数据量大时使用 coef 回归系数

  • Ridge
    解决过拟合问题,具有L2正则化的最小二乘法,病态数据较多时使用

API
sklearn.linear_model.Ridge(alpha=1.0)

  • alpha: 正则化力度 值越大权重越小趋近于0 [0-1] 小数 [1-10] 整数

  • coef_:回归系数

  • 案例:

  1. 获取波士顿房价
  2. 分割数据集
  3. 标准化(KNN 线性回归算法需要标准化原因见公式1,标准化后需要用inverse_trainsform进行还原 )
  4. 使用LinearRegression和SGDRegression进行预测
  • 线性回归的例子
# coding:utf-8

from sklearn.datasets import load_boston
from sklearn.linear_model import LinearRegression, SGDRegressor,Ridge
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.feature_extraction.text import TfidfVectorizer, CountVectorizer
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.ensemble import RandomForestClassifier
import numpy as np
from sklearn.metrics import mean_squared_error


def liner():
    '''
    线性回归
    :return:
    '''
    # 获取数据
    boston_data = load_boston()

    # 分割数据
    x_train, x_test, y_train, y_test = train_test_split(boston_data.data, boston_data.target, test_size=0.25)

    # 标准化 特征值和目标值都需要标准化处理
    std_x = StandardScaler()  # 特征值 0.19必须转化为二维
    x_train = std_x.fit_transform(x_train)
    x_test = std_x.transform(x_test)
    std_y = StandardScaler()  # 目标值
    y_train = std_y.fit_transform(y_train.reshape(-1, 1))
    y_test = std_y.transform(y_test.reshape(-1, 1))

    # estimator 预测
    lr = LinearRegression()  # 正规方程求解
    lr.fit(x_train, y_train)
    print(lr.coef_)  # 参数,回归系数
    # 预测测试集的结果,标准化的数据偏小,需要反标准化
    print('正规方程预测价格:', std_y.inverse_transform(lr.predict(x_test)))
    print('正规方程均方误差',mean_squared_error(std_y.inverse_transform(y_test),std_y.inverse_transform(lr.predict(x_test))))

    sgd = SGDRegressor()  # 梯度下降求解,sklearn不需要指定学习率
    sgd.fit(x_train, y_train)
    print(sgd.coef_)  # 参数,回归系数
    # 预测测试集的结果,标准化的数据偏小,需要反标准化
    print('梯度下降预测价格:', std_y.inverse_transform(sgd.predict(x_test)))
    print('梯度下降均方误差',mean_squared_error(std_y.inverse_transform(y_test),std_y.inverse_transform(sgd.predict(x_test))))

    rd = Ridge(alpha=1.0)  # 岭回归,alpha是回归力度,越大权重越小 ,趋近于0
    rd.fit(x_train, y_train)
    print(rd.coef_)  # 参数,回归系数
    # 预测测试集的结果,标准化的数据偏小,需要反标准化
    print('岭回归预测价格:', std_y.inverse_transform(rd.predict(x_test)))
    print('岭回归均方误差', mean_squared_error(std_y.inverse_transform(y_test), std_y.inverse_transform(rd.predict(x_test))))
    return None


if __name__ == '__main__':
    liner()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
数据模型的保存和加载

from sklearn.externals import joblib

保存:joblib.dump(rf,‘test.pkl’)
加载:estimator=joblib.load(‘test.pkl’)
保存格式:pkl

逻辑回归

二分类问题,预测的是一个概率,判别模型。已经带有正则化的过程,有正则化力度系数。解决过拟合问题。典形应用例如广告被点击的概率 ,是否垃圾邮件,是否患病,金融诈骗,虚假账号的判定。简单速度快。基于线性回归。朴素贝叶斯解决多分类,文本分类,没有系数,基于先验概率,生成模型,应用场景的区别。得出的结果都有概率解释。 sigmoid函数的输出值时[0-1],默认0.5作为阈值,sigmoid函数如下

z=\frac{1}{1+e^{-x}}
  • 1

损失误差函数(对数似然函数):

cos(h_θ(x),y)=
\begin{cases}-log(h_θ(x)),&if&y=1
\\-log(1-h_θ(x)),&if&y=0 \end{cases}
  • 1
  • 2
  • 3

均方误差不存在多个最低点,对数似然利用梯度下降法求解,存在局部最优解。利用随机初始化,多次比较最小值,或者调整学习率去优化改善局部最优解的问题 。sklearn已经考虑了这些问题。

完整的损失函数:

cos(h_θ(x),y)=Σ^m_{i=1}-y_ilog(h_θ(x))-(1-y_i)log(1-h_θ(x)))
  • 1

API
sklearn.linear_model.LogisticRegression(penalty=‘12’,C=1.0)

  • Logistic 回归分类器 penalty正则化 C正则化
  • coef_:回归系数

在样本中哪个类比少,就把那个类别作为目标类别,即正样本
例如如果癌症样本少,就把预测癌症作为正样本。癌症预测样本
癌症数据的第一类是id,所以去掉

癌症分析过程:
  1. 网上获取数据(pandas)
  2. 数据缺失值处理、标准化
  3. LogisticRegression估计器流程

pandas.read_csv(’’,names=column_names) names是指定列的名字

# coding :utf-8

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split, GridSearchCV
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import mean_squared_error, classification_report


def Logstic():
    # 自定义列名
    columns = ['Sample code number', 'Clump Thickness ', 'Uniformity of Cell Size ', 'Uniformity of Cell Shape ',
               'Marginal Adhesion', 'Single Epithelial Cell Size ', 'Bare Nuclei ', 'Bland Chromatin ',
               'Normal Nucleoli ', 'Mitoses ', 'Classes']
    cancelData = pd.read_csv('breast-cancer-wisconsin.data', names=columns)
    # 将特殊字符替换成Nan
    cancelData = cancelData.replace(to_replace='?', value=np.nan)
    # 去掉nan值
    cancelData = cancelData.dropna()
    data = cancelData[columns[1:10]]
    target = cancelData[columns[10]]
    # 进行数据分割
    x_train, x_test, y_train, y_test = train_test_split(data, target, test_size=0.25)
    # 线性回归需要标准化处理
    x_std = StandardScaler()
    x_train = x_std.fit_transform(x_train)
    x_test = x_std.transform(x_test)
    # 二分类,分类结果不用特征化,正则化需要调节超参数
    lg = LogisticRegression(C=1.0)
    lg.fit(x_train, y_train)
    print('回归系数',lg.coef_)  # 回归系数
    y_pre = lg.predict(x_test)
    print('预测结果', y_pre)
    print('准确率', lg.score(x_test, y_test))
    # 2对应良性,4对应恶性
    print('召回率', classification_report(y_test, y_pre, labels=[2, 4], target_names=['良性', '恶性']))

    # print(cancelData.head(10))
    return None


if __name__ == '__main__':
    Logstic()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
聚类

聚类一般在分类之前,聚类效果好坏用轮廓系数表示,外部最大化即族群之间,内部最小化族群内部。 sci取值范围[-1,1]之间,在0以上效果就比较好

API
sklearn.cluster.KMeans(n_clusters=8,init=‘k-means++’)
轮廓系数
from sklearn.metrics import silhouette_score

# coding : utf-8
import pandas as pd
from sklearn.decomposition import PCA
from sklearn.cluster import KMeans
import numpy.matlib.plt as plt
from sklearn.metrics import silhouette_score

'''
多个表利用pandas串表,然后利用PCA进行分析
'''


def kmeans():
    # 读取数据表
    priror = pd.read_csv('./data/priror.csv')
    products = pd.read_csv('./data/products.csv')
    order = pd.read_csv('./data/order.csv')
    ailes = pd.read_csv('./data/ailes.csv')
    # 利用pandas合并表
    _mg = pd.merge(priror, products, open=['product_id', 'product_id'])
    _mg = pd.merge(_mg, order, open=['order_id', 'order_id'])
    mdata = pd.merge(_mg, ailes, open=['ailes_id', 'ailes_id'])
    print(mdata.head(10))

    # 建立行列数据,交叉表(特殊的分组)
    cross = pd.crosstab(mdata['user_id'], mdata['ailes'])

    pca = PCA(n_components=0.9)
    finalData = pca.fit_transform(cross)
    km = KMeans(n_clusters=4)
    pre = km.fit(finalData)
    colors=['red','green','white','orange']
    color=[colors[i] for i in pre]
    print('聚类效果',silhouette_score(finalData,pre))

    plt.figure(finalData[:,1],finalData[:,2],color=color)
    return None


if __name__ == '__main__':
    kmeans()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
深度学习:tensorflow

典形应用:图像识别、语音识别、自然语言处理、自动驾驶
突出神经网络:卷积神经网络(图像) 循环神经网络(自然语言处理)

官方网站:tensorflow
框架可以分为计算密集型(tensorflow,cpu,gpu)和IO密集型(web,scrapy,django,http,磁盘)

  • 结构
  1. tensor:张量 即数据,可以是op中存在的数据
    Tensor(“Const:0”, shape=(), dtype=float32)
    const是张量类型,shape张量的形状,0维(),1维(5),二维(5,6),3维(2,3,4) Constant(常量)是值不能改变的一种tensor
    .Placeholder(占位符)先占住一个固定的位置,之后在往里面添加值的一种Tensor,定义在tf.placeholder中
    Variable(变量)是值可以改变的一种tensor,定义在tf.Variable这个类
  2. operation(op) 操作节点,操作运算的操作节点,所有操作都是op,计算标量、向量、矩阵、神经网络、存储恢复、同步、控制流、神经网络组件、变量,只要使用tensorflow的api都是op
  3. graph,图:整个程序结构,相当于是分配一个内存
  4. 会话:运算程序的图,运行图结构,掌握和分配资源(变量、队列、线程)

图:默认已经注册,一组表示tf.Operation计算的单位对象和tf.Tensor表示操作之间的流动的数据单元对象

  • 获取调用
  1. tf.get_default_graph()
  2. op、sess或者tensor的graph属性
  • 定义
    grph = tf.get_default_graph()

tensorflow api地址

变量是一种op,是一种特殊的张量,能够持久化,默认被训练

# coding:utf-8

import os

os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2'  # 取出警告信息
import tensorflow as tf

# 实现一个加法
a = tf.constant(3.0)
b = tf.constant(6.0)
sum1 = tf.add(a, b)
print('图1', a.graph)
print('张量a', a)
print('图1', sum1.graph)
print('op操作sum1', sum1)

# op是一个tensor可以重载
var1 = 1
sum1 = var1 + b
print('op重载:', sum1)

# 默认的图,相当于是分配一个内存
grph = tf.get_default_graph()
print('图1', grph)
# 使用默认图,只能运行一张图,但可以指定图运行,run可以是一个列表
with tf.Session() as sess:
    print('图1', sess.graph)
    print('默认运行图1', sess.run([a, b, sum1]))

# print(a, b, sum1)
# 创建一个图,包含op运算和tensor,使用上下文环境
g = tf.Graph()
with g.as_default():
    c = tf.constant(11.0)
    print('图2', c.graph)

# b 实时提供数据 进行训练,占位符
plt = tf.placeholder(tf.float32, [None, 3])
print('placeholder', plt)

with tf.Session(config=tf.ConfigProto(log_device_placement=True)) as sess0:
    print('placeholder运行', sess0.run(plt, feed_dict={plt: [[1, 2, 3], [4, 5, 6]]}))

# 交互式
tf.InteractiveSession()
print('eval a', a.eval())
print('eval sum1', sum1.eval())
# config=tf.ConfigProto(log_device_placement=True看到运行设备
with tf.Session(graph=g, config=tf.ConfigProto(log_device_placement=True)) as sess1:
    print('指定运行图2', sess1.run(c))
    # 只要有会话的上下文环境就可以使用eval()
    print('指定运行图2 eval c', c.eval())

# 静态和动态形状
plt = tf.placeholder(tf.float32, [None, 2])
print(plt)
plt.set_shape([3, 2])  # 静态形状只能修改一次,只能修改行数 总共6个数
# plt.set_shape([4,2]) #静态形状只能修改一次
print(plt)

plt_reshape = tf.reshape(plt, [2, 3])  # 动态形状数量总数要匹配,可以修改列数 总共6个数
print(plt_reshape)

# 变量张量和常数张量
const = tf.constant([1, 2, 3],name='a')
var = tf.Variable(tf.random_normal([2, 3], mean=0.0, stddev=1.0))
print('变量张量和常数张量', const, '\n', var)

init_op = tf.global_variables_initializer()  # 初始化
with tf.Session() as sess:
    sess.run(init_op)
    # 程序图结构写入文件
    filterWriter = tf.summary.FileWriter('./test', graph=sess.graph)
    print('变量和张量', sess.run([const, var]))





 ~~打印结果~~:
图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0>
张量a Tensor("Const:0", shape=(), dtype=float32)
图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0>
op操作sum1 Tensor("Add:0", shape=(), dtype=float32)
op重载: Tensor("add_1:0", shape=(), dtype=float32)
图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0>
图1 <tensorflow.python.framework.ops.Graph object at 0x000002BEBBA1C6A0>
默认运行图1 [3.0, 6.0, 7.0]
图2 <tensorflow.python.framework.ops.Graph object at 0x000002BEC8135080>
placeholder Tensor("Placeholder:0", shape=(?, 3), dtype=float32)
Device mapping: no known devices.
placeholder运行 [[1. 2. 3.]
 [4. 5. 6.]]
eval a 3.0
eval sum1 7.0
Device mapping: no known devices.
Const: (Const): /job:localhost/replica:0/task:0/device:CPU:0
指定运行图2 11.0
指定运行图2 eval c 11.0
Tensor("Placeholder_1:0", shape=(?, 2), dtype=float32)
Tensor("Placeholder_1:0", shape=(3, 2), dtype=float32)
Tensor("Reshape:0", shape=(2, 3), dtype=float32)
WARNING:tensorflow:From C:\Users\Administrator\AppData\Local\Programs\Python\Python37\lib\site-packages\tensorflow\python\framework\op_def_library.py:263: colocate_with (from tensorflow.python.framework.ops) is deprecated and will be removed in a future version.
变量张量和常数张量 Tensor("a:0", shape=(3,), dtype=int32) 
Instructions for updating:
Colocations handled automatically by placer.
 <tf.Variable 'Variable:0' shape=(2, 3) dtype=float32_ref>
变量和张量 [array([1, 2, 3]), array([[ 1.9696811 , -1.3698837 , -0.863022  ],
       [ 0.49489492,  0.21399571,  0.9890076 ]], dtype=float32)]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109

tensorflow的前端系统用来定义程序图的结构,后端系统用来运算图结构

会话 tf.Session() ,使用默认注册的图,只能运行一张图(可以指定运行的图)

会话资源:tf.Variable,tf.QueueBase、tf.ReaderBase,会话结束后需要释放资源

1. sess=tf.Session() sess.run(...):启动 sess.close()
2. with tf.Session() as sess
        sess.run()
Session(config=tf.ConfigProto(log_device_placement=True)看到运行设备
3. # 交互式 tf.InteractiveSession()
print('a',a.eval())
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 线性回归的步骤
  1. 准备数据
  2. 建立模型 权重和偏置 tf.matmul(x,w) 矩阵
  3. 误差函数 tf.square(erro) 平方 tf.reduce_mean(erro) 均值
  4. 梯度下降求学习率 tf.train.GradientDescentOptimizer(learning_rate) learning_rate 学习率
声明:本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号