机器学习入门(一)科学计算库Numpy

1、概述

因为搬家和结婚的事比较忙,好久没更新博客了,TensorFlow的学习进度到了人脸识别,但是,总感觉自己都没写多少代码,这样跟学习Linux只会ls和cd命令有何区别?所以,我打算,更深入的学习机器学习,毕竟深度学习的一些算法也是从机器学习中来的。学习TensorFlow的时候,经常用到Numpy库,当时也没去深入的学习这个库,现在就从这个库开始新的征程。

2、Numpy简介

NumPy是Python语言的一个扩充程序库。支持高级大量的维度数组与矩阵运算,此外也针对数组运算提供大量的数学函数库。Numpy内部解除了Python的PIL(全局解释器锁),运算效率极好,是大量机器学习框架的基础库!(引自简书)

Numpy内置函数的处理数据的速度是C语音级别的,所以,在实际应用中,应该尽量使用内置函数。

3、numpy.genfromtxt

Numpy.genfromtxt函数可以从TXT文本中取出数据并进行处理。用代码来说明吧。

新建文本文件hello.txt,里面只有一行,hello python 123。数据准备好了,代码如下,

import numpy as np
myData = np.genfromtxt('hello.txt')
print(type(myData))
print(myData)

运行结果如下,

<class 'numpy.ndarray'>

[ nan  nan 123.]

可以看到,其返回的结果的数据类型为numpy.ndarray。而前面两个值为“nan”,第三个值为123,说明,genfromtxt函数默认处理的数据类型为float,而默认的分隔符为空格。那么,我们想让结果为[‘hello’ ‘python’ ‘123’]怎么做呢?代码如下,

import numpy as np
myData = np.genfromtxt('hello.txt', dtype=str)
print(type(myData))
print(myData)

运行结果为,

<class 'numpy.ndarray'>

['hello' 'python' '123']

如果将hello.txt的内容改为,

id,name,math,english
1,wilf,61,66
2,momo,100,99

运行结果为,

<class 'numpy.ndarray'>

['id,name,math,english' '1,wilf,61,66' '2,momo,100,99']

这不符合我们一般想要的数据形式,怎么办?genfromtxt函数可以指定分隔符,代码如下,

import numpy as np
myData = np.genfromtxt('hello.txt', dtype=str, delimiter=',')
print(type(myData))
print(myData)

运行结果为,

<class 'numpy.ndarray'>

[['id' 'name' 'math' 'english']

 ['1' 'wilf' '61' '66']

 ['2' 'momo' '100' '99']]

如果要处理数据的话,一般第一行的标题我们也不需要,应该将其去掉,代码如下,

import numpy as np
myData = np.genfromtxt('hello.txt', dtype=str, delimiter=',', skip_header=1)
print(type(myData))
print(myData)
print(myData[1, 1])

运行结果为,

<class 'numpy.ndarray'>

[['1' 'wilf' '61' '66']

 ['2' 'momo' '100' '99']]

momo

genfromtxt函数还有很多参数,用到再看咯。那怎么看呢?Linux想查c函数的用法时有个man的命令,Numpy也有类似的help函数,比如想查看genfromtxt函数的用法,运行如下代码即可,

import numpy as np
print(help(np.genfromtxt))

运行结果为,

这里会打印出每个参数的含义,以及一些使用示例。

4、numpy.array

如果想创建数组,可以使用numpy.array函数,代码如下,

import numpy as np
myarray = np.array([1, 2, 3, 4])
myarray1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
print(myarray)
print(myarray1)

运行结果,

[1 2 3 4]

[[1 2 3 4]

 [5 6 7 8]]

还可以获取矩阵的某部分,代码如下,

import numpy as np
myarray1 = np.array([[1, 2, 3],
                     [4, 5, 6],
                     [7, 8, 9]])
print('-------------')
print('获取第2-3行')
print(myarray1[1:3])
print('-------------')
print('获取首行到第2行')
print(myarray1[:2])
print('-------------')
print('获取第2行到尾行')
print(myarray1[1:])
print('-------------')
print('获取首列到第2列')
print(myarray1[:,:2])
print('-------------')
print('获取第2-3行,第2-3列')
print(myarray1[1:3,1:3])

运行结果,

-------------

获取第2-3行

[[4 5 6]

 [7 8 9]]

-------------

获取首行到第2行

[[1 2 3]

 [4 5 6]]

