人工智能学习笔记

文章目录

  • 一. 机器学习概述
    • 人工智能概述
    • 人工智能、机器学习和深度学习的关系
    • 机器学习工作流程
      • 1.定义
      • 2.工作流程
      • 3.获取到的数据集介绍
      • 4.数据基本处理
      • 5.特征工程
      • 6.机器学习
      • 7.模型评估
    • 机器学习算法分类
    • 模型评估
    • Azure机器学习模型搭建实验
    • 深度学习简介
  • 二. 机器学习基础环境按照与使用
    • 安装第三方库
    • jupyter notebook使用
  • 三. Matplotlib
    • matplotlib之helloworld
      • 实现一个简单的matplotlib画图
      • 实现多个坐标系显示图像
    • 折线图(plot)与基础绘图功能
    • 常见图形绘制
  • 四. Numpy
    • 4.1 Numpy优势
      • 1.定义
      • 2.创建
      • 3.numpy的优势
      • 4.效率对比
    • 4.2 N维数组 - ndarray
    • 4.3 基本操作
      • 生成数组
      • 数组索引、切片
      • 形状修改
      • 类型修改
      • 数组去重
    • 4.4 ndarray运算
      • 聚合运算
      • 逻辑运算
      • 通用判断
      • 三元运算符
      • 统计运算
    • 4.5 矩阵
    • 4.6 数组间的运算
  • 五. Pandas
    • 5.1 Pandas介绍
      • pandas概念
      • 数据结构
      • 案例知识点
      • 注意
    • 5.2 基本数据操作
    • 5.3 dataframe运算
    • 5.4 pandas画图
    • 5.5文件读取与存储
    • 5.6高级处理 - 缺失值处理
    • 5.7高级处理 - 数据离散化
    • 5.8高级处理 - 合并
    • 5.9高级处理 - 交叉表与透视表
    • 5.10高级处理 - 分组与聚合
    • 5.11案例
  • 计算机视觉
    • 分类
    • 图像预处理
  • OPENCV
    • OPENCV简介
      • 安装OPENCV
      • opencv主要模块
    • OPENCV基本操作
      • 创建和显示窗口
      • 加载显示图片
      • 视频操作
        • 读取视频
        • 录制视频
      • 保存图片
      • 绘制几何图形
      • 鼠标控制
      • 图像操作
      • trackbar用法
      • 色彩操作
        • HSV(HSB)\HSL\YUV
        • 颜色空间的转化
      • Mat的深浅拷贝
      • 图像的分割和合并
    • 图像的算术运算和位运算
      • 图像的加减乘除运算
      • 图像的加权融合
      • 位运算
    • 图像的基本变换
      • resize用法
      • 图像的翻转
      • 图像的旋转
      • 仿射变换
        • 图像平移
        • 获取变换矩阵
        • 透视变换
    • 滤波器
      • 卷积
        • 卷积核的大小
        • 卷积案例
      • 均值滤波和方盒滤波
      • 高斯滤波
      • 中值滤波
      • 双边滤波
    • 算子
      • sobel算子
      • 沙尔 (Scharr)算子
      • 拉普拉斯算子
      • Canny边缘检测
    • 形态学
      • 图像全局二值化
      • 自适应阈值二值化
      • 腐蚀操作
      • 获取形态学卷积核
      • 膨胀操作
      • 开运算
      • 闭运算
      • 形态学梯度
      • 顶帽运算
      • 黑帽操作
    • 图形轮廓
      • 查找、绘制、计算轮廓,
      • 多边形逼近
      • 凸包
  • 人脸检测
    • 人脸检测
  • 机器学习算法
    • 分类算法 --- KNN算法
      • KNN算法步骤
      • KNN算法函数
      • 归一化处理
      • KNN算法的探讨
    • 分类算法 --- 支持向量机原理
      • 支持向量机本质
      • 支持向量机实战
        • python机器学习库SKlearn
        • 入门SKlearn
    • 分类算法 --- 决策树
      • 决策时的定义
      • 决策树的构建
      • 决策树特征选择
      • 决策树剪枝
      • 连续值与缺失值处理
      • 决策树本质
    • 回归算法 --- 相关和回归
    • 回归算法 --- 一元线性回归与最小二乘法
    • 回归算法 --- 多元线性回归与梯度下降算法
      • 梯度下降法
    • 无监督学习 --- 聚类算法
      • 聚类(clustering)的定义
      • K-Means算法
      • 层次聚类算法
      • 主成分分析
    • 人工神经网络
      • 人工神经网络(ANN)的定义
      • ANN基本原理
      • BP神经网络的基本原理
    • 深度学习
      • 深度学习本质
      • 自动编码机
      • 卷积神经网络(CNN)
      • Keras
        • DNN的keras实战
        • CNN的keras实战
      • 图像分类
        • 图像分类评价指标
        • GoogleNet的keras实现
          • 图像读取 --- 图像增强-图像生成器
  • PyTorch
    • pytorch基本数据类型

一. 机器学习概述

人工智能概述

  • 人工智能的起源
    图灵测试
    1956年,达特茅斯会议,人工智能诞生

  • 主要分支介绍
    1.计算机视觉
    eg:人脸识别
    2.自然语言处理
    语音识别
    语义识别
    3.机器人

  • 人工智能必备三要数
    数据
    算法
    计算力

  • gpu、cpu
    gpu – 计算密集型
    cpu – IO密集型

人工智能、机器学习和深度学习的关系

机器学习是人工智能的一个实现途径
深度学习是机器学习的一个方法发展而来
人工智能 > 机器学习 > 深度学习

机器学习工作流程

1.定义

数据
自动分析获得模型
预测
从数据中自动分析获得模型,并利用模型对未知数据进行预测

2.工作流程

1.获得数据
2.数据基本处理
3.特征工程
4.机器学习(模型训练)
5.模型评估

3.获取到的数据集介绍

  • 1.专有名词
    • 样本
    • 特征
    • 目标值(标签值)
    • 特征值
  • 2.数据类型构成
    类型一:特征值+目标值
    目标值分为离散还是连续
    类型二:只有特征值,没有目标值
  • 3.数据划分
    训练数据(训练集) – 构建模型
    0.7-0.8
    测试数据(测试集) – 模型评估
    0.2-0.3

4.数据基本处理

对数据进行缺失值,去除异常值等处理

5.特征工程

1.定义
把数据转化为机器更容易识别的数据
2.为什么需要特征工程
数据和特征决定了机器学习的上限,而模型和算法只是逼近这个上限
3.包含内容
特征提取
特征预处理
特征降维

6.机器学习

选择合适的算法对模型进行训练

7.模型评估

对训练好的模型进行评估

机器学习算法分类

1.监督学习 – 有特征值,有目标值
目标值连续 – 回归
目标值离散 – 分类
2.无监督学习 — 仅有特征值
聚类
关联规则
3.半监督学习
有特征值,但是一部分数据有目标值,一部分没有
4.强化学习
动态过程,上一步数据的输出是下一步数据的输入
四要素:agent,action,environment,reward

模型评估

1.分类模型评估
准确率
精确率
召回率
F1-score
AUC指标
2.回归模型评估
均方根误差 root mean squared error RMSE
相对平方误差 relative squared error RSE
平均绝对误差 mean absolute error MAE
相对绝对误差 relative absolute error RAE
决定系数 coefficient of determination
3.拟合
欠拟合
过拟合

Azure机器学习模型搭建实验

microsoft开发的,可视化的机器学习模型搭建平台。

深度学习简介

二. 机器学习基础环境按照与使用

安装第三方库

jupyter notebook使用

1.jupyter定义
开源的科学计算平台
类比ipython
可以运行代码,可以做笔记
文件按后缀.ipynb
使用:jupyter notebook
2.jupyter和pycharm对比
jupyter – 探索性数据,一边分析,一边运行
pycharm – 适合逻辑性强的操作(web)

3.jupyter两种模式
编辑模式 – 直接点击进去,可以进行编写代码,做笔记
命令模式 – 通过快捷键,操作,eg:添加一行

4.快捷键
通用:
shift + enter,执行本单元代码,并跳转到下一单元
ctrl + enter,执行本单元代码,留在本单元
命令模式:
Y,cell切换到code模式
M,cell切换到markdown模式
A,在当前cell的上面添加cell
B,在当前cell的下面添加cell
双击D,删除当前cell
编辑模式:
和常规方式一样

三. Matplotlib

官网:https://matplotlib.org/

matplotlib之helloworld

  1. 定义:
    主要用于开发2D图表(3D)
    数据分析,基于分析,进行展示
  2. 绘图流程
    创建画布
    绘制图像
    显示图像
  3. matplotlib三层结构
    容器层
    canvas
    figure
    axes
    辅助显示层
    添加x轴,y轴描述,标题
    图像层
    绘制什么图像的声明

实现一个简单的matplotlib画图

import matplotlib.pyplot as plt 
import random
# 生成数据
x = range(60)
y_bj = [random.uniform(10,15) for i in x]
y_sh = [random.uniform(15,20) for i in x]

# 1.创建画布
plt.figure(figsize=(20,8),dpi=100)
    figsize参数可以指定绘图对象的宽度和高度,单位为英寸。
    dpi参数指定绘图对象的分辨率,即每英寸多少个像素,缺省值为80。

# 2.绘制图像
plt.plot(x,y_bj,label = "beijing")
plt.plot(x,y_sh,label = "shanghai")

# 2.1添加x,y轴刻度
y_ticks = range(40)
x_ticks_labels = ["11点{}分".format(i) for i in x]  # 可能不显示中文,需要安装语言包
plt.yticks(y_ticks[::5])
plt.xticks(x[::5],x_ticks_labels[::5])
# plt.xticks(x_ticks_labels[::5]) # 第一个参数必须是数字

# 2.2添加网格
plt.grid(True,linestyle = "--",alpha=1) # linestyle:绘制网格的方式 alpha:透明度

# 2.3添加描述
plt.xlabel("time",fontsize = 20)
plt.ylabel("temperature")
plt.title("一小时温度变化图",fontsize = 10)

# 2.4 显示图例
plt.legend(loc="best") # best:显示的最好位置,0

# 3.显示图像
plt.show()

实现多个坐标系显示图像

# 生成数据
x = range(60)
y_bj = [random.uniform(10,15) for i in x]
y_sh = [random.uniform(15,20) for i in x]

# 1.创建画布
fig,axes = plt.subplots(nrows=1 ,ncols=2,figsize=(20,8),dpi=100)

# 2.绘制图像
axes[0].plot(x,y_bj,label = "beijing")
axes[1].plot(x,y_sh,label = "shanghai")

# 2.1添加x,y轴刻度
y_ticks = range(40)
x_ticks_labels = ["11点{}分".format(i) for i in x]  # 可能不显示中文,需要安装语言包

axes[0].set_xticks(x[::5])
axes[0].set_yticks(y_ticks[::5])
axes[0].set_xticklabels(x_ticks_labels[::5])
axes[1].set_xticks(x[::5])
axes[1].set_yticks(y_ticks[::5])
axes[1].set_xticklabels(x_ticks_labels[::5])

