python学习笔记(10):面向对象

  一、类和实例

    1.类(Class): 用来描述具有相同的属性和方法的对象的集合。它定义了该集合中每个对象所共有的属性和方法。对象是类的实例。

    2.对象:通过类定义的数据结构实例。对象包括两个数据成员(类变量和实例变量)和方法。

    3.类变量:类变量在整个实例化的对象中是公用的。类变量定义在类中且在函数体之外。类变量通常不作为实例变量使用。

    4.实例变量:定义在方法中的变量,只作用于当前实例的类。

    5.对“类”和“对象”的使用:

      类就是一个模板,模板里可以包含多个函数,函数里实现一些功能。

      对象则是根据模板创建的实例,通过实例对象可以执行类中的函数。  

# class Foo:  # 完成类的创建
# # 类中的函数
# def bar(self):
# # 功能阐述
# pass
# # =========完毕==============
# obj = Foo()
# 创建对象的时候,记得在后面加个括号
"""
注意,按照Python通用规则,Class用驼峰式表示(HelloWorld)

而其他的obj等等,都用‘_’隔开(this_is_object),在创建对象的时候要加括号

类中的函数第一个参数必须是self,类中定义的函数叫做“方法”,叫自我指代参数。

self 是个什么鬼呢?它是为了指代它所存在的类Class之中。

比如我们如果有好几个不同的obj被创建成同一个类,

那么有了self,我们的class Foo就能很好的知道哪个指的是自己,不会乱
"""

# 创建类
# class Foo:
# def bar(self):
# print('Bar')
# def hello(self,name):
# print('i am %s' %name) #注意在python中,%s表示格式化一个对象为字符串,%d表示整数,这里表示格式化name为一个字符串
#
# #根据Foo创建的对象
# obj = Foo()
# obj.bar()
# obj.hello('tom')


class Foo:
# 这里我们可以创建一个类级别的变量
# 它不会随着此类创建的变量变化而变化

name = 'Jan'
def bar(self):
print('Bar')
def hello(self,name):
print('you are %s'%self.name)
print('i am %s'%name)
print(' ')

# 根据Foo创建对象
obj1 =Foo()
obj2 = Foo()
obj1.hello('August')
obj2.hello('July')
"""
所以说,这个 self 就是个代指。
代指了自己所在的class。
你可以由 self 点进所指class本身的函数。
由此可见,self 本身作为一个代词,并不一定要叫self。
你也可以用个其他什么来代替。只不过,必须得是这个类的所有子方法的第一个参数
"""
# 用其他代词来进行指代
class Foo:
#这里我们创建一个类级别的变量,它不会由此类的创建而发生变化,
name = 'jane'
def bar(july):
print('Bar')
def hello(july,name):#这里将self改成july,但是其作为第一参数的位置没有变,依旧是Foo Class 的自我指代
print('you are %s' %july.name)
print('i am %s' %name)
print(' ')
# 根据Foo创建的对象
obj1 = Foo()
obj2 = Foo()
obj1.hello('August')
obj2.hello('July')


     2.构造函数:构造函数,是一种特殊的方法。主要用来在创建对象时初始化对象, 即为对象成员变量赋初始值。

      跟所有OOP语言一样,python也是有构造函数的,默认为:

# #构造函数
# class Foo:
#     def __init__(self):  #这就是构造函数,他的职责就是在模型创建的初期就完成一些动作
#         #简单的说就是自定义的初始化步骤,在object创建之初,就将object初始化
#         #同样,它也需要self来指定本身这个class
#         self.name='Jan'
#     def hello(self,name):
#         print('you are %s'%self.name)
#         print('i am %s'%name)
#         print('
')
# #当你创建一个Foo类的时候,Init会被自动的跑一遍
# 
# obj = Foo()
# #在这个例子中,我们默认给self自己的name变量,赋值为‘Jan’
# #此刻,当我们调用Foo的hello()方法的时候,hello自己name变量就被赋值为'July'
# obj.hello('July')

    3.init是可以带更多的参数的,用以初始化我们的class本身。

    比如说,你要初始化一个类的时候要用到一些外部参数:

#创建类
class Foo:
    def __init__(self,name2):#可以在这两里附加上一些参数
        #这些参数将是你创建一个Foo类时的一个必要条件
        self.name = name2
    def hello(self,name):
        print('you are %s'%self.name)
        print('i am %s' %name)
        print('
')
#当你创建一个Foo类的时候,init会自动跑一遍
#此刻可以不直接跑Foo,需要填入一个参数:name2
obj1 = Foo('jack')
obj1.hello('stone')

由楼上这些例子,我们大概可以知道整个Python的OOP概念了:

Class(类)就是一个把一堆Object(对象?)集合起来的地方。

在这里,无论是变量还是方法,他们享有基本一样的层级概念。只不过,方法要做一点事儿,而变量直接就是一个值。

  二、访问限制

我们刚刚看到,在调用obj的时候,可以直接调出name或者使用hello()。那么我们怎么知道什么时候可以调用他们,什么时候不可以呢?

在Class内部,可以有属性和方法,而外部代码可以通过直接调用实例变量的方法来操作数据,这样,就隐藏了内部的复杂逻辑。如果要让内部属性不被外部访问,可以把属性的名称前加上两个下划线__,在Python中,实例的变量名如果以__开头,
就变成了一个私有变量(private),只有内部可以访问,外部不能访问
举个学生的例子,我们可以用一个学生类来存储学生的信息,但是我们在外部可以接触到name,那么其实我们就是可以直接修改name的,这是不安全的

  三、继承和多态以及多重继承

在Python中展现面向对象三大特性:

面向对象的三大特性是指:封装、继承和多态。

封装

指的就是把内容封装到某个地方,用于日后调用

它需要:

  • 把内容封装在某处

  • 从另一处调用被封装的内容

 

通过对象直接调用

我们可以在存完一个内容以后,在类以外的地方,通过这个类的对象,来直接”点“调用

In [17]:
class Student:
    # 假定我们初始化一个Student类的时候要做的就是,记录下每个学生的名字和年龄
    def __init__(self, name, age):
        self.name = name
        self.age = age  
    # 至此,我们用self指代student本身,并用name和age存下了他们的年龄和名字

    # === 完毕 ===

#此时,我们新建一个学生
obj1 = Student('July', 18)
print(obj1.name)    # 直接调用obj1对象的name属性
print(obj1.age)   # 直接调用obj1对象的age属性
obj2 = Student('Aug', 73)
print(obj2.name)    # 直接调用obj2对象的name属性
print(obj2.age)     # 直接调用obj2对象的age属性
 
July
18
Aug
73
 

通过self间接调用

执行类中某一个方法时,通过self来调用了类自己的变量

In [18]:
class Student:
    
    def __init__(self, name, age):
        self.name = name
        self.age = age  
    
    def detail(self):
        print(self.name)
        print(self.age)

    # === 完毕 ===

#此时,我们新建一个学生
obj1 = Student('July', 18)
obj1.detail() #Python默认将obj1传给self,所以其实我们做的是obj1.detail(obj1)
# 那么,detail()内部的样貌其实就是:
# print(obj1.name)
# print(obj1.age)
obj2 = Student('Aug', 73)
obj2.detail()
 
July
18
Aug
73
 

综上所述,对于面向对象的封装来说,其实就是使用构造方法将内容封装到 对象 中,然后通过对象直接或者self间接获取被封装的内容。

 

继承

继承,面向对象中的继承和现实生活中的继承相同,即:子可以继承父的内容(爸爸有的儿子都有)。

例如,每个学生都有名字和年龄,木有问题。我们可以把这个作为我们的父亲类。

但是,每个学生自己,可能有自己不同的”方法“,比如,每个人有每个人不同的外号,不同的口号,不同的饮食习惯,不同的。。。。。

In [28]:
# 我们首先创建一个学生类,这个类是所有学生的爸爸
class Student:
    
    def __init__(self, name, age):
        self.name = name
        self.age = age  
    
    def detail(self):
        print(self.name)
        print(self.age)

# 然后,我们创建一个小学生类,小学生特点是,LOL sala无敌
class PrimaryStudent(Student):#因为是继承于学生类,所以我们写在括号内
    # 这里我们可以不写构造函数,于是我们就是直接沿用Student类的构造函数
    def lol(self): # 我们有一些新的独有的方法,会被叠加起来
        print('不服sala!')
    
# 接下来,我们创建一个大学生类,大学生特点是,额,每个人都有个妹子。。
class CollegeStudent(Student):
    def __init__(self, name, age, gf): #这里,我们改写一下构造函数
        # 于是爸爸的init会被直接overwrite
        self.name = name
        self.age = age
        self.gf = gf
    def gf_detail(self):
        print(self.gf)

# 来,我们来创建一下
obj1 = PrimaryStudent('小王', 7)
obj1.lol() # 独有的方法
obj1.detail()#继承与爸爸的方法

obj2 = CollegeStudent('王思聪', 29, '张雨馨')
obj2.detail()
obj2.gf_detail()
 
不服sala!
小王
7
王思聪
29
张雨馨
 

所以,对于面向对象的继承来说,其实就是将多个类共有的方法提取到父类中,子类仅需继承父类而不必一一实现每个方法。

这样可以极大的提高效率,减少代码的重复。

 

问题来了,如果我想多认个干爹呢?

Python和Java/C#的不同就是,Python可以多类继承,也就是,可以认很多干爹

但是干爹多了,就出了问题了。继承的时候,从谁先开始?

有两种方式,分别是深度优先和广度优先

  • 当本身的类是经典类的时候,就按照深度优先方式查找继承的方法 (即,找到一个爸爸,继续找这个爸爸的爸爸,爸爸的爸爸的爸爸。。。)

  • 当本身的类是新式类的时候,就按照广度优先的方式查找 (即,找到一个爸爸,再找下一个爸爸,再找下一个爸爸,平辈之间查找)

那么为什么有经典类新类之分呢?

这是个历史遗留问题,新类 统一了类(class)和类型(type),所以其实也是社区推荐的写法,只不过。。很多程序员都很懒。。

在2.2之前,比如2.1版本中,类和类型是不同的,如a是ClassA的一个实例,那么a.__class__返回 ‘ class    __main__.ClassA‘ ,type(a)返回总是<type 'instance'>。而引入新类后,比如ClassB是个新类,b是ClassB的实例,b.__class__和type(b)都是返回‘class '__main__.ClassB' ,这样就统一了。

于是乎,在新版的Python中,这个经典类和新类的区别已经不存在,都统一使用广度优先。

我们先假设我们还活在python2.2的时代:

In [ ]:
#经典类的写法
class c1:
    pass
class c2(c1):
    pass

#新类的写法
class N1(object):
    pass
class N2(N1):
    pass
 

可见,新类的标志就是,大家的老祖宗继承于一个系统级的类,叫Object

具体的,我们来看看:

  • 经典类
In [36]:
class D:

    def bar(self):
        print('D.bar')


class C(D):

    def bar(self):
        print('C.bar')


class B(D):

    pass


class A(B, C):

    pass

a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去D类中找,如果D类中么有,则继续去C类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> D --> C
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
 
C.bar
 
  • 新类
In [37]:
class D(object):

    def bar(self):
        print('D.bar')


class C(D):

    def bar(self):
        print('C.bar')


class B(D):

    pass

class A(B, C):

    pass

a = A()
# 执行bar方法时
# 首先去A类中查找,如果A类中没有,则继续去B类中找,如果B类中么有,则继续去C类中找,如果C类中么有,则继续去D类中找,如果还是未找到,则报错
# 所以,查找顺序:A --> B --> C --> D
# 在上述查找bar方法的过程中,一旦找到,则寻找过程立即中断,便不会再继续找了
a.bar()
C.bar

当然,对我们先现在而言,两种写法都得出C.bar ;这说明,已经木有区别了

class F1:
    pass

# 假设,S1是我们的正统类,它继承于根正苗红的F1,是我们的正统类
class S1(F1):
    def show(self):
        print('S1.show')

# S2是路人甲,是个歪瓜裂枣,但是他自己也有一个叫show的方法。
class S2:
    def show(self):
        print('S2.show')
        
        
# 在Java或C#中定义函数参数时,必须指定参数的类型,也即是说,我们如果用
# Java写下面的Func,需要告知,obj是F1类还是其他什么东西。
# 如果限定了F1,那么S2是不可以被采纳的。
# 然而,在Python中,一切都是Obj,它不care你到底是什么类,直接塞进去就可以

def Func(obj):
    """Func函数需要接收一个F1类型或者F1子类的类型"""
    obj.show()
    
s1_obj = S1()
Func(s1_obj) # 在Func函数中传入S1类的对象 s1_obj,执行 S1 的show方法,结果:S1.show

s2_obj = S2()
Func(s2_obj) # 在Func函数中传入Ss类的对象 ss_obj,执行 Ss 的show方法,结果:S2.show
 
S1.show
S2.show
 

获取对象信息

当我们拿到一个对象的引用时,如何知道这个对象是什么类型、有哪些方法呢?

用type()

In [1]:
type(123)
Out[1]:
int
In [2]:
type('str')
Out[2]:
str
In [3]:
type(None)
Out[3]:
NoneType
In [4]:
type(abs)
Out[4]:
builtin_function_or_method
In [9]:
class a:
    def __init__(self):
        pass 

type(a)
Out[9]:
type
 

如何用语句判断是不是一种type呢?

In [10]:
type(123)==type(456)
Out[10]:
True
In [11]:
type('abc')==type('123')
Out[11]:
True
In [12]:
type('abc')==type(123)
Out[12]:
False
In [18]:
type('abc')==str
Out[18]:
True
In [22]:
type([])==list
Out[22]:
True

  四、获取对象信息

用isinstance()

isinstance()可以告诉我们,一个对象是否是某种类型(包括继承关系)。

In [23]:
class A:
    pass
class B(A):
    pass
class C(B):
    pass

k=A()
g=B()
y=C()

isinstance(y, C)
Out[23]:
True
In [24]:
isinstance(y, B)
Out[24]:
True
 

同理,isinstance()也可以当type()用

In [25]:
isinstance('a', str)
Out[25]:
True
 

使用dir()

如果要获得一个对象的所有属性和方法,可以使用dir()函数,它返回一个包含字符串的list,比如,获得一个str对象的所有属性和方法:

In [26]:
dir('ABC')
Out[26]:
['__add__',
 '__class__',
 '__contains__',
 '__delattr__',
 '__dir__',
 '__doc__',
 '__eq__',
 '__format__',
 '__ge__',
 '__getattribute__',
 '__getitem__',
 '__getnewargs__',
 '__gt__',
 '__hash__',
 '__init__',
 '__iter__',
 '__le__',
 '__len__',
 '__lt__',
 '__mod__',
 '__mul__',
 '__ne__',
 '__new__',
 '__reduce__',
 '__reduce_ex__',
 '__repr__',
 '__rmod__',
 '__rmul__',
 '__setattr__',
 '__sizeof__',
 '__str__',
 '__subclasshook__',
 'capitalize',
 'casefold',
 'center',
 'count',
 'encode',
 'endswith',
 'expandtabs',
 'find',
 'format',
 'format_map',
 'index',
 'isalnum',
 'isalpha',
 'isdecimal',
 'isdigit',
 'isidentifier',
 'islower',
 'isnumeric',
 'isprintable',
 'isspace',
 'istitle',
 'isupper',
 'join',
 'ljust',
 'lower',
 'lstrip',
 'maketrans',
 'partition',
 'replace',
 'rfind',
 'rindex',
 'rjust',
 'rpartition',
 'rsplit',
 'rstrip',
 'split',
 'splitlines',
 'startswith',
 'strip',
 'swapcase',
 'title',
 'translate',
 'upper',
 'zfill']
 
类似__xxx__的属性和方法在Python中都是有特殊用途的,比如__len__方法返回长度。在Python中,如果你调用len()函数试图获取一个对象的长度,实际上,在len()函数内部,它自动去调用该对象的__len__()方法,所以,下面的代码是等价的:
In [27]:
'ABC'.__len__()
Out[27]:
3
 
我们自己写的类,如果也想用len(myObj)的话,就自己写一个__len__()方法:
In [28]:
class MyObject:
    def __len__(self):
        return 100

obj = MyObject()
len(obj)
Out[28]:
100
 

仅仅把属性和方法列出来是不够的,配合getattr()、setattr()以及hasattr(),我们可以直接操作一个对象的状态:

In [29]:
class MyObject:
    def __init__(self):
        self.x = 9
    def power(self):
        return self.x * self.x

obj = MyObject()
 

紧接着,可以测试该对象的属性:

In [30]:
hasattr(obj, 'x') #有木有属性'x'
Out[30]:
True
In [31]:
obj.x
Out[31]:
9
In [32]:
hasattr(obj, 'y') # 有属性'y'吗?
Out[32]:
False
In [33]:
setattr(obj, 'y', 19) # 设置一个属性'y'
In [34]:
hasattr(obj, 'y') # 有属性'y'吗?
Out[34]:
True
In [35]:
getattr(obj, 'y') # 获取属性'y'
Out[35]:
19
In [36]:
obj.y # 获取属性'y'
Out[36]:
19
 

可以传入一个default参数,如果属性不存在,就返回默认值:

In [37]:
getattr(obj, 'z', 404) # 获取属性'z',如果不存在,返回默认值404
Out[37]:
404
 

也可以获得对象的方法:

In [38]:
hasattr(obj, 'power') # 有属性'power'吗?
Out[38]:
True
In [39]:
getattr(obj, 'power') # 获取属性'power'
Out[39]:
<bound method MyObject.power of <__main__.MyObject object at 0x1043cb668>>
In [40]:
fn = getattr(obj, 'power') # 获取属性'power'并赋值到变量fn
In [41]:
fn # fn指向obj.power
Out[41]:
<bound method MyObject.power of <__main__.MyObject object at 0x1043cb668>>
In [42]:
fn() # 调用fn()与调用obj.power()是一样的
Out[42]:

  五、实例属性和类属性

由于Python是动态语言,根据类创建的实例可以任意绑定属性。

给实例绑定属性的方法是通过实例变量,或者通过self变量:

In [1]:
class Student(object):
    def __init__(self, name):
        self.name = name

s = Student('Bob')
s.score = 90
 

但是,如果Student类本身需要绑定一个属性呢?可以直接在class中定义属性,这种属性是类属性,归Student类所有:

In [2]:
class Student(object):
    name = 'Student'
 

我们来用一个例子说明一下实例与类的属性差异:

In [3]:
class Student(object):
    name = 'Student'

s = Student() # 创建实例s
print(s.name) # 打印name属性,因为实例并没有name属性,所以会继续查找class的name属性
 
Student
In [4]:
print(Student.name) # 打印类的name属性
 
Student
In [6]:
s.name = 'Michael' # 给实例绑定name属性
print(s.name) # 由于实例属性优先级比类属性高,因此,它会屏蔽掉类的name属性
 
Michael
In [7]:
print(Student.name) # 但是类属性并未消失,用Student.name仍然可以访问
 
Student
In [8]:
del s.name # 如果删除实例的name属性
In [9]:
print(s.name) # 再次调用s.name,由于实例的name属性没有找到,类的name属性就显示出来了
 
Student
 

从上面的例子可以看出,在编写程序的时候,千万不要把实例属性和类属性使用相同的名字,因为相同名称的实例属性将屏蔽掉类属性,但是当你删除实例属性后,再使用相同的名称,访问到的将是类属性。

 

模块和包

Python的程序由包(package)、模块(module)和函数组成。包是由一系列模块组成的集合。模块是处理某一类问题的函数和类的集合。

包就是一个完成特定任务的工具箱,Python提供了许多有用的工具包,如字符串处理、图形用户接口、Web应用、图形图像处理等。这些自带的工具包和模块安装在Python的安装目录下的Lib子目录中。

注意:
包必须至少含有一个__int__.py文件按,该文件的内容可以为空。__int__.py用于标识当前文件夹是一个包。

模块

在python中一个文件可以被看成一个独立模块,而包对应着文件夹,模块把python代码分成一些有组织的代码段,通过导入的方式实现代码重用。

导入模块时,是按照sys.path变量的值搜索模块,sys.path的值是包含每一个独立路径的列表,包含当前目录、python安装目录、PYTHONPATH环境变量,搜索顺序按照路径在列表中的顺序(一般当前目录优先级最高)。

想看自己的Python路径,大家可以

import sys
print(sys.path)

如果你发现你在某个地方写的文件(包)import错误,你就可以看看这个sys.path是否囊括了你那批文件的根目录。

 

导入模块

使用import语句(不管是你自己写的,还是你下载的别人的)

import module1
import module2
import module3

import module1,module2,module3

这两种方式的效果是一样的,但是第一种可读性比第二种好,推荐按照下面的顺序导入模块,并且一般在文件首部导入所有的模块

python标准库
第三方模块
应用程序自定义模块

使用from-import语句导入模块的属性

单行导入

from module import name1,name2,name3

多行导入

from module import name1,name2,name3

导入全部属性(由于容易覆盖当前名称空间中现有的名字,所以一般不推荐使用,适合模块中变量名很长并且变量很多的情况)

from module import *

自定义导入模块名称

就是为了用的时候方便好记。

import simplejson as json

包将有联系的模块组织在一起,有效避免模块名称冲突问题,让应用组织结构更加清晰。 一个普通的python应用程序目录结构:

app/
__init__.py
a/
__init__.py
a.py
b/
__init__.py
b.py

app是最顶层的包,a和b是它的子包,可以这样导入:

from app.a import a
from app.b.b import test

a.test()
test()
上面代码表示:导入app包的子包a和子包b的属性test,然后分别调用test方法。
每个目录下都有__init__.py文件,这个是初始化模块,from-import语句导入子包时需要它,可以在里面做一些初始化工作,也可以是空文件。ps:__init__.py定义的属性直接使用 顶层包.子包 的方式导入,如在目录a的__init__.py文件中定义init_db()方法,调用如下:
from app import a

a.init_db()
 

实战

我们现在已经完全掌握了使用包,自己定义类,组件一个可运行的程序的方法

现在我们可以专注于Machine Learning方面,来看看实战是怎么运用这些知识的。

In [15]:
from sklearn import svm, datasets

class Dataset:
    # 我们创造一个dataset的类,这个类会帮我们下载相关的数据集,
    # 并给我们分类好x,y
    def __init__(self, name):
        # 告诉类,我们需要哪一个数据集
        # 我们有两个选择,一个是'iris'一个是'digits'
        self.name = name
        
    def download_data(self):
        # 从sklearn的自带集中下载我们指定的数据集
        if self.name == 'iris':
            # 这里是sklearn自带的数据集下载方法,更多信息可以参照官网
            self.downloaded_data = datasets.load_iris()
        elif self.name == 'digits':
            self.downloaded_data = datasets.load_digits()
        else:
            # 如果不是我们预想的两种数据集,则报错
            print('Dataset Error: No named datasets')
    
    def generate_xy(self):
        # 通过这个过程来把我们的数据集分为原始数据以及他们的label
        # 我们先把数据下载下来
        self.download_data()
        x = self.downloaded_data.data
        y = self.downloaded_data.target
        print('
Original data looks like this: 
', x)
        print('
Labels looks like this: 
', y)
        return x,y
    
    def get_train_test_set(self, ratio):
        # 这里,我们把所有的数据分成训练集和测试集
        # 一个参数要求我们告知,我们以多少的比例来分割训练和测试集
        # 首先,我们把XY给generate出来:
        x, y = self.generate_xy()
        
        # 有个比例,我们首先得知道 一共有多少的数据
        n_samples = len(x)
        # 于是我们知道,有多少应该是训练集,多少应该是测试集
        n_train = n_samples * ratio
        # 好了,接下来我们分割数据
        X_train = x[:n_train]
        y_train = y[:n_train]
        X_test = x[n_train:]
        y_test = y[n_train:]
        # 好,我们得到了所有想要的玩意儿
        return X_train, y_train, X_test, y_test
# ====== 我们的dataset类创造完毕=======
 

接下来,我们在main中code以下来调用我们自己写的类:

In [16]:
# 比如,我们使用digits数据集
data = Dataset('digits')
# 接着,我们可以用0.7的分割率把xy给分割出来
X_train, y_train, X_test, y_test = data.get_train_test_set(0.7)
 
Original data looks like this: 
 [[  0.   0.   5. ...,   0.   0.   0.]
 [  0.   0.   0. ...,  10.   0.   0.]
 [  0.   0.   0. ...,  16.   9.   0.]
 ..., 
 [  0.   0.   1. ...,   6.   0.   0.]
 [  0.   0.   2. ...,  12.   0.   0.]
 [  0.   0.  10. ...,  12.   1.   0.]]

Labels looks like this: 
 [0 1 2 ..., 8 9 8]
 
/Users/JiahaoRBC/Git/.virtualenvs/rbc/lib/python3.5/site-packages/ipykernel/__main__.py:43: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
/Users/JiahaoRBC/Git/.virtualenvs/rbc/lib/python3.5/site-packages/ipykernel/__main__.py:44: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
/Users/JiahaoRBC/Git/.virtualenvs/rbc/lib/python3.5/site-packages/ipykernel/__main__.py:45: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
/Users/JiahaoRBC/Git/.virtualenvs/rbc/lib/python3.5/site-packages/ipykernel/__main__.py:46: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
 

同样,我们也不一定需要自己创造类,我们可以引用第三方库里的类, 比如这里,我们用SVM作为我们的分类器,去训练我们的算法 我们就直接建造一个object,使他成为SVM类

In [17]:
clf = svm.SVC()
 

这里 clf 是 classifier的简称,SVC指的是SVM的classification版本。

因为我们的数据集都是分类问题,所以我们使用SVC()

接下来,我们fit我们的数据(也就是训练我们的数据)

显然,做fit的时候,我们只可以使用训练集

In [18]:
clf.fit(X_train, y_train)
Out[18]:
SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
  decision_function_shape=None, degree=3, gamma='auto', kernel='rbf',
  max_iter=-1, probability=False, random_state=None, shrinking=True,
  tol=0.001, verbose=False)
 

好,现在你的clf已经训练好了,我们来看看它的表现:

我们随便取test集中的一个数据点,并对应它的真实label

In [19]:
test_point = X_test[12]
y_true = y_test[12]
 

我们来看看,我们的clf给出的预测是什么:

In [21]:
clf.predict(test_point)
 
/Users/JiahaoRBC/Git/.virtualenvs/rbc/lib/python3.5/site-packages/sklearn/utils/validation.py:395: DeprecationWarning: Passing 1d arrays as data is deprecated in 0.17 and will raise ValueError in 0.19. Reshape your data either using X.reshape(-1, 1) if your data has a single feature or X.reshape(1, -1) if it contains a single sample.
  DeprecationWarning)
Out[21]:
array([7])
 

再看看真正的label应该是什么:

In [22]:
y_true
Out[22]:
7
 

正确!

那么这样,你们已经学会如何训练数据集并作出新的预测了。

把所有的测试集都导入clf,让他pridict,并看看跟真实的label相差多少。

 

原文地址:https://www.cnblogs.com/bigdata-stone/p/10192419.html