标签(空格分隔): 王小草机器学习笔记
python的强大之处不但因为简洁易学高效,还在于她有许多库,可以方便我们得到想要的计算。比如今天讲的numpy库,为python提供了快速的多维数组的处理能力。有人数,numpy库的出现使得python可以像matlab一样去计算了。(matlab是10年前乃至今日仍然大受青睐的草稿本式的编程语言)。
1. 导入Numpy库
要调用numpy库,我们就要导入这个库,导入的语句就一句。
as 后面是重命名,也可以说是缩写,在我们的程序中,我们只要写np,自动就代码numpy。这是约定俗称的一个简称,当其他人阅读你的代码的时候,他们也知道np代表的就是Numpy,所以缩写最好不要自己创新。
2. 使用Aarry创建数组
2.1 通过Array传递List
标准Python的列表(list)中,元素本质是对象。
如:L = [1, 2, 3],需要3个指针和三个整数对象,对于数值运算比较浪费内存和CPU。
因此,Numpy提供了ndarray(N-dimensional array object)对象:存储单一数据类型的多维数组。
创建一维数组:
L = [, , , , , ]
print L
a = np.array(L)
print a
打印结果:
[1, 2, 3, 4, 5, 6]
[1 2 3 4 5 6]
创建多维数组:
嵌套多个list
b = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]])
print b
打印结果:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
2.2 数组大小
查看数组大小
print a.shape
print b.shape
打印结果:
a是6行1列,b是3行4列
(6L,)
(3L, 4L)
强制修改数组大小
1.将3*4的数组改成4*3的数组
b.shape = 4, 3
print b
打印结果:
从(3,4)改为(4,3)并不是对数组进行转置,而只是改变每个轴的大小,数组元素在内存中的位置并没有改变,还是按照1,2,3,4,5…12这样的顺序来排列的。
[[ 1 2 3]
[ 4 5 6]
[ 7 8 9]
[10 11 12]]
2.当某个轴为-1时,将根据数组元素的个数自动计算此轴的长度
b.shape = 2, -1
print b
打印结果:
行是2行,列为-1的话就表示根据行来定,所以是6列
[[ 1 2 3 4 5 6]
[ 7 8 9 10 11 12]]
修改数组大小后成新数组
使用reshape方法,可以创建改变了尺寸的新数组,原数组的shape保持不变
c = b.reshape((4, -1))
print c
创建的新数组,仍然与老数组共享内存,修改任意一个将影响另外一个。
比如修改b数组的第1行第2列的元素为20,再来看b和c两个数组的变化
2.3 获取数组的元素类型
查看数据类型
print a.dtype
print b.dtype
创建指定元素类型的数组
可以通过dtype参数在创建时指定元素类型
d = np.array([[1, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.float)
f = np.array([[1+4j, 2, 3, 4], [5, 6, 7, 8], [9, 10, 11, 12]], dtype=np.complex)
print d
print f
打印结果:分别是浮点型与复数型
[[ 1. 2. 3. 4.]
[ 5. 6. 7. 8.]
[ 9. 10. 11. 12.]]
[[ 1.+4.j 2.+0.j 3.+0.j 4.+0.j]
[ 5.+0.j 6.+0.j 7.+0.j 8.+0.j]
[ 9.+0.j 10.+0.j 11.+0.j 12.+0.j]]
更改元素类型
如果更改元素类型,可以使用astype安全的转换
f = d.astype(np.int)
print f
打印结果:
[[ 1 2 3 4]
[ 5 6 7 8]
[ 9 10 11 12]]
3. 使用函数创建
3.1 arrage
如果生成一定规则的数据,可以使用NumPy提供的专门函数
arange函数类似于python的range函数:指定起始值、终止值和步长来创建数组
和Python的range类似,arange同样不包括终值;但arange可以生成浮点类型,而range只能是整数类型
生成1开始,10结束(不包含10),步长为0.5的一个数组
a = np.arange(, , )
print a
打印结果:
[ 1. 1.5 2. 2.5 3. 3.5 4. 4.5 5. 5.5 6. 6.5 7. 7.5 8.
8.5 9. 9.5]
3.2 linespace
linspace函数通过指定起始值、终止值和元素个数来创建数组,缺省包括终止值
b = np.linspace(1, 10, 10)
print b
打印结果:生成了一个1到10,步长为1的等差数列,并且时前闭后闭的。
[ 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
可以通过endpoint关键字指定是否包括终值 ,默认是包括的。
c = np.linspace(, , , endpoint=False)
print c
打印结果:生成了1到9的10个等差数列
[ 1. 1.9 2.8 3.7 4.6 5.5 6.4 7.3 8.2 9.1]
3.3 logspace
和linspace类似,logspace可以创建等比数列
下面函数创建起始值为10^1,终止值为10^2,有20个数的等比数列
d = np.logspace(, , , endpoint=False)
print d
打印结果:
[ 10. 11.22018454 12.58925412 14.12537545 15.84893192
17.7827941 19.95262315 22.38721139 25.11886432 28.18382931
31.6227766 35.48133892 39.81071706 44.66835922 50.11872336
56.23413252 63.09573445 70.79457844 79.43282347 89.12509381]
下面创建起始值为2^0,终止值为2^10(不包括),有10个数的等比数列
f = np.logspace(, , , endpoint=True, base=)
print f
打印结果:
[
]
3.4 frombuffer, fromstring, fromfile
使用 frombuffer, fromstring, fromfile等函数可以从字节序列创建数组
s = 'ABCDZ'
g = np.fromstring(s, dtype=np.int8)
打印结果:
[65 66 67 68 90]
4. 存取
4.1 常规办法
数组元素的存取方法和Python的标准方法相同
首先我们使用arange创建一个数组a
[0 1 2 3 4 5 6 7 8 9]
获取某个元素
print a[]
获取索引为3的元素
3
获取一组元素,切片[3,6),左闭右开
print a[:]
[3 4 5]
省略开始下标,表示从0开始
print a[:]
[0 1 2 3 4]
下标为负表示从后向前数
print a[:]
[3 4 5 6 7 8 9]
取索引[1,8)步长为2
print a[::]
[1 3 5 7]
步长为-1,即翻转
print a[::-]
[9 8 7 6 5 4 3 2 1 0]
切片数据是原数组的一个视图,与原数组共享内容空间,可以直接修改元素
a[:] = , ,
print a
[ 0 10 20 30 4 5 6 7 8 9]
4.2 整数数组的存取
根据整数数组存取:当使用整数序列对数组元素进行存取时,
将使用整数序列中的每个元素作为下标,整数序列可以是列表(list)或者数组(ndarray)。
使用整数序列作为下标获得的数组不和原始数组共享数据空间。
//创建两个数组
a = np.logspace(, , , base=)
print a
i = np.arange(, , )
print i
//利用i取a中的元素
b = a[i]
print b
打印结果
[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
[0 2 4 6 8]
[ 1. 4. 16. 64. 256.]
//b的元素更改,a中元素不受影响
b[] =
print b
print a
打印结果:b变了,a不变
[ 1. 4. 1.6 64. 256. ]
[ 1. 2. 4. 8. 16. 32. 64. 128. 256. 512.]
4.3 布尔数组的存取
使用布尔数组i作为下标存取数组a中的元素:返回数组a中所有在数组b中对应下标为True的元素
首先生成10个满足[0,1)中均匀分布的随机数
a = np.random.rand()
print a
[ 0.84334711 0.54587789 0.41350371 0.73992619 0.00475762 0.0972838
0.0522206 0.6696739 0.33550459 0.64959176]
大于0.5的元素索引
print a >
[ True True False True False False False True False True]
大于0.5的元素,打印出了一组布尔类型的值,符合条件的为true
b = a[a > ]
print b
[ 0.84334711 0.54587789 0.73992619 0.6696739 0.64959176]
将原数组中大于0.5的元素截取成0.5
a[a > ] =
print a
//b不受影响
print b
[ 0.5 0.5 0.41350371 0.5 0.00475762 0.0972838
0.0522206 0.5 0.33550459 0.5 ]
[ 0.84334711 0.54587789 0.73992619 0.6696739 0.64959176]
4.4 二维数组的切片
生成二维数组
若我们想生成以下这样一个多维数组:
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
[50 51 52 53 54 55]]
可以经过以下几步
先生成行向量,0到60,步长为10的数组。
[ 0 10 20 30 40 50]
将行向量,转化成列向量
[[ 0]
[10]
[20]
[30]
[40]
[50]]
生成一个0到5,步长为1的行向量
[0 1 2 3 4 5]
将列向量b每一列都c行向量
f = b + c
print f
[[ 0 1 2 3 4 5]
[10 11 12 13 14 15]
[20 21 22 23 24 25]
[30 31 32 33 34 35]
[40 41 42 43 44 45]
将上面所有步骤合起来可以用一句代码表示:
a = np.arange(, , ).reshape((-, )) + np.arange()
二维数组的切片
//大括号里,前面的list表示行的索引,后面的list表示列的索引
//比如第一个数提取的是行索引为0列索引为2
print a[(,,,), (,,,)]
//获取行号从3开始(包括3),列号是0,2,5的元素
print a[:, [, , ]]
//创建布尔类型的数组
i = np.array([True, False, True, False, False, True])
//获取为true的行
print a[i]
//获取为true的行的列索引为3的元素
print a[i, ]
打印结果:
[ 2 13 24 35]
[[30 32 35]
[40 42 45]
[50 52 55]]
[[ 0 1 2 3 4 5]
[20 21 22 23 24 25]
[50 51 52 53 54 55]]
[ 3 23 53]
5. 绘图
5.1 绘制正态分布概率密度函数
mu = //均值
sigma = //标准差
//创建一个50个元素的数组,收尾与均值相差三个标准差
x = np.linspace(mu - * sigma, mu + * sigma, )
//根据正太分布的公式写出y
y = np.exp(-(x - mu) ** / ( * sigma ** )) / (math.sqrt( * math.pi) * sigma)
//以x,y为横纵坐标,'r-'表示红色线,'ro-表示红色线加原点',linewidth为线的粗细度
#plot.plot(x, y, 'ro-', linewidth=2)
//或者也可以:用'go'表示绿色原点,markersize为原点大小
plot.plot(x, y, 'r-', x, y, 'go', linewidth=, markersize=)
//有灰色格子
plot.grid(True)
//画出来吧,少年!
plot.show()
图形如下:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIn5GcuMDNyIjNxUDM5AjNxAjMFJUJClTJ1UUJBFUJ4gTJ2UUJRF1LcFzb5NXZ3lXb6d3btRXcpxGNmBje1smZw9CXvF2Yn5WY39CXt92Yu8WdsVnY5pnLjlGdhR3cvw1LcpDc0RHaiojIsJye.png)
接下去,我们再来看几个好玩的画图案例
5.2 损失函数:Logistic损失(-1,1)/SVM Hinge损失/ 0/1损失
x = np.linspace(-, , )
y_logit = np.log( + np.exp(-x)) / math.log()
y_01 = x <
y_hinge = - x
y_hinge[y_hinge < ] =
//label表示标记
plot.plot(x, y_logit, 'r-', label='Logistic Loss', linewidth=)
plot.plot(x, y_01, 'g-', label='0/1 Loss', linewidth=)
plot.plot(x, y_hinge, 'b-', label='Hinge Loss', linewidth=)
plot.grid()
//标记的放的位置,这里是右上角
plot.legend(loc='upper right')
plot.show()
图形画出来如下:
5.3 x^x
x = np.linspace(-1.3, 1.3, 101)
y = f(x)
plot.plot(x, y, 'g-', label='x^x', linewidth=2)
plot.grid()
plot.legend(loc='upper right')
plot.show()
5.4 胸型线
(前方高能。。。)
x = np.arange(, , -)
y = (- * x * np.log(x) + np.exp(-( * (x - / np.e)) ** ) / ) /
//设置画布大小
plot.figure(figsize=(,))
plot.plot(y, x, 'r-', linewidth=)
plot.grid(True)
plot.show()
这个图太辣眼睛了。。。男生心里估计已经浮现过ABCDEF了。。
5.5 心形线
t = np.linspace(, , )
x = * np.sin(t) **
y = * np.cos(t) - * np.cos(*t) - * np.cos(*t) - np.cos(*t)
plot.plot(x, y, 'r-', linewidth=)
plot.grid(True)
plot.show()
嗯,这个图美,愿大家有情人终成眷属
5.6 渐开线
t = np.linspace(, , num=)
x = t*np.sin(t) + np.cos(t)
y = np.sin(t) - t*np.cos(t)
plot.plot(x, y, 'r-', linewidth=)
plot.grid()
plot.show()
关于画函数图,总结规律,其实就是,设置一个x的变量,然后根据某种公式用x得到y的分布,然后把x,y用Plot函数套进去,什么颜色啊,圆点啊,线条粗细啊之类的都可以套模板写。棒棒棒!