-------------

获取第2行到尾行

[[4 5 6]

 [7 8 9]]

-------------

获取首列到第2列

[[1 2]

 [4 5]

 [7 8]]

-------------

获取第2-3行,第2-3列

[[5 6]

 [8 9]]

5、shape

numpy.shape是查看矩阵维度的,代码如下,

import numpy as np
myarray = np.array([1, 2, 3, 4, 5])
myarray1 = np.array([[1, 2, 3, 4], [5, 6, 7, 8]])
myarray2 = np.array([[[1, 2, 3, 4], [5, 6, 7, 8],[9, 0, 0, 0]],[[1, 2, 3, 4], [5, 6, 7, 8],[9, 0, 0, 0]]])
print(myarray.shape)
print(myarray1.shape)
print(myarray2.shape)

运行结果,

(5,)

(2, 4)

(2, 3, 4)

6、数据类型转换

假设一个矩阵里的数据的类型都是str型,我们想把它们全部转成float型,代码如下,

import numpy as np

myArray = np.array(['1', '2', '3'])
print('-----------------------')
print('输出数据类型:')
print(myArray.dtype)
print('-----------------------')
myArray = myArray.astype(float)
print('转换后的数据类型:')
print(myArray.dtype)

运行结果,

-----------------------

输出数据类型:

<U1

-----------------------

转换后的数据类型:

float64

7、输出最大值和最小值

还可以输出矩阵中的最大值和最小值,

import numpy as np

myArray = np.array([[1, 2, 3], [4, 5, 6]])
print('-----------------------')
print('输出最大值:')
print(myArray.max())
print('-----------------------')
print('输出最小值:')
print(myArray.min())

运行结果,

-----------------------

输出最大值:

6

-----------------------

输出最小值:

1

8、求和

如果需要求矩阵行的和或者列的和,代码如下,

import numpy as np

myArray = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]])
print('-----------------------')
print('求行和:')
print(myArray.sum(axis=1))
print('-----------------------')
print('求列和:')
print(myArray.sum(axis=0))

运行结果,

-----------------------

求行和:

[ 6 15 24]

-----------------------

求列和:

[12 15 18]

9、reshape维度转换

Reshape函数可以转换矩阵的维度,上代码,

import numpy as np

myArray = np.arange(12)
print('-----------------------')
print('转换前:')
print(myArray)
print('-----------------------')
print('转换成3行4列的矩阵:')
print(myArray.reshape(3, 4))
print(myArray.reshape(3, 4).shape)
print('-----------------------')
print('转换成4行3列的矩阵:')
print(myArray.reshape(4, 3))
print(myArray.reshape(4, 3).shape)

运行结果,

-----------------------

转换前:

[ 0  1  2  3  4  5  6  7  8  9 10 11]

-----------------------

转换成3行4列的矩阵:

[[ 0  1  2  3]

 [ 4  5  6  7]

 [ 8  9 10 11]]

(3, 4)

-----------------------

转换成4行3列的矩阵:

[[ 0  1  2]

 [ 3  4  5]

 [ 6  7  8]

 [ 9 10 11]]

(4, 3)

10、初始化矩阵

初始化一个值都是0的矩阵,代码如下,

import numpy as np
print(np.zeros((2, 3)))

运行结果,

[[0. 0. 0.]

  1. 0. 0.]]

初始化一个值都是1的矩阵,代码如下,

import numpy as np
print(np.ones((2, 3)))

运行结果,

[[1. 1. 1.]

  1. 1. 1.]]

初始化一个值是随机数的矩阵,代码如下,

import numpy as np
print(np.random.random((2, 3)))

运行结果,

[[0.08325535 0.09373238 0.55359789]

 [0.8212977  0.46203935 0.31433286]]

如果想初始化值为以2递增的向量,怎么办呢?代码如下,

import numpy as np
print(np.arange(0, 10, 2))

运行结果,

[0 2 4 6 8]

如果想初始化值为一个区间的平均值,比如,10到100,分成10份,代码如下,

import numpy as np
print(np.linspace(10, 100, 10))

运行结果,

[ 10.  20.  30.  40.  50.  60.  70.  80.  90. 100.]

 

10、运算

直接上代码,

