全连接神经网络 FCNN
参考:公众号 阿力阿哩哩
激活函数:加上f( )这个运算的目的是将输出的值域压缩到(0,1),也就是所谓的归一化,因为每一级输出的值都将作为下一级的输入,只有将输入归一化了,才会避免某个输入无穷大,导致其他输入无效,变成“一家之言”,最终网络训练效果非常不好。
神经网络的训练是有监督的学习,也就是输入X有着与之对应的真实值Y ,神经网络的输出Y 与真实值Y 之间的损失Loss 就是网络反向传播的东西。整个网络的训练过程就是不断缩小损失Loss 的过程。
缩小loss
上述的公式经过化简,我们可以看到A、B、C、D、E、F都是常系数,未知数就是w 和b ,也就是为了让Loss 最小,我们要求解出最佳的w 和b 。
使用梯度下降法 求偏导数 获取最小的loss
w的上标i表示第几个w,下标n表示第几步,α是学习率。
BP网络中节点数目如何确定
向量的维数:维数是指向量的长度,例如向量v={a1,a2,…,an},向量有n个特征维度,则维数为n
输入层:输入层节点数=输入向量维数 即每一条数据的特征数目
输出层:输出层节点数=输出向量维数 即该条数据label的可能数
隐藏层
首先运用三种确定隐含层层数的方法得到三个隐含层层数,找到最小值和最大值,然后从最小值开始逐个验证模型预测误差,直到达到最大值,最后选取模型误差最小的那个隐含层层数。该方法适用于双隐含层网络。
python相关
- python中的乘法
- numpy中的resize
resize原尺寸:不会改变原格式数据
resize小于原尺寸:按照原数据从左往右顺序,从上往下,Z字型填充。不会改变原格式数据(直接resize会报错,需添加 refcheck=False)
resize大于原尺寸:按照原数据从左往右顺序,从上往下,Z字型填充。缺失部分填充值为0。不会改变原数据格式。
>>x = np.array([[1, 2, 3], [3, 4, 5], [5, 6, 7]])
>>x.shape
(3, 3)
>>x.resize(3, 3)
array([[1, 2, 3],
[3, 4, 5],
[5, 6, 7]])
>>x.resize((2, 2),refcheck=False)
array([[1, 2],
[3, 3]])
>>x.resize(4, 3)
array([[1, 2, 3],
[3, 4, 5],
[5, 6, 7],
[0, 0, 0]])
>>x.resize(3, 4)
array([[1, 2, 3, 3],
[4, 5, 5, 6],
[7, 0, 0, 0]])
- linspace 在指定区间内取n个数
- torch.randn:用来生成随机数字的tensor,这些随机数字满足标准正态分布(0~1)https://blog.youkuaiyun.com/weixin_47156261/article/details/116611894
import torch
a=torch.randn(3)
b=torch.randn(3,4)
print("a:",a)
print("b:",b)
a: tensor([ 0.9405, -0.1068, 0.1712])
b: tensor([[-1.0962, -0.1893, 1.2323, 0.5703],
[-1.5256, -1.4923, 0.4275, 0.5143],
[ 1.1200, 0.5317, 1.1961, -2.2533]])
- numpy中的reshape
reshape(1,-1)转化成1行
reshape(2,-1)转换成两行
reshape(-1,1)转换成1列:
使用BP网络的项目
参考:https://www.bilibili.com/video/BV1UL411j786?spm_id_from=333.337.search-card.all.click
import numpy as np
import torch
## 语音数据分类预测
# 激活函数
import torch as torch
def Sigmoid(x):
function=1.0/(1.0+np.exp(-x))
return function
#对sigmod函数的求导
def DS(x):
f=Sigmoid(x)
derivative=f*(1.0-f)
return derivative
def forward(x,w1,w2,b1,b2,xite):
'''
前项传播,给定一个输入x,输出输入层
'''
# x:[1,输入层] w1:[隐藏层,输入层]
a1=x
#[1, 隐藏层]
a2=a1@w1.T+b1
z2=Sigmoid(a2)
a3=z2@w2.T+b2
z3=Sigmoid(a3)
return z2,z3,a2,a3
def loss(y_hat,y):
## y.shape[0] 指矩阵的行数,即神经元的个数
out=np.array((y-y_hat)**2)/2*y.shape[0]
return out
## loss函数的导数,用在反向传播
def DLoss(y_hat,y):
out=np.array(y-y_hat)
return out
def grad(out,out_hat,a2,a3,w1,w2,b1,b2,z2,x,xite):
dw1_1=DLoss(out,out_hat)*DS(a3)
dw1_2=dw1_1@w2
dw1_3=dw1_2*DS(a2)
dw1=dw1_3.T@x
dw2_1=DLoss(out,out_hat)*DS(a3)
dw2=np.dot(dw2_1.T,z2)
db1_1=DLoss(out,out_hat)*DS(a3)
db1_2=db1_1@w2
db1=db1_2*DS(a2)
db2=db1_1*DS(a3)
# 权重更新
w2=w2-xite*dw2
w1=w1-xite*dw1
b2=b2-xite*db2
b1=b1-xite*db1
return w1,w2,b1,b2
def read_data(dir_str):
'''
:param dir_str:
:return:
读取txt文件中的数据
数据内容:科学计数法保存的多行多列数据
输入:txt文件的路径
输出:小数格式的数组,行列与txt文件中相同
'''
data_temp=[]
with open(dir_str) as fdata:
while True:
line=fdata.readline()
if not line:
break
data_temp.append([float(i) for i in line.split()])
return np.array(data_temp)
data=read_data(r"F:\codeForAi\语音数据txt.txt")
n=275
input1=np.array([data[:,1:25]]) #这是24个特征
# 分散数据和标签
input1.resize(2000,24)
output1=np.array([data[:,0]])
output=np.linspace(0,0,8000)#这里其实是看做生成一个长度为8000的数组
output.resize(2000,4)
for i in range(2000):#遍历 每一行 将标签化为四维矩阵
if np.array(output1[:,i]) ==1:
output[i:,]=np.array([1,0,0,0])
elif np.array(output1[:,i]) ==2:
output[i:, ] = np.array([0, 1, 0, 0])
elif np.array(output1[:, i]) == 3:
output[i:, ] = np.array([0, 0, 1, 0])
elif np.array(output1[:, i]) == 4:
output[i:, ] = np.array([0, 0, 0, 1])
#下面是为了打乱顺序
data_num,_=data.shape
index=np.arange(data_num)
np.random.shuffle(index)
index=index
print(index.shape)
print(input1.shape)
#训练集
input_train =np.array(input1[index][0:1500,:])#左闭右开
# 上面那个方法 是在index里去1500 个行。。
print(input1[index][0:1500,:].shape)
output_train =np.array(output[index][0:1500,:])
#测试集
input_test=np.array(input1[index][1500:2000,:])
print(input_test.shape)
output_test=np.array(output[index][1500:2000,:])
print(output_test.shape)
output_test1=np.zeros((1,500))
innum,midnum,outnum=(24,25,4)
w1=np.array(torch.randn(midnum,innum))#(25,24)
print(w1.shape)
w2=np.array(torch.randn(outnum,midnum))#(4,25)
b1=np.array(torch.zeros(1,midnum))#(1,25)
b2=np.array((torch.zeros(1,outnum)))#(1,4)
#设置学习律
xite=0.1
for j in range(10):
for i in range(input_train.shape[0]):
x=input_train[i].reshape(1,input_train.shape[1])
z2,out,a2,a3=forward(x,w1,w2,b1,b2,xite)
w1,w2,b1,b2=grad(out,output_train[1,:],a2,a3,w1,w2,b1,b2,z2,x,xite)
#测试
output_fore =np.zeros((500,4))
out1=[]
list1=[]
for i in range(input_test.shape[0]):
x=input_test[i].reshape(1,input_test.shape[1])
z2,out,a3,a3=forward(x,w1,w2,b1,b2,xite)
target=output_test[i].reshape(1,-1)
output_fore[i,:]=out
out1.append(target)
list=np.argmax(out)
list1.append(list)
list2=np.zeros((500,4))
for i in range(len(list1)):
if list1[i]==0:
list2[i]=np.array([1,0,0,0])
elif list1[i]==1:
list2[i]=np.array([0,1,0,0])
elif list1[i]==2:
list2[i]=np.array([0,0,1,0])
elif list1[i]==3:
list2[i]=np.array([0,0,0,1])
output_list=np.zeros(2000)
output_list2=np.zeros(500)
output_list=output1[0,index]
output_list2=output_list[index][1500:2000]
for i in range(500):
if output_list2[i]-list1[i]-1==0:
n+=1
print('准确率=',n/500)