# 2.2添加网格
axes[0].grid(True,linestyle = "--",alpha=1) # linestyle:绘制网格的方式 alpha:透明度
axes[1].grid(True,linestyle = "--",alpha=1) # linestyle:绘制网格的方式 alpha:透明度

# 2.3添加描述
axes[0].set_xlabel("time",fontsize = 20)
axes[0].set_ylabel("temperature")
axes[0].set_title("beijing温度变化图",fontsize = 10)
axes[1].set_xlabel("time",fontsize = 20)
axes[1].set_ylabel("temperature")
axes[1].set_title("shanghai温度变化图",fontsize = 10)

# 2.4 显示图例
axes[0].legend(loc="best") # best:显示的最好位置,0
axes[1].legend(loc="best") # best:显示的最好位置,0

# 3.显示图像
plt.show()

折线图(plot)与基础绘图功能

1.图像保存
plot.savafig(‘path’,dpi=300)
注意:图像保存一定要做到show前面。因为show会释放figure资源
2.添加x轴,y轴刻度
plt.xticks(x,**kwargs) X:要显示的刻度值
plt.yticks(y,*kwargs) y:要显示的刻度值 Y:
注意:第一个参数必须是数字,如果不是数字,需要进行值替换。
3.添加网格
plt.grid(True,linestyle = “–”,alpha=1)
linestyle:绘制网格的方式 alpha:透明度
4.添加描述信息
plt.xlabel(“time”,fontsize = 20)
plt.ylabel(“temperature”)
plt.title(“一小时温度变化图”,fontsize = 10)
5.多次plot
直接绘制
6.显示图例
plt.legend()
注意:需要显示之前,声明plot里面的具体label值
7.多个坐标系图像显示
fig,axes = plt.subplots(nrows = 1,ncols = 2)
nrows – 几行
ncols – 几列
注意:有些方法需要添加set_

8.折线图应用场景
1.表述数据变化
2.绘制一些数学图像

常见图形绘制

  1. 折线图 – plt.plot() :变化
  2. 散点图 – plt.scatter(): 分布规律
  3. 直方图 – plt.hist(x,bins) : x代表要使用的数据,bins表示要划分区间数(分成多少组).
# 0.数据准备
x = [0,243,324,123,3124]
y = [213,321,634,23,312]
# 1.创建画布
plt.figure(figsize=(20,8),dpi=100)
# 2.绘制图像(散点图)
plt.scatter(x,y)
# 3.图像展示
plt.show()
  1. 柱状图 – plt.bar():统计,对比
# 0.数据准备
movie_name = ["weq","eq","demo"]

x = range(len(movie_name))
y = [213,312,314]
# 1.创建画布
plt.figure(figsize=(20,8),dpi=100)
# 2.绘制图像(柱状图)
plt.bar(x,y,color = ['b','r'],width=0.5)

# 2.1 x轴
plt.xticks(x,movie_name,fontsize=20)
# 2.2网格
plt.grid()
# 2.3标题
plt.title("sdad") 

# 3.图像展示
plt.show()
  1. 直方图 --plt.hist():统计、分布
  2. 饼图 – plt.pie(): 占比

四. Numpy

4.1 Numpy优势

1.定义

开源的python科学计算库,用于快速处理任意维度的数组,Numpy中,存储对象是ndarray(N维数组)。

2.创建

np.array(list/tuple)

3.numpy的优势

内存块风格 – 一体式存储
支持并行化运算 – 向量化运算
效率高于纯python代码 – 底层使用了C,内部释放了GIL。

4.效率对比

import random
import time
import numpy as np
a= []
for i in range(1000000):
    a.append(random.random())
# 通过%time魔法方法,查看当前行的代码运行一次所花费的时间
%time sum1 = sum(a)
b = np.array(a)
%time sum2 = np.sum(b)

4.2 N维数组 - ndarray

0.创建
score = np.array([[80,89,86],
[23,123,13]],dtype = np.float32)

1.ndarray的属性
属性名字 属性解释
ndarray.shape 数组维度的元组
ndarray.ndim 数组维度
ndarray.size 数组中的元素数量
ndarray.itemsize 一个数组元素的长度(字节)
ndarray.dtype 数组元素的类型

2.ndarray的形状
np.array()

3.ndarray的类型
bool
Int
float
str

注意:若不指定,整数默认int64,小数默认float64

4.3 基本操作

生成数组

  1. 生成0和1的数组
    np.ones(shape[,dtype,order])
    np.ones_like(a[,dtype,order,subok])
    np.zeros(shape[,dtype,order])
    np.zeros_like(a[,dtype,order,subok])
    e.g: zero = np.zeros([3,4])

  2. 从现用的数组中生成
    np.array – 深拷贝
    np.asarray – 浅拷贝

  3. 生成固定范围的数组(产生连续的序列)
    np.linspace(start,stop,num,endpoint)
    num:要生成的等间隔样例数量,默认为50
    endpoint:序列中是否包含stop值,默认为ture
    np.arange(start,stop,step,dtype)
    step:每隔多少生成数据
    np.logspace(start,stop,num)
    生成以10的n次幂的数据

  4. 生成随机数组
    1.生成均匀分布随机数
    np.random.uniform(low=0.0,high=1.0,size=None)
    size = 数量
    2.生成正态分布随机数
    np.random.normal(loc=0.0,scale=1.0,size=None)
    loc = 此概率分布的均值
    scale = 此概率分布的标准差
    均值 – 图形的左右位置
    方差 – 图像是痩,还是胖
    值越小,图形越瘦高,数据越集中
    值越大,图形越矮胖,数据越分散

数组索引、切片

数组名[0:2,0:3]
直接索引
二维数组:先对行进行索引,在对列进行索引。
高维数组:从宏观到微观。

形状修改

1.数组对象.reshape([5,4]) : 5行2列(先拉直,再重排)
不进行行列互换,产生新变量
reshape(-1,1):变成向量例:(16,) --> (16,1)
2.数组对象.resize([-1,2]) : 不知道几行,但是2列
不进行行列互换,对原值进行修改

3.数组对象.T
进行行列互换,产生新变量

类型修改

数组对象.astype(type)
e.g:array.astype(np.int32)
转化为byte:
arr.tostring()

数组去重

np.unique(array)

4.4 ndarray运算

聚合运算

sum(0/1) 
    0:表示按照列求和
    1:表示按照行求和

逻辑运算

大于,小于直接进行判断。
赋值:满足要求,直接进行赋值。
e.g:
    stock_c>1
    stock_c[stock>1] = 2

通用判断

np.all(condition): 所有元素都满足条件才返回True 
np.any(condition): 只要有一个元素满足条件就返回True

三元运算符

np.where(condition,first,second):
    满足要求,赋值第一个值,否则赋值第二个值
np.logical_and(cond1,cond2) : 都满足
np.logical_or(cond1,cond2): 满足一个

统计运算

Min
Max
midian -- 中位数
mean -- 均值
std --标准差
var -- 方差
argmax -- 最大值下标
argmin -- 最小值下标

4.5 矩阵

1.矩阵和向量
矩阵:理解-二维数组
向量:理解-一维数组

2.加法和标量乘法
加法:对应位置相加
乘法:标量和每个位置的元素相乘

3.矩阵向量(矩阵)乘法
[m行 , n列] * [n行 , l列] = [m行 , l列]

4.矩阵乘法性质
满足结合律,不满足交换律

5.单位矩阵
对角线为1,其他位置为0的矩阵

6.逆矩阵
矩阵a* 矩阵b = 单位矩阵
那么a和b就互为逆矩阵

7.转置(T)
行列互换

4.6 数组间的运算

1.数组和数字是直接可以进行运算
2.数组和数组:
需要满足广播机制
维度相同。
shape对应位置为1
3.矩阵乘法api
np.dot – 点乘
np.matmul --矩阵相乘
注意: 两者之间在进行矩阵相乘时候,没有区别。
但是,dot支持矩阵和数字相乘。

五. Pandas

5.1 Pandas介绍

pandas概念

开源的数据挖掘库
用于数据探索
封装了matplotlib,Numpy

import Pandas as pd

数据结构

Series 1维 带有标签的同结构类型数组。
DataFrame 2维 表格结构,带有标签,大小可变,且可以包含异构的数组。

注:一个DataFrame中可以包含若干个Series。

案例知识点

1.创建DataFrame(字典结构)
pd.DataFrame(ndarray,index,columns,…)
ndarray: np数据结构
index:行索引值
columns:列索引值

2.创建日期
pd.date_range(start=None,end=None,periods=None,freq=‘B’)
start – 开始日期
end – 结束日期
periods – 时间跨度,时间天数
freq – 统计时间方式,递进单位,默认1天,‘B’默认略过周末。

3.DataFrame介绍 – 类比二维数组
1 dataframe属性
对象.shape
对象.index
对象.columns
对象.values
对象.T
对象.head(n): 看前几行
对象.tail(n): 默认后5行
2 dataframe设置索引
修改行列索引:
必须整行或者整列去进行修改
重设索引
对象.reset_index(drop=False): drop默认为False,不删除原来的索引值。
设置新索引:
对象.set_index(keys=[],drop=True)
keys:列索引名作为索引
drop:默认为True,删除原来的索引
如果设置索引是两个的时候就是multiIndex

4.MultiIndex和panel – 类比三维数组
1 MultiIndex
对象.index
对象.index.names
2 panel – 已经弃用,了解
直接没法进行查看里面的值,需要通过索引获取

5.Series – 一维数组
1 创建
pd.Series(ndarray,list/dictionary)
通过ndarray创建
指定索引创建
通过字典创建
2 属性
对象.index
对象.values

注意

  • dataframe的不同列可以是不同的数据类型
  • 如果以series数组来创建dataframe,每个series将成为一行,而不是一列。

5.2 基本数据操作

1.索引操作
1. 直接 – 先列后行
2. 对象.loc[行,列] – 先行后列,通过行和列的索引来访问数据。":“表示连续,”[]"表示枚举。包首包尾
3. 对象.iloc[] – 先行后列,索引值的下标。包首不包尾。
4. 对象.ix[] – 先行后列,混合索引

2.赋值操作
对close列进行重新赋值
1.对象[“close”] =1
2.对象.close = 1

3.排序
1.dataframe
对象.sort_values(by,ascending=True)
单个键或者多个键进行排序,默认升序。
by – 按照什么排序
ascending – 升降序
对象.sort_index()
注意:by这个参数可以接受多个值,优先按照第一个索引排序,如果相同,按照后面的。
2.Series
对象.sort_values()
对象.sort_index()

5.3 dataframe运算

1.算术运算
对象.add(n)
直接使用方法,add,sub …
也可以用符号

2.逻辑运算
逻辑运算符号 < 、>、| 、 &
直接判断
逻辑运算函数
对象.query(“expr”)
expr:查询字符串
对象.isin([])

3.统计函数
对象.describe()
统计函数
Sum
mean

mode – 众数(出现次数最多的数)
idxmax – 最大值的索引
idxmin – 最小值的索引

