首先卷积神经网络一定是非循环的神经网络
神经网络的设计是以层为单位的
而每层卷积神经网络都有输入输出和W,H
四个参数
根据传递方向可得到以下性质
必须满足前一层的输出后一层的输入参数一致,也就是说最好一层一层逐级的写。
其次最好将数据的输入也要看成是一层神经网络,就是说数据的输入参数不是最重要的,而数据的输出位置的参数一定要与第一层的输入一致
且输入位置参数乘输出位置参数必须是第一层输入位置的参数的倍数
(上面的实际上和矩阵行列的乘法有关,不过为们这样理解矩阵乘法更加实用)
上面是全局都可用的性质
后面的处理
输出的时候直接使用view(-1),全部展开成一维 也就说没有输入输出区分,即是输入也是输出 w、h
view(-1,可以被上层输出整除的数) 输入,输出
但是,到这里还是不能任意输出我们想要的参数
所以要使用torch.nn.Linear(输入,输出任意参数)
使用上面的Linear 和view的配合可以调出自己想要的输出参数
与标签一致
以上观点可以设计所有非循环网络
简单介绍一下神经网络的整个原理
原理其实很简单
神经网络就是一个数学上的多元方程,具体多少自定义
反正基本上是多到你的计算机无法通过数据拟合出来方程,也就是计算机无法短时间内求出未知数前面的系数。
那么怎么办,
人们给定任意系数 计算平均方差 loss 如果有这样一组数 能让loss更小 就更新 初始系数值
但是任意过于偶然
所以就采取了梯度下降 梯度下降基本是将已知数据带入loss和系数w(权重) 的
方程中得到一个loss和w的多元方程
误差方程
只要求得误差方程loss为0 所有W的值
但是还是不能计算得出
所以对误差方程求偏导数 所谓的梯度
当梯度等于0的时候 ,是loss值的最小或最大值
虽然我们不知道 这个未知函数的最小值
但是,这 就有可能求出最小值
直接求不出 就间接的求出 都知道梯度等于0是可能最小 那么就让按照梯度的不断减小调节初始值w
知道loss的梯度为0
那么loss才有可能最小
那么要怎么更新调节 所有的w
所有下次w = 这次w -learn_rate乘这次w的梯度 这次数据要带入
输入数据的处理
神经网络的第一层是3 64 w h
你输入数据的维度 因该是 64*n 3 w h
那么如何使用pytorch 控制维度呢
这样的例子
transforms.Compose([
#transforms.ToPILImage(),
transforms.RandomCrop(32, padding=4),
transforms.RandomHorizontalFlip(),
transforms.RandomRotation(15),
transforms.ToTensor(),
transforms.Normalize(mean, std)
])
transforms.RandomCrop(w或h, padding=4),一般w=h
transforms.ToTensor() 转换成张量
transforms.Normalize(mean, std)
归一化处理
重点在于mean 和 std 的维度 决定了你的 64*n 3 w h 3的位置的维度
一般图片类的基本这个位置都是3
而前面的64*n的位置基本就是你要输入多少张图片
图片都是3通道 w h
#加载自己的数据集
class Data_set_self(data.Dataset):
def __init__(self,data_path,transforms=None):
self.transforms=transforms
# 这里要提供所有图片或数据的所有路径
# 扫描data_path 下所有图片的名字
data_name_list=os.listdir(data_path)
# 创建数据的绝对路径
self.data_path_list=[os.path.join(data_path,one_data_name) for one_data_name in data_name_list]
def __getitem__(self,index):
# 假设我们的每条数据结构是表现在名字中的 例如 dog1000.jpg
one_data_path=self.data_path_list[index]
# 假设dog是0 其他是1
one_label=0 if "dog" in one_data_path.split("/")[-1] else 1
#假设数据是图片
one_data=Image.open(one_data_path)
if self.transforms:
one_data=self.transforms(one_data)
return one_data,one_label
def __len__(self):
# 返回总数据集的长度即可
return len(self.data_path_list)
#这样就可以直接使用torch中的数据加载方法加载数据了DataLoader
#通过梯度下降的广义理解:在给定的自变量值域内进行间隔性扫描 标签域和预测值误差最小的函数,
那么说这样的扫描会把自变量域外忽略掉,
所以要将自便量域外的压缩进来
严格的说目前已经使用了激活函数,但是压缩的是 预测值得范围
通过sin(wx)可以知道 要调整这样才可以压缩进来
直接将整体拟合过程乘sin函数,为了保持原函数得y值不会随着sin变化所以要同时加上一个cos
这样就y值从来没有变化
使用将cos和sin得频率变大也就是说在定义域内(给定数据集的最大定义域内)尽可能的收集全部值得变化
通俗的说容纳了更多的波峰波谷
其实这样做并不是什么新鲜的事情 在通信领域早就这样做了
这个过程叫载波 发信号的时候 收信号的时候进行滤波 即可
这样我们的梯度下降的时候就可以 算出更多的波峰波谷
是个函数极大或者极小值得概率更高
这样也就突破了数据集大小的限制
这样还可以相位移动不改变频率 不改变原函数
突破数据集的定义域 突破数据量限制
看到数据集 外的天空
假如我们训练完的模型没有达到我们的标准
那么我们就可以不断的调整相位来提高模型的进度