机器学习基础知识笔记
- 人工智能基础:需要扎实的数学理论功底:线性代数、统计学和运筹学;Python或R语言的基础知识;NumPy,Pandos,Matplotlib等专用于科学计算的模块库,封装大量API以快速实现矢量计算。
- 机器学习(Machine Learn) :人工智能的入门学习模型分为监督学习模型和非监督学习模型。核心在于学习算法模型的应用,如逻辑回归、随机梯度下降、SVC支持向量机、朴素贝叶斯、K近邻等等。
- 深度学习 (Deep Learn) : 常用的人工智能框架Tensorflow/PyTorch,回归算法模型实现(最小二乘法、数据拟合和残差值,自我实现sklearn中的算法函数进行参数调优)。
- 科学计算与数据分析是人工智能基础,数据学(Dataology)和数据科学(DataScience)是关于数据的科学。主要两个内涵:一个是研究数据本身;另一个是为自然科学和社会科学研究提供一种新方法,称为科学研究数据的方法。大量应用到多维矩阵和矢量计算。
- 机器学习是人工智能的主要领域,也是人工智能的算法核心基础。监督学习模型(特征+标签),非监督学习(只有特征)。前者有分类学习和回归预测,而后者有数据聚类和特征降维。
- 深度学习的概念源于人工神经网络研究,含多隐层的多层感知器就是一种深度学习结构,深度学习通过组合低层特征形成更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。
1. Numpy模块应用基础
- NumPy是高性能科学计算和数据分析的基础模块包,它是科学计算与数据分析中几乎所有高级工具的构建基础。
- ndarray:一个具有矢量算术运算和复杂广播能力的快速且节省空间的多维数组
- 用于对整数组数据记性快速运算的标准数学函数(无需编写循环)
- 用于读取磁盘数据的工具以及用于操作内存映射文件的工具
- 具备线性代数\随机数生成以及傅里叶变换功能
- 用于集成由C\C++\Fortran等语言编写的代码的工具
(1)创建NumPy的数组已经矢量化运算
- 数组很重要,即使不使用复杂的循环语句,也可对数据执行批量了运算,这通常就叫做矢量化运算。
import numpy as np # 定义numpy数组 array = np.array([1,2,3,4,5]) # 创建一维数组 print(array) print([1,2,3,4,5]) print(type(array))
- 大小相等的数组之间的任何算术运算都会将运算应用到元素级。
# numpy数组的矢量计算 print(array**2) # 计算出每个元素的平方 #等价于 for temp in array: print(temp**2) pass print(array**0.5)
# 二维数组的矢量化计算 print(array2d**2) # 三维数组, 多个形状一样的二维数组 array3d = np.array([[[1, 2, 3], [3, 4, 5]], [[6, 7, 8], [9, 10, 11]]]) print(array3d) print(array3d**2)
# 数组的矢量化运算 array1 = np.array([[1, 2, 4], [4, 5, 6]]) array2 = np.array([[7, 8, 9], [10, 11, 12]]) # 形状相同的数组,每个执行算术运算是每个元素都执行相同的运算 print(array1 + array2) print(array1 - array2) print(array1 * array2) print(array1 / array2) print(array1 + 1) print(array1 * 2) print(1 / array1)
(2)查看多维数组的大小和类型
- shape返回一个元组类型(2,4),说明该数组中有两个一维数组组成且每个数组由4个元素组成。
- dtype返回int64,说明该数组中的所有数据类型为整型类型。
# 二维数组,数组是有类型的,使用dtype进行规定 array2d = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]], dtype=np.float64) print(array2d)
(3)快速生成数组
还可以使用zeros()和ones()函数快速创建全零或者全1数组,在创建过程中指定长度和维度。也可以使用eye()创建一个正方的N*N的正方矩阵(对角线为1,其余为0)。以及特殊的diag()函数。
# 快速创建特殊矩阵 arrayZeros = np.zeros(shape=(4, 5), dtype=np.int64) # 浮点数的0并不一定表示0 print(arrayZeros) arrayOnes = np.ones(shape=(4, 5, 6, 7, 8, 9), dtype=np.float64) print(arrayOnes) E = np.identity(5) # 生成一个5x5的单位矩阵 print(E) E2 = np.eye(5, 5, dtype=np.int64) # 是方阵 print(E2) E3 = np.eye(5, 4, dtype=np.int64) # 不是方阵 print(E3) # diag()生成对角线矩阵 D = np.diag([1, 2, 3, 4, 5]) # 用一个一维数组生成矩阵,矩阵的主对角线上是一维数组的数组,其余为0 print(D) D2 = np.diag([1, 2, 3, 4, 5], k=1) # 设置k值后,数组不在主对角线上 print(D2)
(4)使用arange生成数组
# range(start, and ,step) int, arrayld=np.arange(-1, 1, 0.1) # arange(start, and, step),但是可以支持小数,是numpy库中的类 print(arrayld)
matrix()构建矩阵形式现在基本不使用,所以暂时不做了解
(5)使用xx_like()生成数组
# like生成数组 array3 = np.zeros_like(array2d) print(array3)
(6)不同类型的array的转换
# 类型和类型转换 arrayInt = array2d.astype(np.int32) print(arrayInt)
(7)数组的索引切片
- NumPy数组的索引选取数据子集或单位各元素的方式有很多。
- 对于高维数组,索引和切片技术能做更多的操作
- 二维数组对象[二维度下标索引值, 一维度元素下标索引值]
- 例如在一个二维数组中,各索引位置上的元素值不是标量,而是一维数组
- 二维数组的切片方式更加灵活,前者是行,后者是列,逗号隔开维度
- 三维数组切片,第一个维度选取二维数组,第二个维度选择一维数组,第三个维度选取一维数组中的元素。
# 数组的索引和切片 import numpy as np array2d = np.arange(0, 100, 1) print(array2d[0]) array2d[0] = 100 print(array2d) # 支持负索引 print(array2d[-1]) # 取出最后一个元素
# 数组切片 # 一维数组切片(start, end , step) array1d = np.array([1, 2, 3, 4, 5, 6, 7, 8]) print(array1d[3: 6: 1]) # 切片支持批量赋值 array1d[3:6] = 0 print(array1d) # 二维数组切片 array1 = np.array([[1, 2, 3], [4, 5, 6]]) array1[:, 2:] = 0 # == array1[0: 2: 1, 2: 3: 1],前面是行,后面是列,中间用逗号隔开 print(array1) array1[:, :] = 10 print(array1) # 二维数组的索引 print(array1[0][0]) print(array1[0, 0]) # 三维数组的切片 array3 = np.array([[[1, 2, 3], [4, 5, 6]], [[7, 8, 9], [10, 11, 12]]]) print(array3) # 选取第二个二维数组,所有行,第二三列 print(array3[1:, :, 1:])
2. NumPy数据预处理
(1) 布尔型索引
布尔索引的效率要比for更高,所以可以期待使用bool索引取代for循环,知道更多,在工程实践时会有更多的选择:
import numpy as np # 布尔索引 : 一种过滤机制 array = np.array([1, 2, 3, 4, 5]) boolIndex = np.array([False, True, False, True, False]) array2 = array[boolIndex] print(array2) # 等价写法 print(array[[False, True, False, True, False]]) # numpy数组的比较运算,会返回布尔数组 print(array % 2 == 0) print(array > 3) print(array[array % 2 == 0]) # 简洁好用
# 布尔索引的运算 & | result = ((array % 2 == 0) & (array > 3)) print(result) print(array[result]) # 选取符合条件的数据项
人工智能核心是算法,是数据处理,所以Python语言的NumPy库可以高效地处理数据,所以成为人工智能研究的必备工具。(2)花式索引
import numpy as np # 花式索引, 应用场景很少 array = np.array([1, 2, 3, 4, 5]) print(array[[1, 3]]) # 用另外一个数组作为一个数组的索引 array2d = np.array([[1, 2, 3], [4, 5, 6]]) # 第一列组成一个数值索引(0,1),另一列(1,2)组成另一个数值索引 print(array2d[[0, 1], [1, 2]])
(3) 数组转置和轴对换
- 转置是重塑的一种特殊形式,它返回的是源数据的视图,不会进行任何复制操作。
- 所谓转置最简单的理解为一种行列(轴)转换操作(轴是三维数组中的纬度值)。
- 数组不仅有transpose方法,还有一个特殊的T属性。
- NumPy提供了transpose()函数完成数组转置,在高纬度数组中称为轴对称。
- 但是我们经常会使用transpose()函数对高维数组进行自定义转置操作
import numpy as np # 数组的轴和轴转换 axis array2d = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) print(array2d) print(array2d.T) print(array2d.sum(axis=1)) # 0是行方向,1是列方向 # 三维数组的transpose array3d = np.array([[[1, 2, 4], [4, 5, 6]], [[6, 7, 8], [10, 11, 12]]]) # transpose print(array3d.transpose(2, 1, 0)) # 轴发生改变 print(array3d.T) # array3d[0][0][2] = 4 第一个二维数组里的第一行第三列 # 转换之后,array3d[2][0][0] = 4, 轴改变使下标改变、值不变
print(array3d.transpose(0, 2, 1))
(0, 2, 1)实际上是二维数组本身的顺序不做改变,而调换二维数组内部的行列轴,所以呈现出来的效果如上。3. NumPy的文件存储技术
- NumPy提供了多种文件操作函数方便我们存取数组内容。文件存取的格式分为两类:二进制和文本。而二进制格式的文件又分为NumPy专用格式化二进制类型和无格式类型。
- 使用数组的方法函数tofile可以方便地将数组中的数据以二进制的格式写进文件。tofile输出的数据没有格式,因此用numpy.fromfile读回来时,需要自己格式化数据。
import numpy as np array2d = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) array2d.tofile('a.bin') # 注意读取时有类型的要求,读取文件的dtype必须与原本的模型相符合 array2d2 = np.fromfile('a.bin', dtype=np.int32) print(array2d2) # npy文件读写,二进制文件 np.save('a.npy', array2d) array2d3 = np.load('a.npy') print(array2d3)
![在这里插入图片描述](https://img-blog.csdnimg.cn/66e8455e2f4a400dbc8f47c71f35f133.png#pic_center
如果你想将多个数组保存到一个文件中的话,可以使用numpy.savez函数,savez函数的第一个参数是文件名,其后的参数都是需要保存的数组,也可以使用关键字参数为数组起一个名字,非关键字参数传递的数组会自动起名为arr_0,arr_1,…。savez函数输出的是一个压缩文件(扩展名为npz),其中每个文件都是一个save函数保存的npy文件,文件名对应于数组名。load函数自动识别npz文件,并且返回一个类似于字典的对象,可以通过数组名作为关键字获取数组的内容。# 保存多个数组到同一个文件,还可以进行还原 array1d = np.array([1, 2, 3, 4, 5]) array3d = np.array([[1, 2, 3, 4, 5]]) np.savez('a.npz', array2d, array1d, W3=array3d) arrs = np.load('a.npz') print(arrs['arr_0']) print(arrs['arr_1']) print(arrs['W3'])
- csv本质是文本文件,python关于csv文件格式的复写,实际上是将数组存放/读取文本文件。
# 将数组存放为文本文件,csv本质是文本文件 np.savetxt('a.txt', array2d) # 需要注明存储类型,分隔符, 换行符 np.savetxt('a.csv', array2d, fmt='%d', delimiter=',', newline='\n') arrays = np.loadtxt('a.csv', delimiter=',', dtype=np.int32) print(arrays)
4. 广播机制
# 广播机制 print("按行广播") # 一个一行多列的一维数组可以与array2d广播 print(array2d + array1d) print(array2d - array1d) print(array2d * array1d) print(array2d / array1d) print(array2d ** array1d) # 按列广播,需要使用多行一列的数据列 print("按列广播") array1d = np.array([[1], [2]]) print(array2d + array1d)
5. 通用函数
(1)一元函数
- 有一些(add和maximum)接受两个数组,因此也叫做二元(binary)ufunc,并返回一个结果数组。
import numpy as np # 自然数e = 2.718 print(np.e) # 机器学习、深度学习 自然数e 1/(1 + ^(-x))激活函数 print(np.e**2) result = np.exp(2) # e^x print(result) array1 = np.array([1, 2, 3]) array2 = np.array([4, 5, 6]) result = np.sum(array1) print(result) result = np.mean(array1) print(result) print(np.exp(array1))
- python中还有一种modf()方法,可以将浮点数组的整数部分和小数部分分开。
# 生成一个浮点数组 array = np.random.uniform(-5.0, 5.0, size=(4, 5)) print(array) r1, r2 = np.modf(array) print(r1) print(r2)
- 对数函数
# 对数函数,Numy的log函数函数默认是以e为底 r = np.log(np.e) # 信息论、信息熵、交叉熵基础 print(r)
- 还有其他的ufunc函数
- abs, fabs:计算整数、浮点数或复数的绝对值,对于非复数值,可以使用更快的fabs。
- sqrt,计算各元素的平方和。
- log, log10, log2, log1p:分别为自然对数,底数为10的log,底数为2的log和log(1+x)。
- sign:计算个元素的正负号,正数为1,复数为-1,零为0。
- ceil:计算各元素的ceiling值,即大于等于该值的最小整数。
- floor:计算各元素的floor值,即小于等于该值的最大整数。
- rint:将各元素值四舍五入到最接近的整数,保留dtype类型。
- isnan:返回一个表示哪些值是NAN的布尔型数组
- isfinite, isinf:分别返回一个表示“哪些元素是有穷的”或“哪些元素是无穷的”布尔值型数组。
(2)二元函数
# 二元函数 r = np.add(array1, array2) print(r) r1 = np.subtract(array1, array2) print(r1) r2 = np.power(10.0, 10) print(r2)
6. 用数组处理数据
- NumPy数组使我们可以将多种数据处理任务表述为简洁的数组表达式,否则还需要编写循环。
- 用数组代替循环的做法,通常被称为“矢量化”。
- 一般来说,矢量化数组运算要比等价的纯Python方式快上1~2个级别,甚至更多,尤其是各种数值计算。这也是矢量化计算的强大之处。
- np.meshgrid函数接受两个一维数组,并产生两个二维矩阵(对应于两个数组中所有的(x,y)对)
# meshgrid函数 pointX = np.array([1, 2, 3]) pointY = np.array([2, 4, 6]) vx, vy = np.meshgrid(pointX, pointY) print(vx) print(vy)
- np.where的用法
# 使用where简化代码 result = np.where(array >= 90, '优秀', '一般') print(result) # np.where的嵌套 result = np.where(array>= 90, '优秀', np.where(array>= 80, '良好', '一般')) print(result)
- zip
# for循环可以使用zip多个集合进行同时遍历 array = np.array([1, 2, 3, 4, 5]) list1 = [1, 2, 3, 4, 6, 7] t1 = (11, 2, 3, 4, 5, 6.6, 7) # zip会选择最短的进行遍历,避免越界 for x, y, z in zip(array, list1, t1): print(x, y, z) pass
7.数学和统计方法介绍
- 可以通过数组上的一组数学函数对整个数组或某个轴向的数据进行统计计算。sum,mean以及标准差std等聚合计算(aggregation, 通常叫做约简(reduction))即可当做数组的实例方法调用,也可以当做顶级NumPy函数使用。
import numpy as np # 常见的数学统计函数 array = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) # 归一化处理,用(偏差-均值)/标准差 r1 = array.mean(axis=0) # 0代表着列方向 print(r1) r2 = array - r1 print(r2) r3 = r2/array.std(axis=0) print(r3) # 等价写法 r3 = (array-array.mean(axis=0))/array.std(axis=0) print(r3)
- argmax和argmin,求一个数组中最大值和最小值的索引
# argmax 和 argmin array = np.array([-1, 1, -10, 11, 13, 20, -6]) print(np.argmax(array)) print((np.argmin(array)))
- 用于布尔型数组的方法
# 布尔数组求和 boolArray = np.array([True, False, False, True]) r = np.sum(boolArray) print(r) # 统计布尔数组非零值 r = np.count_nonzero(boolArray) print(r) # 获取非零元素的索引,这里其实使用了一个花式索引 r = np.nonzero(boolArray) print(boolArray[r])
- 一维数组可以使用array.sort()函数进行排序,但是不建议使用,后续可以使用pandas实现排序。
8. 线性代数
- 这一块内容,需要重点学习dot函数
- 首先是学习矩阵的乘法:
import numpy as np # 线性代数函数使用dot(点积和计算)矩阵 向量 (N*M M*K) array = np.array([[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]) # 2*5 5*k array2 = np.array([[1], [2], [3], [4], [5]]) # 2*5 5*1 == 2*1 print(array.dot(array2)) #矩阵相乘 print(np.dot(array, array2)) print(array @ array2)
还有一种特殊情况:# numpy比较灵活 f(A,x) = A.dot(x) # 行向量 和 列向量 x = np.array([1, 2, 3, 4, 5]) print(array.dot(x)) # 这是一种不符合矩阵运算的写法,但是依然可以得到答案
- NumPy里的线性函数
import numpy as np array = np.array([[1, 2], [3, 4]]) print(np.linalg.det(array)) # 行列式 # AX = 参数*x # 得到特征值和特征向量 v, x = np.linalg.eig(array) print(v) print(x) print(array.dot([-0.82456484, 0.56576746])) print(-0.37228132 * (np.array([-0.82456484, 0.56576746]))) # 矩阵求逆 A'A=E a1 = np.linalg.inv(array) print(a1) print(array.dot(a1)) # 由于精度问题,不能完全显示,但输出就是单位矩阵
- 随机数生成
# 随机数模块 data = np.random.randint(0, 100, size=(2,3)) print(data) dataf = np.random.uniform(-1, 1, size=(5, 5)) print(dataf)
- 随机数的“洗牌”功能
# 随机打乱顺序 arrayx = np.array([1, 2, 5, 10, 22, 11, 99, 100]) np.random.shuffle(arrayx) print(arrayx)