4.累计统计函数
函数 作用
cumsum 计算前1/2/3/…/n个数的和
cummax 计算前1/2/3/…/n个数的最大值
cummin 计算前1/2/3/…/n个数的最小值
cumprod 计算前1/2/3/…/n个数的积

5.自定义运算
apply(func,axis=)
func – 自己定义的函数
axis 按行还是按列计算

5.4 pandas画图

对象.plot(x=None,y=None,kind=“line”)
kind –
line – 折线图
bar
barh – 条形图旋转
hist
pie
scatter
plt.show()

5.5文件读取与存储

1.csv
读取 – pd.read_csv(filepath_or_buffer,usecols=[,])
filepath_or_buffer: 文件路径
usecols – 需要读取的列名
存储 – 对象.to_csv(path_or_buf=None,conlumns,mode=‘w’,index = True)
mode:"w"重写,"a"追加
conlumns – 保存哪列
index : 是否保存索引

2.hdf
读取 – pd.read_hdf()
写入 – 对象.to_hdf()
注意:保存文件是xxx.h5

3.json
读取 – pd.read_json(path_or_buf=None,orient=None,typ=‘frame’,line=False)
orient – 按照什么方式进行读取或者写入(‘split’,‘records’,‘index’,‘columns’,‘values’)
lines – 是否按照行读取和写入
typ – 指定转换成的对象类型series或dataframe
写入 – 对象.to_json(path_or_buf=None,orient=None,line=False)
orient – 按照什么方式进行读取或者写入(‘split’,‘records’,‘index’,‘columns’,‘values’)
lines – 是否按照行写入

4.推荐使用hdf
压缩方式,读取效率快。
压缩后,节省空间。
支持跨平台。

5.6高级处理 - 缺失值处理

判断数据是否为NaN:
np.any(pd.isnull(movie)) # 里面如果有一个缺失值,就返回True
np.all(pd.notnull(movie)) # 里面如果有一个缺失值,就返回False
处理方式:
存在缺失值,并且是np.nan:
1.删除存在缺失值的:data = movie.dropna(axis=“rows”)
注:不会修改原数据,需要接受返回值
2.替换缺失值,fillna(value=“”,inplace=True)
value:替换成的值
inplace:True:会修改原数据,False:不替换修改原数据,生成新的对象
不是缺失值nan,有默认标记的
对象.replace(to_replace=,value=)
to_replace – 替换前的值
value – 替换后的值(np.NaN)

5.7高级处理 - 数据离散化

1.什么是数据离散化
把一些数据分到某个区间,最后用不同的符号或者数字表达式
2.数据离散化api
pd.qcut() – 把数据大致分为数量相等的几类
pd.cur() – 指定分组间隔
数量统计:
对象.value_counts()
3.one-hot编码
就是把数据转换为0,1统计类型
别名:哑变量,热独编码
api:
pd.get_dummies()

5.8高级处理 - 合并

pd.concat()
axis=
pd.merge()
left – 左表
right – 右表
on – 指定键
how – 按照什么方式进行拼接

5.9高级处理 - 交叉表与透视表

1.什么交叉表,透视表
就是探索两列数据之间的占比关系
2.交叉表:pd.crosstab()
返回具体数量的统计
3.透视表:对象.pivot_table([],index=[])
返回占比情况

5.10高级处理 - 分组与聚合

对象.groupby(key,as_index)
key – 按照什么去分组
as_index – 是否发生结构变化
注意:如果抛开聚合,去说分组,没有意义。

5.11案例

计算机视觉

现在说的机器视觉(machine vision)一般指计算机视觉(computer vision),简单来说就是研究如何使机器看懂东西,就是指使用摄影机和电脑代替人眼对目标进行是被、跟踪和测量等机器视觉,并进一步做图形处理,使电脑处理成为更适合人眼观察或传送给仪器检测的图像。

  • 物体识别
  • 识别图像中的文字(OCR)
  • 图像拼接,修复,背景替换

分类

计算机视觉:
语义感知:
分类 Classification(物体、属性、场景等)
检测 Detection(物体、行人、人脸等)
识别 Recognition(物体、人)
分割 Segmentation
检索 Retrieval
语言 Language
几何属性:
3D建模
双目视觉
增强现实

图像预处理

图像处理:
空间域处理:
点运算 (HE、CLAHE)
形态学运算(膨胀、腐蚀)
临域运算(卷积、金字塔)
频率域处理:
傅里叶变换
小波变换

OPENCV

OPENCV简介

opencv是一个的跨平台库,可以运行在 Linux、Windows 和 Mac OS 操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时也提供了python接口,实现了图像处理和计算机视觉方面的很多通用算法。

  • 应用场景
    OpenCV 可以应用但不仅限于以下场景:二维和三维特征提取、街景图像拼接、人脸识别系统、手势识别、人机交互、动作识别、物体识别、自动检查和监视、分割与识别、医学图像分析、运动跟踪、增强现实、视频/图像搜索与检索、机器人与无人驾驶汽车导航与控制、驾驶员疲劳驾驶检测等。

Gray Bradsky于1999年开发,2000年发布
c++、python、java、js
跨平台

安装OPENCV

pip install opencv-python
pip install opencv-contrib-python 

opencv主要模块

模块 介绍
core 核心模块,是定义基本数据结构的模块,也包括库中所有其他模块使用的基本函数
imgproc 图像处理模块,包括图像滤波、几何图像变换、颜色空间变换和直方图
imgcodecs 图像文件读写
highgui 高级GUI,提供UI功能的接口,可以执行以下操作:创建和操作可以显示的窗口、将滑动条添加到窗口、键盘命令和处理鼠标事件等
videoio 视频I/O,视频捕获和视频编解码器的接口
video 视频分析模块,包括背景减法、运动估计和目标跟踪算法
calib3d 摄像机标定和三维重建,包括基本的多视点几何算法、立体匹配算法、目标姿态估计、单摄像机和立体摄像机标定以及三维重建
features2d 二维特征框架,该模块包括特征检测器、描述符和描述符匹配器
objdetect 目标检测,检测预定义类的对象和实例(例如,人脸、眼睛、人和汽车)
dnn 深度神经网络(Deep neural network, DNN)模块,本模块包含以下内容:用于创建新层的API、一组预定义的常用层、从层构造和修改神经网络的API、从不同深度学习框架加载序列化网络模型的功能等
ml 机器学习库(Machine Learning Library, MLL)是一组可用于分类、回归和聚类目的的类和方法
flann 快速近似近邻库(Fast Library for Approximate Nearest Neighbors, FLANN)是一组非常适合快速近邻搜索的算法,用于多维空间中的聚类和搜索
photo 计算摄影,提供一些计算摄影的函数
stitching 图像拼接,实现了一个自动拼接全景图像的拼接流水线
shape 形状距离和匹配模块,可用于形状匹配、检索或比较
superres 超分辨率,包含一组可用于提高分辨率的类和方法
videostab 视频稳定,包含一组用于视频稳定的类和方法
viz 三维可视化工具,用于显示与场景交互的小部件

OPENCV基本操作

创建和显示窗口

import cv2

# 创建窗口
# cv2.namedWindow('window', cv2.WINDOW_AUTOSIZE)
cv2.namedWindow('window', cv2.WINDOW_NORMAL)

# 更改窗口的大小
cv2.resizeWindow("window", 800, 600)

# 展示名字为window的窗口
cv2.imshow('window', 0)

# 等待按键
# 0表示接收任意按键,如果给其他的整数,表示等待按键的时间,单位是毫秒
key = cv2.waitKey(0)

# key是int 型,最少都是16位,但是ascii码是8位
# ord()是python中计算ascii的值的函数q
if key & 0xFF == ord("q"):
    print("准备销毁窗口")
    cv2.destroyAllWindows()

加载显示图片

import cv2
import matplotlib.pyplot as plt

# 默认是按照彩色图片来读取的(0是灰度)
# pic 的数据格式是numpy的ndarray
pic = cv2.imread('./1.jpg')

# 发现matplotlib显示的图片和真实的图片颜色不一样,因为opencv读进来的图片数据的通道不是默认的(RGB),
# 而是BGR,所以一般opencv读进来的图片不要用别的方式去展示,比如matplotlib
# 用opencv自己的方式去展示
# plt.imshow(pic)
#   plt.imshow(pic[:, :, ::-1])
# plt.show()
def cv_show(name, img):
    cv2.imshow(name, img)
    key = cv2.waitKey(0)
    if key & 0xFF == ord('q'):
        print("销毁窗口")
        cv2.destroyAllWindows()

视频操作

读取视频
import cv2
# VideoCapture可以捕获摄像头,用数字来表示不同的设备,比如0,1(打开失败不会报错);如果是文件直接指定路径。
video = cv2.VideoCapture("../1.mp4")
# 检查是否打开正确
if video.isOpened():
    # 读一帧数据,返回标记和这一帧数据,True表示读到了数据,False表示没读到数据。
    op, frame = video.read()
else:
    op = False
while op:
    op, frame = video.read()
    if frame is None:
        break
    if op:
        gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
        cv2.imshow('ret', gray)
        # 假如一个视频是30帧,那么每张图片间隔1000//30毫秒(只能是整数)
        if cv2.waitKey(10) & 0xFF == 27:
            break
video.release()
cv2.destroyAllWindows()
录制视频
cap = cv2.VideoCapture(0)
# fource = cv2.VideoWriter_fourcc(*'mp4v')
fource = cv2.VideoWriter_fourcc(*'XVID')
# 创建videowriter
# vw = cv2.VideoWriter('output.mp4',fource,30,(640,480))
vw = cv2.VideoWriter('output.avi', fource, 30, (640, 480))
while cap.isOpened():
    ret,frame = cap.read()
    if not ret:
        break
    # 写入每一帧图片
    vw.write(frame)
    cv2.imshow('frame',frame)
    if cv2.waitKey(1) == ord('q'):
        break
cap.release()
vw.release()
cv2.destroyAllWindows()

保存图片

import cv2
cv2.namedWindow('img', cv2.WINDOW_NORMAL)
cv2.resizeWindow('img', 300, 200)
img = cv2.imread("./1.jpg")
while True:
    cv2.imshow('img', img)
    key = cv2.waitKey(0)
    if key & 0xFF == ord('q'):
        break
    elif key & 0xFF == ord("s"):
        cv2.imwrite("./2.png", img)
    else:
        print(key)
cv2.destroyAllWindows()

绘制几何图形

  • .cv.line(img,start,end,color,thickness,linetype,shift) # 绘制直线
    thickness:线条宽度
    linetype: 线型-1,4,5,16 默认是8
    shift:坐标缩放比例,可不写

  • .cv.circle(img,centerpoint,r,color,thickness) # 绘制圆形

  • .cv.rectangle(img,leftupper,rightdown,color,thickness) # 绘制矩形

  • .cv.putText(img,text,station,font,fontsize,color,thickness,cv.LINE_AA) # 向图像中添加文字