import numpy as np
a = np.array([5, 10, 15, 20])
b = np.arange(4)
c = np.array([[1, 2, 3], [4, 5, 6]])
d = np.array([[7, 8], [9, 10], [11, 12]])
e = np.array([[7, 8, 9], [10, 11, 12]])
print('-----------------------')
print('求矩阵相减:')
print(a - b)
print('-----------------------')
print('求矩阵减一个固定值:')
print(a - 2)
print('-----------------------')
print('求矩阵乘方:')
print(a ** 2)
print('-----------------------')
print('矩阵比较:')
print(a < 13)
print('-----------------------')
print('矩阵乘法:')
print(c * e)
print('-----------------------')
print('矩阵点乘:')
print(c.dot(d))
print('或者')
print(np.dot(c, d))

运行结果,

-----------------------

求矩阵相减:

[ 5  9 13 17]

-----------------------

求矩阵减一个固定值:

[ 3  8 13 18]

-----------------------

求矩阵乘方:

[ 25 100 225 400]

-----------------------

矩阵比较:

[ True  True False False]

-----------------------

矩阵乘法:

[[ 7 16 27]

 [40 55 72]]

-----------------------

矩阵点乘:

[[ 58  64]

 [139 154]]

或者

[[ 58  64]

 [139 154]]

12、其他操作

求e的指数,

import numpy as np
a = np.arange(3)
print(np.exp(a))

运行结果,

[1.  2.71828183 7.3890561 ]

求平方根,

import numpy as np
a = np.arange(3)
print(np.sqrt(a))

运行结果,

[0.        1.         1.41421356]

取整,

import numpy as np
print(np.floor(np.array([1.1, 2.2, 3.9])))

运行结果,

[1. 2. 3.]

调整矩阵结构,

import numpy as np
a = np.floor(10 * np.random.random((4, 3)))
print('-----------------------')
print('原结构:')
print(a)
print('-----------------------')
print('调整后的结构:')
a.resize((2, 6))
print(a)

运行结果,

-----------------------

原结构:

[[5. 9. 4.]

 [1. 1. 9.]

 [2. 7. 8.]

 [3. 0. 7.]]

-----------------------

调整后的结构:

[[5. 9. 4. 1. 1. 9.]

[2. 7. 8. 3. 0. 7.]]

合并矩阵,

import numpy as np
a = np.floor(10 * np.random.random((2, 3)))
b = np.floor(10 * np.random.random((2, 3)))
print('-----------------------')
print('原矩阵:')
print('a:')
print(a)
print('b:')
print(b)
print('-----------------------')
print('横向合并:')
print(np.hstack((a, b)))
print('-----------------------')
print('纵向合并:')
print(np.vstack((a, b)))

运行结果,

-----------------------

原矩阵:

a:

[[2. 8. 2.]

 [2. 7. 2.]]

b:

[[3. 1. 6.]

 [5. 8. 6.]]

-----------------------

横向合并:

[[2. 8. 2. 3. 1. 6.]

 [2. 7. 2. 5. 8. 6.]]

-----------------------

纵向合并:

[[2. 8. 2.]

 [2. 7. 2.]

 [3. 1. 6.]

 [5. 8. 6.]]

 

拆分矩阵,

import numpy as np
a = np.floor(10 * np.random.random((2, 12)))
b = np.floor(10 * np.random.random((12, 2)))
print('-----------------------')
print('原矩阵:')
print('a:')
print(a)
print('b:')
print(b)
print('-----------------------')
print('横向拆分:')
print(np.hsplit(a, 3))
print('-----------------------')
print('指定横向拆分:')
print(np.hsplit(a, (2, 6)))
print('-----------------------')
print('纵向拆分:')
print(np.vsplit(b, 3))

运行结果,

-----------------------

原矩阵:

a:

[[7. 1. 1. 4. 8. 3. 9. 4. 2. 0. 3. 7.]

 [2. 4. 3. 5. 0. 9. 0. 1. 4. 1. 0. 4.]]

b:

[[2. 7.]

 [7. 4.]

 [8. 8.]

 [2. 0.]

 [5. 0.]

 [8. 5.]

 [0. 5.]

 [8. 7.]

 [0. 5.]

 [3. 3.]

 [6. 6.]

 [8. 4.]]

-----------------------

横向拆分:

[array([[7., 1., 1., 4.],

       [2., 4., 3., 5.]]), array([[8., 3., 9., 4.],

       [0., 9., 0., 1.]]), array([[2., 0., 3., 7.],

       [4., 1., 0., 4.]])]