# opencv是没有办法直接绘制中文的。需要用到第三方库:pip install pillow 
#创建一张全白的图片用来绘制中文
img = np.full((200,200,3),fill_value=255,dtype=np.uint8)
from PIL import ImageFont,ImageDraw,Image
fontpath = "C:\Windows\Fonts\....."
#设置字体的颜色
b,g,r,a = 0,255,0,0
#设置字体大小
font = ImageFont.truetype(fontpath,15)
#将numpy array的图片格式转为PIL的图片格式
img_pil = Image.fromarray(img)
#创建画板
draw = ImageDraw.Draw(img_pil)
#在图片上绘制中文
draw.text((10,150),"绘制中文",font=font,fill=(b,g,r,a))
#将图片转为numpy array的数据格式
img = np.array(img_pil)
cv2.imshow("img",img)
  • .cv2.ellipse(img,中心点,长宽的一半,角度,从哪个角度开始,从哪个角度结束,颜色…) # 画椭圆

  • .cv2.polylines(img,[pts],boolean_isclosed,color,thickness) # 画多边形(pts多边形的点集ndarray,必须是int32,且pts是3维的例:np.array([(…,…),(.,.)],np.int32)

  • .cv2.fillPoly(img,[pts],color) # 填充多边形,一定是闭合的。

注意
1.左上角是原点
2.y轴向下,x轴向右
3.单位:像素点

鼠标控制

def mouse_callback(event, x, y, flags, userdata):
    """
    对窗口上的鼠标动作做出响应,函数名可以随便取,但是参数必须时5个。
    :param event:鼠标事件
    :param x:鼠标的x坐标
    :param y:鼠标的y坐标
    :param flags:鼠标的组合案件
    :param userdata:用户数据
    :return:
    """
    print(event, x, y, flags, userdata)
    
# 调用鼠标的回调函数
cv2.setMouseCallback('mouse', mouse_callback, 'userdata')

图像操作

  • 获取并修改图像中的像素点
    img是ndarray,通过行列坐标来获取相应的值并修改。
    其中行对应y轴,列对应x轴。

  • 图像属性
    shape,size,dtype

trackbar用法

import cv2
import numpy as np

# 创建窗口
cv2.namedWindow('trackbar', cv2.WINDOW_NORMAL)
cv2.resizeWindow('trackbar', 640, 480)
# 定回调函数
def callback(value):
    pass
# 创建trackbar
cv2.createTrackbar('R', 'trackbar', 0, 255, callback)
cv2.createTrackbar('G', 'trackbar', 0, 255, callback)
cv2.createTrackbar('B', 'trackbar', 0, 255, callback)
# 创建一个背景图片
img = np.zeros((480, 640, 3), np.uint8)
while True:
    # 获取当前tracker的值
    r = cv2.getTrackbarPos('R', 'trackbar')
    g = cv2.getTrackbarPos('G', 'trackbar')
    b = cv2.getTrackbarPos('B', 'trackbar')
    # 改变背景图颜色
    img[:] = [b, g, r]
    cv2.imshow('trackbar', img)
    if cv2.waitKey(1) & 0xFF == ord('q'):
        break
cv2.destroyAllWindows()

色彩操作

HSV(HSB)\HSL\YUV
  • HSV
    hue:色相,即色彩。
    saturation:饱和度,颜色接近光谱色的程度。(混合)
    value(Brightness):明度,颜色明亮的程度。(黑色控制)

  • HSL
    hue:色相,即色彩。
    saturation:饱和度,颜色纯度。(稀释)
    Lightness(Brightness):明度。(黑白控制)

  • YUV
    考虑到人类的感知能力,减低色度的带宽。
    最大的优点就是占用极少的带宽。

颜色空间的转化
index = cv2.getTrackbarPos('curcolor','color',0,2,callback)
colorspaces=[cv2.COLOR_BGR2GRAY,cv2.COLOR_BGR2BGRA,cv2.COLOR_BGR2HSV]
cvt_img = cv2.cvtColor(img,colorspaces[index])

Mat的深浅拷贝

mat是opencv在c++语言中用来表示图像数据的一种数据结构,在python中转化为numpy的ndarray。

img2 = img.view() # 浅拷贝
img3 = img.copy() # 深拷贝
cv2.imshow('img',np.hstack((img2,img3))) # 水平堆叠显示
cv2.imshow('img',np.vstack((img2,img3))) # 垂直堆叠显示

图像的分割和合并

b,g,r = cv2.split(img) # 分割通道
b[10:100,10:100] =255 # 修改一些颜色
img2 = cv2.merge((b,g,r)) # 合并通道

图像的算术运算和位运算

图像的加减乘除运算

import cv2

img1 = cv2.imread("../1.jpg")
img2 = cv2.imread("../img.png")
print(img1.shape)
print(img2.shape)
# 在加法之前需要把图片的形状变得完全一致才行。长宽相同,通道数一样
new_img1 = img1[:483, :500]
new_img2 = img2[:483, :500]
# add的规则就是两个图对应位置的元素相加,如果超过255,全部变成255
# 图片和单个数字运算,每个数都会和100进行加法运算,相当于%256 # img1 +=100
new_img = cv2.add(new_img1, new_img2)
# 减 subtract 相应位置元素相减,减完小于0,统一变成0
new_img2 = cv2.subtract(new_img1, new_img2)
# 乘 multiply
new_img3 = cv2.multiply(new_img1, new_img2)
# 除 divide
new_img4 = cv2.divide(new_img1, new_img2)
cv2.imshow("img", new_img)
if cv2.waitKey(1) & 0xFF == ord('q'):
    cv2.destroyAllWindows()

图像的加权融合

# 图像的融合
# 不是简单的加法了,相当于拿图片做了线性运算,new_img = img1*w1 + img2*w2 + bias
import cv2

img1 = cv2.imread("../1.jpg")
img2 = cv2.imread("../img.png")
new_img1 = img1[:483, :500]
new_img2 = img2[:483, :500]
new_img = cv2.addWeighted(new_img1, 0.3, new_img2, 0.7, 0)

位运算

opencv中的逻辑运算就是对应位置元素进行与或非,异或。
opencv中的非,0反过来是255。

import cv2
import numpy as np

img1 = cv2.imread("../1.jpg")
img2 = cv2.imread("../img.png")
# 变成相同形状的图片
img1 = img1[:483, :500]
img2 = img2[:483, :500]
# 非操作。相当于(255-img1)
img1_not = cv2.bitwise_not(img1)
# 与操作,按位与
img_and = cv2.bitwise_and(img1,img2)
# 或操作,按位或
img_or= cv2.bitwise_or(img1,img2)
# 异或,按位异或
img_xor= cv2.bitwise_xor(img1,img2)
cv2.imshow('not', np.hstack((img2,img1, img_xor)))

图像的基本变换

resize用法

resize(src,src, dsize, dst=None, fx=None, fy=None, interpolation=None)
src: 要缩放的图片
dsize: 缩放之后的图片大小,元组和列表示均可
dst: 可选参数,缩放之后的输出图片
fx,fy: 可选参数,x轴和y轴的缩放比,及宽度和高度的缩放比
interpolation:插值算法
INTER_NEAREST:邻近插值,速度快,效果差。
INTER_LINEAR:双线性插值,使用原图中的4个点进行插值,默认。
INTER_CUBIC:三次插值,原图中的16个点。
INTER_AREA:区域插值,效果最好,计算时间最长。

import cv2
import numpy as np

img1 = cv2.imread("../1.jpg")
img2 = cv2.imread("../img.png")
# 把图片变成一样尺寸并展示,不用切片
new_img1 = cv2.resize(img1, (500, 483))
new_img2 = cv2.resize(img2, (500, 483))
print(img1.__sizeof__())  # 查看字节
# 按照x,y轴的比例进行缩放
new_img3 = cv2.resize(img1,dsize=None,fx=0.5,fy=0.5,interpolation=cv2.INTER_AREA)
cv2.imshow("img", np.hstack((new_img1, img2)))
cv2.waitKey(0)
cv2.destroyAllWindows()

图像的翻转

flip(src,flipCode)
flipcode = 0 上下翻转
flipcode > 0 左右翻转
flipcode < 0 上下+左右翻转

import cv2
import numpy as np
img1 = cv2.imread("../1.jpg")
new_img1 = cv2.flip(img1, flipCode=-1)
cv2.imshow("img", np.hstack((img1, new_img1)))
cv2.waitKey(0)
cv2.destroyAllWindows()

图像的旋转

rotate(img,rotatecode)
cv2.rotate_90_clockwise 90度顺时针
cv2.rotate_180 180度
cv2.rotate_90_counterclockwise 90度逆时针

仿射变换

图像平移
  • 仿射变换是图像旋转,缩放,平移的总称,具体的做法是通过一个矩阵和原图片坐标进行计算,得到新的坐标,完成变换,所以关键就是这个矩阵。
  • warpAffine(src,M,dsize,flags,mode,value)
    M:变换矩阵
    dsize:输出图片大小
    flag:与resize中的插值算法一致
    mode:边界外推法标志
    value:填充边界值
  • 平移矩阵:矩阵中的每个像素由(X,Y)组成(x,y)表示这个像素的坐标,假设沿x轴平移tx,沿y轴平移ty,那么用M变换矩阵就是
    [[1,0,tx],[0,1,ty]]
import numpy as np
import cv2

img1 = cv2.imread("../1.jpg")
h, w, ch = img1.shape
# 变换矩阵,最少是float32位
M = np.float32([[1, 0, 200], [0, 1, 0]])  # 左移200px
# 平移,注意opencv中是先宽度,后高度
new_img2 = cv2.warpAffine(img1, M, dsize=(w, h))
cv2.imshow('img', np.hstack((img1, new_img2)))
cv2.waitKey(0)
cv2.destroyAllWindows()
获取变换矩阵
  • 在进行旋转操作的时候,不方便手动计算变换矩阵。opencv提供了获取变换矩阵的api。
  • getrotationmatrix2D(center,angle,scale)
    center: 中心点,以图片的哪个点作为旋转时的中心点
    angle: 角度,旋转中的角度,按照逆时针旋转。
    scale: 缩放比例,想把图片进行什么样的缩放。
img1 = cv2.imread("../1.jpg")
h, w, ch = img1.shape
# 获取变换矩阵
# 规定时逆时针旋转
M = cv2.getRotationMatrix2D((w/2,h/2),45,1)
new_img1 = cv2.warpAffine(img1,M,(w,h))
cv2.imshow('img', np.hstack((img1, new_img1)))
cv2.waitKey(0)
cv2.destroyAllWindows()
  • getAffineTransform(src[],dst[])
    通过三点可以确定变换后的位置,相当于解方程,3个点对应三个方程,能解出偏移的参数和旋转的角度。
    src:原目标的三个点
    dst: 对应变换后的三个点
透视变换

透视变换就是将一种坐标系变换成另一种坐标系,简单来说可以把一张“斜”的图变“正”。

  • warpPerspective(img,M,dsize)
    对于透视变换来说,M是一个3*3的矩阵
  • getPerspectiveTransform(src,dst)获取透视变换的变换矩阵,需要4个点,即图片的4个角。

滤波器

降噪

卷积

图像卷积就是卷积核在图像上按行滑动像素时不断的相乘求和的过程。

  • padding
    卷积之后图片的长宽会变小,如果要保持图片大小不变,我们需要在图片周围填充0,padding指的就是填充的0的圈数。

  • 计算padding的圈数
    输入体积大小 H1W1D1
    四个超参数:
    filter数量k
    filter大小f
    步长s
    零填充大小p
    输出体积大小h2w2d2
    h2 = (h1-f+2p)/s +1
    w2 = (w1-f+2p)/s +1
    d2 = k

卷积核的大小

为什么都是奇数?
1.根据上面padding的计算公式,如果要保持图片大小不变,采用偶数卷积核的话,将会出现补零为小数的情况
2.奇数维度的过滤器有中心,便于指出过滤器的位置,即opencv卷积中的锚点。

卷积案例
  • filter2D(src, ddepth, kernel, dst=None, anchor=None, delta=None, borderType=None)
    ddepth: 卷积之后图片的位深,即卷积之后图片的数据类型,一般设为-1,表示与原图类型一致。
    kernel: 卷积核的大小。用元组或者ndarray表示,要求数据类型必须时float
    anchor:锚点,即卷积核的中心点,可选参数,默认(-1,-1)。
    delta: 可选参数,表示卷积之后额外加的一个值,相当于线性方程中的偏差,默认是0。
    bordertype: 边界类型,一般不设。
img1 = cv2.imread("../1.jpg")
# kernel = np.ones((5, 5), np.float32)/25
# 尝试其他的卷积核,突出轮廓
# kernel = np.array([[-1, -1, -1], [-1, 8, -1], [-1, -1, -1]])
# kernel = np.array([[-2, 1, 0], [-1, 1, 1], [0, 1, 2]]) # 浮雕效果
kernel = np.array([[0, -1, 0], [-1, 5, -1], [0, -1, 0]]) # 锐化

new_img1 = cv2.filter2D(img1, -1, kernel)
cv2.imshow("img", np.hstack((img1, new_img1)))

均值滤波和方盒滤波

  • 方盒滤波
    boxfilter(src, ddepth, ksize, dst=None, anchor=None, normalize=None, borderType=None)
    ksize:卷积核大小,例如(5,5)
    normalize = True时,a=1/(w*h)滤波器的宽高。
    normalize = false时,a=1。
    一般情况都是用normalize = true,这时方盒滤波等价于均值滤波。

  • 均值滤波
    blur(src, ksize, dst=None, anchor=None, borderType=None)

高斯滤波

符合高斯分布(也叫正态分布)的数据的概率密度函数。

  • GaussianBlur(src, ksize, sigmaX, dst=None, sigmaY=None, borderType=None)
    ksize: 高斯核的大小
    sigmaX: x轴的标准差
    sigmaY: y轴的标准差,默认为0,这时sigmaY = sigmaX
    如果没有指定sigma值,会分别从ksize的宽度和高度中计算sigma。
    旋转不同的sigma值会得到不同的平滑效果,sigma越大,平滑效果越明显。

中值滤波

假设有一个数组[1556789],取其中的中间值(即中位数)作为卷积后的结果值即可,中值滤波对胡椒噪音(椒盐噪音)效果明显。

  • medianBlur(src,ksize)
    注意这里的ksize就是一个数字,不是元组。

双边滤波

双边滤波对于图像的边缘信息能有更好的保存。其原理是一个与空间距离相关的高斯函数与一个灰度距离相关的高斯函数相乘。

  • bilateralFilter(src, d, sigmaColor, sigmaSpace, dst=None, borderType=None)
    d: 卷积核大小(一个数字)
    sigmaColor: 是计算像素信息使用的sigma
    sigmaSpace: 是计算空间信息使用的sigma

算子

边缘检测

sobel算子

边缘时像素值发生跃迁的位置,是图像的显著特征之一,再图像特征提取,对象检测,模式识别等方面都有重要的作用。

  • sobel算子对图像求一阶导数,一阶导数越大,说明像素在该方向的变化越大,边缘信号越强。
  • 图像的灰度值都是离散的数字,sobel算子采用离散差分算子计算图像像素点亮度值的近似梯度。
  • 图像是二维的,即沿着宽度/高度两个方向,使用卷积核对原图进行处理:
    • 水平方向
      Gx = [[-1,0,+1],[-2,0,+2],[-1,0,+1]] * I
    • 垂直方向
      Gy = [[-1,-2,-1],[0,0,0],[+1,+2,+1]] * I
# x轴方向梯度,获取的是垂直边缘
dx = cv2.Sobel(img, cv2.CV_64F, dx=1, dy=0, ksize=5)
dy = cv2.Sobel(img, cv2.CV_64F, dx=0, dy=1, ksize=5)

# 可利用nump的加法,直接整合两张图
# dst = dx + dy
# 也可以利用opencv的加法
dst = cv2.add(dx, dy)
cv2.imshow("img", np.hstack((dx, dy, dst)))

沙尔 (Scharr)算子

  • 当内核大小为3时,以上sobel内核可能产生比较明显的误差(毕竟,sobel算子只是求取了导数的近似值)。为解决这一问题,opencv提供了schaar函数,但该函数仅作用于大小为3的内核。该函数的运算与sobel函数一样快,但结果却更加准确。
  • scharr算子和sober类似,只不过使用不同的kernel值,放大了像素变换的情况。
    • 水平方向
      Gx = [[-3,0,+3],[-10,0,+10],[-3,0,+3]] * I
    • 垂直方向
      Gy = [[-3,-10,-3],[0,0,0],[+3,+10,+3]] * I
  • scharr算子只支持3*3的kernel所以没有kernel参数了
  • scharr算子只能求x方向和y方向的边缘
  • sobel算子的ksize设为-1就是scharr算子
  • schaar擅长寻找细小的边缘,一般用的少
# x轴方向梯度,获取的是垂直边缘
dx = cv2.Scharr(img, cv2.CV_64F, dx=1, dy=0)
dy = cv2.Scharr(img, cv2.CV_64F, dx=0, dy=1)

# 可利用nump的加法,直接整合两张图
# dst = dx + dy
# 也可以利用opencv的加法
dst = cv2.add(dx, dy)
cv2.imshow("img", np.hstack((dx, dy, dst)))

拉普拉斯算子

  • 卷积核
    [[0,1,0],[1,-4,1],[0,1,0]]
  • 卷积模板
    [[f(x-1,y-1),f(x,y-1),f(x+1,y-1)],[f(x-1,y),f(x,y,f(x+1,y)],[f(x-1,y+1),f(x,y+1),f(x+1,y+1)]]
  • Laplacian(src, ddepth, dst=None, ksize=None, scale=None, delta=None, borderType=None)
  • 可以同时求两个方向的边缘
  • 对噪音敏感,一般需要先进行去噪再调用拉普达斯
img = cv2.imread("../1.jpg")
dst = cv2.Laplacian(img,-1,ksize=3)
cv2.imshow("img", np.hstack((img, dst)))

Canny边缘检测

  • Canny(image, threshold1, threshold2, edges=None, apertureSize=None, L2gradient=None)

  • 最优边缘检测的三个主要评价标准

    • 低错误率:标识出尽可能多的实际边缘,同时尽可能的减少噪声产生的误报。
    • 高定位性:标识出的边缘要与图像中的实际边缘尽可能接近。
    • 最小响应:图像中的边缘只能标识一次。
  • Canny边缘检测的一般步骤
    1.去噪:边缘检测容易收到噪声影响,在进行边缘检测前通常需要进行去噪,一般用高斯滤波去除噪音。
    2.计算梯度:对平滑后的图像采用sobel算子计算梯度和方向
    3.非极大值抑制(NMS)
    - 在获取了梯度和方向后,遍历图像,去除所有不是边界的点。
    - 实现方法:逐个遍历像素点,判断当前像素点是否是周围像素点中具有相同方向梯度的最大值。
    4.滞后阈值

img = cv2.imread("../1.jpg")
# 阈值越小,细节越丰富,绘制的边缘越精细
img1 = cv2.Canny(img, 100, 200)
img2 = cv2.Canny(img, 64, 128)
cv2.imshow("img", np.hstack((img1, img2)))

形态学

指一系列处理图像形状特征的图像处理技术。

  • 形态学的基本思想是利用一种特殊的结构元(本质上就是卷积核)来测量或提取输入图像中相应的形状或特征,以便进一步进行图像分析和目标识别。
  • 这些处理方法基本是对二进制图像进行处理,即黑白图像
  • 卷积核决定着图像处理后的效果
  • 形态学常用基本操作有:
    • 碰撞和腐蚀
    • 开运算
    • 闭运算
    • 顶帽
    • 黑帽

图像全局二值化

  • threshold(src, thresh, maxval, type, dst=None)
    src:最好是灰度图
    thresh:阈值
    maxval:最大值,最大值不一定是255,一般255
    type:操作类型常见操作:
    cv2.THRESH_BINARY
    CV2.THRESH_BINARY_INV
    CV2.THRESH_TRUNC
    CV2.THRESH_TOZERO
    CV2.THRESH_TOZERO_INV
img = cv2.imread("../1.jpg")
# 二值化操作是对灰度图像操作,将图片变成灰度图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 返回两个结果,一个是阈值,另一个是处理后的图片
ret, dst = cv2.threshold(gray, 100, 255, cv2.THRESH_BINARY)
cv2.imshow("img", np.hstack((gray, dst)))

自适应阈值二值化

  • adaptiveThreshold(src, maxValue, adaptiveMethod, thresholdType, blockSize, C, dst=None)
    adaptiveMethod:指定计算阈值的方法
    cv2.ADPTIVE_THRESH_MEAN_C:阈值取自相邻区域的平均值
    cv2.ADPTIVE_THRESH_GAUSSIAN_C:阈值取值相邻区域的加权和,权值为一个高斯窗口。
    blockSize: 领域大小(用来计算阈值的区域大小)
    C:一个常数,阈值就等于平均值或加权平均值减去这个常数。
img = cv2.imread("../1.jpg")
# 二值化操作是对灰度图像操作,将图片变成灰度图片
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 自适应阈值二值化只返回一个值,即二值化之后的结果
dst = cv2.adaptiveThreshold(gray, 255, cv2.ADAPTIVE_THRESH_GAUSSIAN_C, cv2.THRESH_BINARY_INV,3,0)
cv2.imshow("img", np.hstack((gray, dst)))

腐蚀操作

腐蚀操作也是用卷积核扫描图像,只不过腐蚀操作的卷积核一般都是1,如果卷积核内所有像素点都是白色,那么锚点即为白色。

  • erode(src, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    iterations:是腐蚀操作的迭代次数,次数越多,腐蚀操作执行的次数越多,腐蚀效果越明显。
img = cv2.imread("../1.jpg")
kernel = np.ones((3,3),np.uint8)
dst = cv2.erode(img,kernel,iterations=2)
cv2.imshow("img", np.hstack((img, dst)))

获取形态学卷积核

opencv 提供了获取卷积核的api,不需要我们手工创建卷积核。

  • getStructuringElement(shape, ksize, anchor=None)
    shape: 指卷积核的形状,不是指长宽,是指卷积核中1形成的形状,常用:
    MORPH_RECT卷积核中的1是矩形,常用。
    MORPH_ELLIPSE 椭圆
    MOTPH_CROSS 十字
img = cv2.imread("../1.jpg")
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.erode(img, kernel, iterations=2)
cv2.imshow("img", np.hstack((img, dst)))

膨胀操作

膨胀时腐蚀的相反操作,基本原理是只要保证卷积核的锚点是非0值,周边无论是0还是非0值,都变成非0值。

img = cv2.imread("../1.jpg")
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.dilate(img, kernel, iterations=2)
cv2.imshow("img", np.hstack((img, dst)))

开运算

  • 开运算和闭运算都是腐蚀和膨胀的基本应用
  • 开运算 = 腐蚀 + 膨胀
  • morphologyEx(src, op, kernel, dst=None, anchor=None, iterations=None, borderType=None, borderValue=None)
    op:cv2.MORPH_OPEN表示形态学的开运算
    kernel:如果噪点比较多,会选择大一点的kernel;如果噪点比较小,可以选择小点的kernel。
# 开运算 = 腐蚀 + 膨胀
# 开运算提供了另一种去除噪声的思路
img = cv2.imread("../1.jpg")
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_OPEN, kernel,iterations=2)
cv2.imshow("img", np.hstack((img, dst)))

闭运算

  • 闭运算 = 膨胀 + 腐蚀
# 闭运算 = 膨胀 + 腐蚀
# 闭运算可以去除图形内部的噪声
img = cv2.imread("../1.jpg")
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_CLOSE, kernel,iterations=2)
cv2.imshow("img", np.hstack((img, dst)))