-----------------------

指定横向拆分:

[array([[7., 1.],

       [2., 4.]]), array([[1., 4., 8., 3.],

       [3., 5., 0., 9.]]), array([[9., 4., 2., 0., 3., 7.],

       [0., 1., 4., 1., 0., 4.]])]

-----------------------

纵向拆分:

[array([[2., 7.],

       [7., 4.],

       [8., 8.],

       [2., 0.]]), array([[5., 0.],

       [8., 5.],

       [0., 5.],

       [8., 7.]]), array([[0., 5.],

       [3., 3.],

       [6., 6.],

       [8., 4.]])]

 

复制矩阵,

import numpy as np
a = np.floor(10 * np.random.random((2, 2)))
print('-----------------------')
print('原矩阵:')
print('a:')
print(a)
print('-----------------------')
print('复制方法一:')
b = a.view()
print(b)
print('-----------------------')
print('复制方法二:')
b = a.copy()
print(b)
print('-----------------------')
print('复制方法三:')
b = a
print(b)

运行结果,

-----------------------

原矩阵:

a:

[[6. 1.]

 [9. 8.]]

-----------------------

复制方法一:

[[6. 1.]

 [9. 8.]]

-----------------------

复制方法二:

[[6. 1.]

 [9. 8.]]

-----------------------

复制方法三:

[[6. 1.]

  1. 8.]]

这三种复制方法有区别吗?当然有啦,下面来分析,

import numpy as np

print('-----------------------')
a = np.arange(5)
print('复制方法一:')
b = a.view()
print('打印b矩阵:')
print(b)
print('分别打印id:')
print(id(a))
print(id(b))
print('修改b矩阵的某个值再打印a矩阵:')
b[1] = 123
print(a)
print('-----------------------')
a = np.arange(5)
print('复制方法二:')
b = a.copy()
print('打印b矩阵:')
print(b)
print('分别打印id:')
print(id(a))
print(id(b))
print('修改b矩阵的某个值再打印a矩阵:')
b[1] = 123
print(a)
print('-----------------------')
a = np.arange(5)
print('复制方法三:')
b = a
print('打印b矩阵:')
print(b)
print('分别打印id:')
print(id(a))
print(id(b))
print('修改b矩阵的某个值再打印a矩阵:')
b[1] = 123
print(a)

运行结果,

-----------------------

复制方法一:

打印b矩阵:

[0 1 2 3 4]

分别打印id:

140140380341152

140140380342912

修改b矩阵的某个值再打印a矩阵:

[  0 123   2   3   4]

-----------------------

复制方法二:

打印b矩阵:

[0 1 2 3 4]

分别打印id:

140140165910736

140140380342992

修改b矩阵的某个值再打印a矩阵:

[0 1 2 3 4]

-----------------------

复制方法三:

打印b矩阵:

[0 1 2 3 4]

分别打印id:

140140380341152

140140380341152

修改b矩阵的某个值再打印a矩阵:

[  0 123   2   3   4]

我们可以看到,用方法1和方法2复制矩阵,两个矩阵的id是不一样的,但是,方法一却共用数据,即不管是修改了a矩阵还是修改了b矩阵的数据,另一个矩阵的数据也随之改变。用方法二复制的矩阵,则两个矩阵完全独立。方法三其实不能算是复制,就是引用,两个矩阵的id和数据完全一样。

扩展矩阵,

import numpy as np
a = np.arange(4)
print('-----------------------')
print('原矩阵:')
print(a)
print('扩展以后的矩阵:')
print(np.tile(a, (3, 2)))

运行结果,

-----------------------

原矩阵:

[0 1 2 3]

扩展以后的矩阵:

[[0 1 2 3 0 1 2 3]

 [0 1 2 3 0 1 2 3]

 [0 1 2 3 0 1 2 3]]

排序,

import numpy as np
a = np.array([1, 5, 2, 9])
print('-----------------------')
print('原矩阵:')
print(a)
print('排序后的矩阵:')
print(np.sort(a, axis=0))
print('排序后的索引:')
print(np.argsort(a))

运行结果,

-----------------------

原矩阵:

[1 5 2 9]

排序后的矩阵:

[1 2 5 9]

排序后的索引:

[0 2 1 3]

 

 

猜你喜欢

转载自blog.csdn.net/rookie_wei/article/details/82941150