形态学梯度

  • 梯度 = 原图 - 腐蚀
  • 腐蚀之后原图边缘边缘变小了,原图 - 腐蚀 就可以得到腐蚀掉的部分,即边缘。
# 注意调节kernel大小以获得更清晰的边缘
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (3, 3))
dst = cv2.morphologyEx(img, cv2.MORPH_GRADIENT, kernel,iterations=2)
cv2.imshow("img", np.hstack((img, dst)))

顶帽运算

  • 顶帽 = 原图 - 开运算
  • 开运算的效果是去除图像外的噪点,原图 - 开运算就得到了去掉的噪点。
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.morphologyEx(img, cv2.MORPH_TOPHAT, kernel,iterations=1)
cv2.imshow("img", np.hstack((img, dst)))

黑帽操作

  • 黑帽 = 原图 - 闭运算
  • 闭运算可以将图形内部的噪点去掉,那么原图 - 闭运算的结果就是图形内部的噪点。
kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (5, 5))
dst = cv2.morphologyEx(img, cv2.MORPH_BLACKHAT, kernel,iterations=1)
cv2.imshow("img", np.hstack((img, dst)))

图形轮廓

图形轮廓是具有相同颜色或灰度的连续点的曲线。
注意点:
- 为了检测的准确性,需要先对图形进行二值化或Canny操作。
- 画轮廓时辉修改输入的图像,如果之后想继续使用原始图像,应该将原始图像存储到其他变量中。

查找、绘制、计算轮廓,

  • findContours(image, mode, method, contours=None, hierarchy=None, offset=None)

    • mode: 查找轮廓的模式
      RETR_EXTERNAL = 0,表示只检测外围轮廓。
      RETR_LIST = 1,检测的轮廓不建立等级关系,即检测所有轮廓,较为常用。
      RETR_CCOMP = 2,每层最多两级,从小到大,从里到外。
      RETR_CCOMP = 3,按照树型存储轮廓,从小到大,从右到左。
    • method: 轮廓近似方法也叫ApproximationMode
      CHAIN_APPROX_NODE 保存所有轮廓上的点。
      CHAIN_APPROX_SIMPLE: 只保存角点,比如四边形,只保留四边形的4个角,存储信息少,比较常用。
    • 返回contours和hierachy即轮廓和层级
  • drawContours(image, contours, contourIdx, color, thickness=None, lineType=None, hierarchy=None, maxLevel=None, offset=None)

    • image:要绘制的轮廓图像
    • contours轮廓点
    • contourIdx: 要绘制的轮廓的编号,-1表示绘制所有轮廓
    • color:轮廓的颜色,如(0,0,255)红色
    • thickness线宽,-1表示全部填充。
  • contourArea(contour, oriented=None)

  • arcLength(curve, closed)

    • curve即轮廓
    • closed是否是闭合的轮廓
import cv2

img = cv2.imread("../1.jpg")
gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
# 二值化,注意有两个返回值,阈值和结果
ret, binary = cv2.threshold(gray, 150, 255, cv2.THRESH_BINARY)

# 轮廓查找,新版本返回两个结果,轮廓和层级
contours, hierarchy = cv2.findContours(binary, cv2.RETR_TREE, cv2.CHAIN_APPROX_SIMPLE)
# 打印轮廓,contours时list,不是ndarray,里面放的时ndarray,每个ndarray表示一个contour
print(contours)

# 绘制轮廓
# 绘制轮廓会直接修改原图
# 如果想保持原图不变,建议copy一份
img_copy = img.copy()
cv2.drawContours(img_copy, contours, -1, (0, 0, 255), 1)
# cv2.imshow("img",img)
# cv2.imshow("img_copy",img_copy)

# 计算轮廓面积和周长
area = cv2.contourArea(contours[1])  # 面积
perimeter = cv2.arcLength(contours[1], closed=True)  # 周长
cv2.waitKey(0)
cv2.destroyAllWindows()

多边形逼近

findContours后的轮廓信息contours可能过于复杂不平滑,可以用approxPolyDP函数对该多边形曲线做适当近似,这就是轮廓的多边形逼近。
approxPolyDP就是以多边形去逼近轮廓,采用的是Douglas-Peucker算法;DP算法原理比较简单,核心就是不断找多变形最远的点加入形成新的多边形,直到最短距离小于指定的精度。

  • approxPolyDP(curve, epsilon, closed, approxCurve=None)
    curve: 要近似逼近的轮廓
    epsilon: DP算法使用的阈值,值越小,越靠近原来的图像;越大,越粗糙
    closed:轮廓是否闭合
# 使用多边形逼近,近似m模拟轮廓
approx = cv2.approxPolyDP(contours[1], 5, closed=True)
# approx本质上就是一个轮廓数据
# 画出多边形逼近的轮廓
cv2.drawContours(img_copy, [approx], 0, (0, 255, 0), 2)
cv2.imshow("img_copy", img_copy)

凸包

人脸检测

人脸检测

人脸检测:在一张图像中判断是否存在人脸并找出人脸所在的位置。
人脸识别:在人脸检测的基础上收集人脸数据集合进行处理保存信息,将输入人脸与保存的信息进行对比校验,得到的是其中某个人脸。
特征值:以某种特定规则对输入源进行处理得到具有唯一性质量化的值,在人脸识别中特征值的提取有HOG-方向梯度直方图,HAAR-like特征,LBP-局部二进制模式三种方法。
分类器:根据特征值界定输入事物是否属于某种类别的过滤条件组合,未知类别的算聚类器,弱分类器的正确率高于随机分类(50%),强分类器:能满足预期分类并且正确率很高的分类器。
Adaboost:迭代算法,同一个训练集合下训练多个弱分类器,把弱分类器迭代组合成一个强分类器。
级联分类器:将多个同类型的分类器列联合起来进行推算整合以得到符合目标的最终分类器的方法。

机器学习算法

分类算法 — KNN算法

KNN算法步骤

1.准备数据,分析数据,对数据进行预处理,归一化处理
2.划分训练集和测试集。
3.计算未知样本和每个训练集样本的距离。
4.设定参数,k值。
5.将距离升序排列。
6.选取距离最小的k个点。
7.统计前k个最近邻样本点所在类别出现的次数。
8.多数表决,选择出现频率最大的类别作为未知样本的类别。

KNN算法函数

def knn(inx, dataset, labels, k):
    """
    knn算法分类器
    :param inx:未知样本(测试集)
    :param dataset:训练样本的特征矩阵(训练集)
    :param labels:训练集分类标签向量
    :param k:选择距离最小的k个点
    :return:分类结果
    """
    dist = (((dataset - inx) ** 2).sum(1)) ** 0.5  # 欧氏距离:计算未知样本和每个训练集样本的距离
    sorted_dist = dist.argsort()  # 从小到大,返回原序列的索引
    class_count = {}
    for i in range(k):  # 计算类型出现的次数
        vote_lable = labels[sorted_dist[i]]
        class_count[vote_lable] = class_count.get(vote_lable, 0) + 1
    max_type = 0
    max_count = -1
    for key, value in class_count.items():
        if value > max_count:
            max_type = key
            max_count = value
    return max_type

归一化处理

0-1标准化、Z-score标准化、sigmoid压缩法等等
0-1标准化公式:
normalization = x- min / max -min

def autoNorm(dataset):
    minvals = dataset.min(0)
    maxvals = dataset.max(0)
    normaldataset = np.zeros (dataset.shape)
    normaldataset = (dataset-minvals) / (maxvals-minvals)
    return normaldataset

KNN算法的探讨

  • 优点:
    1.简单好用,容易理解,易于实现,可以做分类也可以做回归。
    2.可用于数值型数据和离散型数据。
    3.适合对稀有事件进行分类。
    4.适合于多分类问题。(对象具有多个类别标签)。
  • 缺点:
    1.样本库容量依赖性较强:
    样本小时误差难以控制。
    2.无法给出数据的基础结构信息:
    无法给出数据的内在含义,无法知晓平均实例样本和典型实例样本具有什么特征。
    3.分类计算量大,速度慢,空间复杂度高。
    4.k值不好确定。

分类算法 — 支持向量机原理

支持向量机本质

  • 理解支持向量机的第一个层次 — 支持向量
    找到正确分类训练数据的一组直线。
    在找到的所偶直线中,选择那条离最接近的数据点距离最近的直线。
    距离最接近的数据点称为支持向量(support vector)。支持向量定义的沿着分隔线的区域成为间隔(margin)。

目标:找到一个超平面,使得它能够尽可能多的将两类数据点正确的分开,同时使分来的两类数据点距离分类面最远。

  • 理解支持向量机的第二个层次 — 允许误差
  • 理解支持向量机的第三个层次 — 非线性可分-降维打击
  • 理解支持向量机的第四个层次 — 核函数
    核函数在低维上进行计算,将实质上的分类效果表现在高维上,避免复杂的高维计算。
    能这样做的条件:
    1.定义的核函数能够对应于特征空间中的内积;
    2.识别方法中不需要计算特征空间中的矢量本身,而只须就算特征空间中两个矢量的内积。
    常用的核函数:
    1.线性核函数
    2.多项式核函数
    3.高斯核函数

支持向量机实战

python机器学习库SKlearn

scikit-learn是基于python语言的机器学习工具。

  • 简单高效的数据挖掘和数据分析工具
  • 可供在各种环境重复使用
  • 建立在numpy,scipy和matplotlib上
  • 开源。可商用使用 -BSD许可证。
    官网http://www.scikitlearn.com.cn
入门SKlearn

1.导入库:from sklearn import svm
2.模型定义: model = svm.SVC()
3.模型函数: model.fit(trainingMat,hwlabels)
4.模型测试:classifierresult = model.predict(vectorundertest)

分类算法 — 决策树

决策时的定义

  • 决策树(Decision tree)又称为判定树,是数据挖掘技术中重要的分类和回归方法。是一种以树形结构来表达的预测分析模型。
  • 决策树是监督学习算法
  • 决策树有两种:分类树和回归树
  • 互斥且完备:每一个实例都被有且仅有一条路径和规则覆盖

决策树的构建

  • 策略:自上而下分而治之
  • 递归停止条件:
    1.当前节点包含的样本全属于同一个类别—无需划分。
    2.当前属性集为空,或是所有样本在所有属性上取值相同—无法划分。
    3.当前节点包含的样本集合为空—不能划分。
  • 特征(属性)选择
    • 特征选择是决定用哪个特征来划分特征空间
    • 特征选择表示众多的特征中选择一个特征作为当前节点分裂的标准
    • 如何选择特征有不同的量化评估方法,从而衍生出不同的决策树

决策树特征选择

  • `信息熵(entropy)是度量样本集合“纯度”最常用的一种指标。
  • 信息增益直接以信息熵为基础,计算当前划分对信息熵所造成的变化。
    信息增益 = 划分前的信息熵 - 划分后的信息熵
    信息增益大,越纯。
  • 增益率
    gain_ratio(D,a) = Gain(D,a) / IV(a)
    属性a的可能取值数目越多(即V越大),则IV(a)的值通常就越大。
    启发式:先从候选划分属性中找出信息增益高于平均水平的,再从中选取增益率最高的。
  • 基尼指数 - CART算法
    反映了从D中随机抽取两个样例,其类别标记不一致的概率。
    Gini(D)越小,数据集D的纯度越高。

决策树剪枝

划分选择的各种准则虽然对决策树的尺寸有较大影响,但对泛化性能的影响很有限。
例如信息增益于基尼指数产生的结果,仅在约2%的情况下不同。
剪纸方法和程度对决策树泛化性能的影响更为显著。
剪枝是决策树防止过拟合的手段
在数据带噪时甚至可能将泛化性能提升25%。

  • 预剪枝 vs 后剪枝
    • 事件开销:
      预剪枝:训练时间开销降低,测试事件开销降低
      后剪枝:训练时间开销增加,测试时间开销降低
    • 过/欠拟合风险:
      预剪枝:过拟合风险降低,欠拟合风险增加
      后剪枝:过拟合风险降低,欠拟合风险基本不变
    • 泛化性能:
      后剪枝 通常由于 预剪枝

连续值与缺失值处理

  • 连续值
    连续属性离散化,二分法
  • 缺失值处理
    样本赋权,权重划分
    1.先剔除缺失值计算信息熵
    2.再按无缺失值计算信息增益,并赋予权重(无缺失值)
    3.再选出信息增益最大的,缺失值同时进入所有的分支。

决策树本质

轴平行分类

  • 优点:
    1.速度快
    2.准确度高
    3.非参数学习
  • 缺点:
    1.缺乏伸缩性
    2.对连续的值处理效率不高
from sklearn.tree import DecisionTreeClassifier
model = DecisionTreeClassifier()

回归算法 — 相关和回归

研究和测度两个或两个以上变量之间关系的方法有回归分析和相关分析。
相关分析:研究两个或两个以上随机变量之间线性依存关系的紧密程度。通常用相关系数表示,多元相关时用复相关系数表示。
回归分析:研究某一随机变量(因变量)与其他一个或几个普通变量(自变量)之间的数量变动的关系。

  • 相关分析
    相关系数---- 对变量之间关系密切程度的度量
    r的取值范围时[-1,1]:
    完全相关 / 完全正相关 /完全负相相关 / 不存在线性相关关系 / 负相关 / 正相关
    |r| > 0.7高度相关
    |r| < 0.3 低度相关
    0.3 < |r| <0.7 中度相关
    缺点: r接近于1的程度与n相关。
import numpy as np
import pandas as pd

income = [20, 40, 20, 30, 10, 10, 20, 20, 20, 30]
production = [30, 60, 40, 60, 30, 40, 40, 50, 30, 70]

df = pd.DataFrame({'income':np.array(income),'production':np.array(production)})
print(df)
print(df.corr()) # 相关系数
print(df["income"].corr(df['production']))
  • 相关分析和回归分析区别
    区别:
    相关分析:研究变量都是随机变量,不分自变量和因变量。
    回归分析:明确的自变量和因变量,自变量是确认的普通变量,因变量是随机变量。
    联系:
    事物之间相互依存关系的两个不可分割的方面。在实际工作中,一般先进行相关分析,由相关系数的大小决定是否需要进行回归分析。在相关分析的基础上建立回归模型,以便进行推算、预测。

回归算法 — 一元线性回归与最小二乘法

  • 一元线性回归(linear regression)
    只研究一个自变量与一个因变量之间的统计关系。
  • 最小二乘法(least squares regression)
    1.原数列的观测值与模型估计值的离差平方和(即所有点到该直线的垂直距离的平方和)为最小。
    2.原数列的观测值与模型估计值的离差总和为0。
  • 高斯-马尔可夫定理
    高斯马尔可夫定理(Gauss-markov theory)在给定经典线性回归的假定下,最小二乘法估计量是具有最小方差的线性无偏估计量。
lr = linear_model.LinearRegression()
lr. fit(x,y)
print(lr.coef_)
print(lr.intercept_)

回归算法 — 多元线性回归与梯度下降算法

梯度下降法

梯度下降法(Gradient descent)是一个最优化算法,通常也称为最速下降法。1874年由著名的数学家柯西给出。
函数变化最快的方向就是函数的梯度方向。
批量梯度下降法、随机梯度下降算法(Stochastic gradient descent,SGD)

  • 步骤:
    输入:α、迭代次数
    初始化回归系数
    重复:向负梯度方向递归
    直到:达到迭代次数或收敛
    其中α称为学习速率,即每次“前进”的步长
  • 关于学习率:
    α过大容易“越过”极值点,导致不收敛,过小则收敛速度慢。
    随着迭代次数的增加,一般要慢慢减少α(直观上,先快后慢。)

无监督学习 — 聚类算法

聚类(clustering)的定义

聚类目的在将相似的事务归类。
聚类分析又称为“同质分组”或者“无监督的分类”,指把一组数据分成不同的“簇”,每簇中的数据相似而不同簇间的数据则距离较远。
簇内文档之间应该彼此相似
簇间文档之间差异大
无监督意味着没有已标注好的数据集。

K-Means算法

k-均值聚类算法中的每个簇都定义为其质心向量。
划分准则:使得所有文档到其所在簇的质心向量的平方和最小。
通过以下两步来实现目标优化:
重分配(reassignment):将每篇文档分配给离它最近的簇
重计算(recomputation):重新计算每个簇的质心向量

from sklearn.cluster import KMeans
....
model = KMeans(n_cluster=4) # K类,4类
model.fit(dataset)
print(model.cluster_centers_) # 打印中心
plt.scatter(dataset[:,0],dataset[:,1],c=model.labels_)
  • K-均值聚类算法的决定性因素
    • 数据的采集和抽象,初始化的中心选择。
    • 最大迭代次数,收敛值。
    • k值的选定。
    • 度量距离的手段。

层次聚类算法

  • 自底向上方法(合并):开始时,将每个样本作为单独的一个组;然后,依次合并相近的样本或组,直至所有样本或组被合并为一个组或者达到终止条件为止。
    代表算法:AGNES算法

  • 自顶向下方法(分裂)
    代表算法:DIANA算法

  • 关键问题:如何定义簇相似度

    • 单连接(single-link):最大相似度
      计算任意两篇文档之间的相似度,取其中的最大值(距离最近)
    • 全连接(complete-link):最小相似度
      计算任务两篇文档之间的相似度,取其中的最小值
    • 质心法:平均的类间相似度
      所有的簇间文档对之间相似度的平均值(不包括同一个簇内的文档之间的相似度)。
      这等价于两个簇质心之间的相似度。
    • 组平均(group-average):平均的类内和类间相似度
      所有的簇间文档对之间相似度的平均值(包括同一个簇内的文档之间的相似度)

主成分分析

多个指标降为少数几个综合指标的过程在数学上叫降维。
满足以下条件:
每个主成分的系数平方和为1.
主成分之间相互独立,即无重叠的信息。
主成分的方差依次递减,重要性依次递减。

  • 步骤:
    1.求样本均值和样本协方差矩阵
    2.求解协方差矩阵的特征方程
    3.解得三个特征值和对应的单位特征向量
    4.写出三个主成分的表达式

人工神经网络

人工神经网络(ANN)的定义

广义:
人工神经网络(artificial neural networks)也简称为审计网络或称作连接模型,是对人脑或自然神经网络若干基本特性的抽象和模拟,以大量的具有相同结构的简单单元的连接,来模拟人类大脑的结构和思维方式的一种可实现的物理系统,可通过计算机程度来模拟实现。

ANN基本原理

  • 生物神经元模型:
    细胞体、树突、轴突、突轴
    神经元、生物神经网络、大脑学习过程
  • 典型的激活函数:
    sigmoid函数
    双曲函数和sigmoid函数也称为s形函数,他们具有平滑性和渐近性,并保持单调性。

BP神经网络的基本原理

单层感知机:模型中的激活函数多采用符号函数,因此输出值为二值量,主要用于简单模式分类。
多层感知机:模型通过感知器的组合以及采用s型激活函数,可输出值为0-1之间的连续值,可实现输入到输出的任意非线性映射。
bp神经网络 = 多层感知机 + 反向误差传播(back propagation)学习(训练)算法即模型训练或者说连接权重的调整采用反向传播学习算法。

  • BP学习算法类型:
    监督学习—已知样本数据及其期望值(标签值)
  • BP学习算法核心思想:
    将输出误差以某种形式通过隐藏层向输入层逐层反传,将误差分摊给各层的所有神经元,修正各神经元权值。
  • 学习过程:
    信号正向传播 --> 误差反向传播
  • BP学习算法步骤:
    1.正向传播:
    输入样本 — 输入层 — 各隐层 — 输出层
    2.判断是否转入反向传播阶段:
    若输出层的实际输出与期望的输出不符
    3.误差反传
    误差以某种形式在各层表示 — 修正各层单元的权值
    4.终止条件
    网络输出的误差减少到可接受的程度进行到预先设定的学习次数为止。

深度学习

深度学习本质

1.特征自动学习
2.层次网络结构
3.深层网络结构

  • 本质:
    通过构建多隐层的模型和海量训练数据(可为无标签数据),来学习更有用的特征,从而最终提升分类或预测的准确性。“深度学习”是手段,“特征学习”是目的。

自动编码机

自动编码机就是一种尽可能复现输入信号的神经网络。

第一步:采用自下而上的无监督学习 — wake-sleep算法。
第二步:自顶向下的监督学习

卷积神经网络(CNN)

  • 卷积:
    局部特征提取
    训练中进行参数学习
    每个卷积核提取特定模式的特征
    卷积神经网络训练的是----卷积核的参数

  • 池化(下采样):
    降低数据维度,避免过拟合
    增强局部感受野
    提高平移不变性
    -全连接:
    特征提取到分类的桥梁

Keras

官网:https://keras.io/
基于python的深度学习库
keras是一个用python编写的高级神经网络API,它能够以tensorflow,cntk,或者theano作为后端运行。
-运行简单而快速的原型设计(用户友好,高度模块化,可扩展性)
-同时支持卷积神经网络和循环神经网络,以及两者的组合
-在CPU和GPU上无缝运行。

# 安装
pip install keras
pip install tensorflow / pip install theano

# keras.jsonw文件 修改配置文件的后端
"floatx":"float32",
"epsilon":"1e-07",
"backend":"tensorflow",
"image_data_format":"channels_last"
DNN的keras实战
from os import listdir
from keras.utils.np_utils import to_categorical
from keras.models import Model
from keras.layers import Input, Dense, Flatten, Dropout
from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau
from keras.models import load_model

import matplotlib.pyplot as plt
import numpy as np


def img2vector(filename):
    returnVect = np.zeros((32, 32))
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[i, j] = int(lineStr[j])
    return returnVect


# 9.模型复现
seed = 42
np.random.seed(seed)  # 固定随机种子,使得模型训练结果可以复现

# 2.数据读取
hwlabels = []
trainingfilelist = listdir("trainingDigits")
m = len(trainingfilelist)
trainingmat = []
for i in range(m):
    filenamestr = trainingfilelist[i]
    filestr = filenamestr.split('.')[0]
    classnumstr = int(filestr.split("_")[0])
    hwlabels.append(to_categorical(classnumstr, 10))  # 独热编码(one-hot enconding) 从一维变成10维
    trainingmat.append(img2vector('trainingDigits/%s' % filenamestr))
trainy = np.array(hwlabels)
trainx = np.array(trainingmat)

print(trainx.shape)
# 将三维的ndarray变成4维的
trainx = trainx.reshape((trainx.shape[0],
                         trainx.shape[1],
                         trainx.shape[2],
                         1))
print(trainx.shape)

# 3.建立模型
inp = Input(shape=(32, 32))  # 输入层
x = Flatten(name='flatten')(inp)  # 将输入“压平”,即把多维的输入一维化,常用在从其他层到全连接层的过渡。
x = Dense(400, activation="relu", name="dense-1")(x)  # 全连接层
x = Dropout(0.2, name="dropout-1")(x)  # 删除一些连接,防止过拟合
x = Dense(10, activation="softmax", name="recognition")(x)  # 全连接层
model = Model(inp, x)

# 4.模型编译与显示
model.compile(optimizer='adam',
              loss='mse',
              metrics=['accuracy'])
# optimizer:优化器
#     SGD:随机梯度下降优化器
#     RMSprop:均方根传播优化器,通常是训练循环神经网络RNN的不错选择
#     AdaGrad:适应性梯度优化器,每一个参数保留一个学习率以提升在稀疏梯度上的性能
#     Adam:自适应矩估计优化器,同时获得了AdaGrad和RMSProp算法的优点。
# loss:损失函数(目标函数)
#     mse:均方根误差
# metrics:评价指标(评价函数和损失含数相似,只不过评价函数的结果不会用于训练过程中)
model.summary()

# # 5.模型训练
# # 8.保存和加载模型
modelfilepath = "model.best.hdf5"  # 存入模型的名称
checkpoint = ModelCheckpoint(modelfilepath, monitor="val_accuracy", verbose=1, save_best_only=True, mode="max")  # 保存最好的
earlypoint = EarlyStopping(monitor="val_accuracy", patience=20, verbose=1, mode="auto")  # 没有变化自动停止训练
reduce_lr = ReduceLROnPlateau(monitor="val_loss", factor=0.1, patience=10, verbose=1, mode="auto", min_delta=0.00001,
                              cooldown=0, min_lr=0)  # 学习率自动调整
history = model.fit(trainx, trainy, validation_split=0.1, epochs=100, batch_size=32,
                    callbacks=[checkpoint, earlypoint, reduce_lr])  # 设置验证集比例,迭代次数,样本批次大小

# testmodel = load_model(modelfilepath)  # 加载训练好的模型

# 6.模型测试
testFileList = listdir('testDigits')
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
    fileNameStr = testFileList[i]
    fileStr = fileNameStr.split('.')[0]
    classNumStr = int(fileStr.split('_')[0])
    vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
    testVector = []
    testVector.append(vectorUnderTest)
    testX = np.array(testVector)
    classifierResult = np.argmax(model.predict(testX))
    print(u"DNN得到的辨识结果是: %d, 实际值是: %d" % (classifierResult, classNumStr))
    if classifierResult != classNumStr: errorCount += 1.0
print("\n辨识错误数量为: %d" % errorCount)
print("\n辨识率为: %f %" % ((1 - errorCount / float(mTest)) * 100))

# 7.绘制学习曲线
plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper left')
plt.show()

# # 加深网络模型
# relu函数是目前比较火的一个激活函数,函数公式:f(x) = max(0,x)
# 相比sigmod函数与tanh函数有以下几个优点
# 1.客服梯度消失的问题
# 2.加快训练速度
# 缺点:
# - 输入负数,则完全不激活,relu函数死掉
# - relu函数输出要么是0,要么是正数,也就是relu函数不是以0为中心的函数。

CNN的keras实战
from keras.layers import Input, Dense, Flatten, Dropout, Conv2D, MaxPool2D

from os import listdir
from keras.utils.np_utils import to_categorical
from keras.models import Model
from keras.layers import Input, Dense, Flatten, Dropout
from keras.callbacks import ModelCheckpoint, EarlyStopping, ReduceLROnPlateau
from keras.models import load_model

import matplotlib.pyplot as plt
import numpy as np


def img2vector(filename):
    returnVect = np.zeros((32, 32))
    fr = open(filename)
    for i in range(32):
        lineStr = fr.readline()
        for j in range(32):
            returnVect[i, j] = int(lineStr[j])
    return returnVect


# 9.模型复现
seed = 42
np.random.seed(seed)  # 固定随机种子,使得模型训练结果可以复现

# 2.数据读取
hwlabels = []
trainingfilelist = listdir("trainingDigits")
m = len(trainingfilelist)
trainingmat = []
for i in range(m):
    filenamestr = trainingfilelist[i]
    filestr = filenamestr.split('.')[0]
    classnumstr = int(filestr.split("_")[0])
    hwlabels.append(to_categorical(classnumstr, 10))  # 独热编码(one-hot enconding) 从一维变成10维
    trainingmat.append(img2vector('trainingDigits/%s' % filenamestr))
trainy = np.array(hwlabels)
trainx = np.array(trainingmat)

# 建立模型
inp = Input(shape=(32, 32, 1))
x = Conv2D(50, (5, 5), padding='valid', strides=(1, 1), activation='relu', name='conv-1')(inp)
x = MaxPool2D(pool_size=(2, 2), strides=(2, 2), padding='valid', name='pool-1')(x)
x = Conv2D(50, (3, 3), padding='valid', strides=(1, 1), activation='relu', name='conv-2')(x)
x = MaxPool2D(pool_size=(2, 2), strides=(2, 2), padding='valid', name='pool-2')(x)
x = Conv2D(30, (3, 3), padding='valid', strides=(1, 1), activation='relu', name='conv-3')(x)
x = MaxPool2D(pool_size=(2, 2), strides=(2, 2), padding='valid', name='pool-3')(x)
x = Dropout(0.2, name='dropout-1')(x)
x = Flatten(name='flatten')(x)
x = Dense(10, activation='softmax', name='recognition')(x)
model = Model(inp, x)

# 模型编译与显示
model.compile(optimizer='adam',
              loss='mse',
              metrics=['accuracy'])
model.summary()

modelfilepath = "model.best.hdf5"  # 存入模型的名称
checkpoint = ModelCheckpoint(modelfilepath, monitor="val_accuracy", verbose=1, save_best_only=True, mode="max")  # 保存最好的
earlypoint = EarlyStopping(monitor="val_accuracy", patience=30, verbose=1, mode="auto")  # 没有变化自动停止训练
reduce_lr = ReduceLROnPlateau(monitor="val_loss", factor=0.1, patience=10, verbose=1, mode="auto", min_delta=0.00001,
                              cooldown=0, min_lr=0)  # 学习率自动调整
history = model.fit(trainx, trainy, validation_split=0.1, epochs=100, batch_size=32,
                    callbacks=[checkpoint, earlypoint, reduce_lr])  # 设置验证集比例,迭代次数,样本批次大小

testFileList = listdir('testDigits')
errorCount = 0.0
mTest = len(testFileList)
for i in range(mTest):
    fileNameStr = testFileList[i]
    fileStr = fileNameStr.split('.')[0]
    classNumStr = int(fileStr.split('_')[0])
    vectorUnderTest = img2vector('testDigits/%s' % fileNameStr)
    testVector = []
    testVector.append(vectorUnderTest)
    testX = np.array(testVector)
    testX = testX.reshape((testX.shape[0],testX.shape[1],testX.shape[2],1))
    classifierResult = np.argmax(model.predict(testX))
    print(u"CNN得到的辨识结果是: %d, 实际值是: %d" % (classifierResult, classNumStr))
    if classifierResult != classNumStr: errorCount += 1.0
print("\n辨识错误数量为: %d" % errorCount)
print("\n辨识率为: %f %" % ((1 - errorCount / float(mTest)) * 100))

plt.plot(history.history["loss"])
plt.plot(history.history["val_loss"])
plt.title('model loss')
plt.ylabel('loss')
plt.xlabel('epoch')
plt.legend(['train', 'val'], loc='upper left')
plt.show()

图像分类

图像分类评价指标

精确率:查到准不准
precision = tp/(tp+fp)
召回率:查的全不全
recall = tp/(tp+fn)
准确率:
ACC = (tp+tn)/(tp+tn+fp+fn)
平均准确率(average precision,AP):
pr曲线下的面积,这里的average,等于是对precision进行取平均。

GoogleNet的keras实现
  • 感受野:
    在卷积神经网络中,感受野(receptive field)的定义是卷积神经网络每一个层输出的特征图上的像素点在输入图片上映射的区域大小。换句话说,感受野是特征图上的一个点对应输入图上的区域。
图像读取 — 图像增强-图像生成器

数据增强策略:

  • 翻转变换(flip):沿着水平或者垂直方向翻转图像
  • 缩放变换(zoom):按照一定的比例放大或者缩小图像
  • 平移变换(shift):在图像平面上对图像以一定方式进行平移
  • 尺度变换(scale):对图像按照指定的尺度因子,进行放大或者缩小。
  • 对比度变换(contrast):在图像的HSV颜色空间,改变饱和度S和V高度分量。
  • 噪声扰动(noise):对图像的每个像素RGB进行随机扰动,常用的噪声模式是椒盐噪声和高斯噪声。

PyTorch

官网:https://pytorch.org/get-started/locally/

pytorch基本数据类型

你可能感兴趣的:(学习笔记,人工智能,学习,笔记)