• 2020-08-19 20:42:24

神经网络，多输入多输出
反向传播使用到链式求导，公式如下：

单个神经元类

/**
* 单个神经元
*
* @author SXC 2020年8月13日 下午9:48:19
*/
public class Neurons {
ThreeNeurons tN;
double input[];
double inputandoutput[];
double weight[];// 包含一个偏置的权重，数量比输入大一个
private double nowoutput;
private double ez;// e误差对z中间输出的导数
private double ew[];// e误差对w权重的导数 同权重一起初始化
double expectation = 0;
double trainrate = 10;
double step = 0.00001;// 步进大小
double dw[];// 下次更新增量

// 输入信号数
Neurons(int inputcount) {
input = new double[inputcount];
weight = new double[inputcount + 1];
initweight();
}

public double[] getInput() {
return input;
}

public double[] getEw() {
return ew;
}

public void setEw(double[] ew) {
this.ew = ew;
}

public void setEz(double ez) {
this.ez = ez;
}

public double getEz() {
return ez;
}

public void settN(ThreeNeurons tN) {
this.tN = tN;
}

public double getNowoutput() {
return nowoutput;
}

// 设置期望值
public void setExpectation(double expectation) {
this.expectation = expectation;
}

// 计算误差值
public double errate() {
return Math.abs(calaOutput() - this.expectation);
}

// 计算模型误差值
public double merrate() {
return Math.abs(tN.calaOutput() - this.expectation);
}

// 设置权重值
public void setWeight(double[] weight) {
this.weight = weight;
if (ew == null) {
ew = new double[weight.length];
}
}

// 初始化权重
private void initweight() {
for (int i = 0; i < weight.length; i++) {
weight[i] = Math.random() * 2 - 1;
}
if (ew == null) {
ew = new double[weight.length];
}
}

// 获得权重
public double[] getWeight() {
return weight;
}

// --------------------输出打印---------------------------------------------
public void getEwtostring() {
String string = "当前ew为：[  ";
int i;
for (i = 0; i < ew.length; i++) {
string += ew[i] + "  ";
}
System.out.println("输入数：" + i + string + "] ");
}
public void getEztostring() {
System.out.println("当前ez为：[  " + ez + " ]");
}

public void getinputtostring() {
String string = "当前输入为：[  ";
int i;
for (i = 0; i < input.length; i++) {
string += input[i] + "  ";
}
System.out.println("输入数：" + i + string + "] ");
}

public void getoutnputtostring() {
System.out.println("该神经元输出：" + calaOutput());
}

public void getweighttostring() {
String string = "当前权重为：[  ";
int i;
for (i = 0; i < weight.length; i++) {
string += weight[i] + "  ";
}
System.out.println("权重数：" + i + string + "] ");
}
// --------------------输出打印---------------------------------------------

// 设置输入
public void setInput(double[] input) {
this.input = input;
}

// 设置输入输出
public void setInputandOutput(double[] inputandoutput) {
for (int i = 0; i < inputandoutput.length - 1; i++) {
this.input[i] = inputandoutput[i];
}
setExpectation(inputandoutput[inputandoutput.length - 1]);
}

// 神经元输出 0-1 sigmod(x1w1+x2w2+x3w3+bw4)
public double calaOutput() {
double output = 0;
for (int i = 0; i < input.length; i++) {
output = input[i] * weight[i] + output;
}
output = output + 1 * weight[weight.length - 1];
output = sigmoid(output);
nowoutput = output;
return output;
}

// 未经激励函数输出 x1w1+x2w2+x3w3+bw4
public double total() {
double output = 0;
for (int i = 0; i < input.length; i++) {
output = input[i] * weight[i] + output;
}
output = output + 1 * weight[weight.length - 1];
return output;

}

//----------------------调整权重---------------------------------------
// 调整权重1次
public void train() {
setDw();
updateweight();
}

// 计算权重增量
public void setDw() {
dw = new double[weight.length];
double errate = errate();
double newerrate = 0;
for (int i = 0; i < weight.length; i++) {
weight[i] += step;
newerrate = errate();
dw[i] = (newerrate - errate) / step;
weight[i] -= step;
}
}

public void msetDw() {
dw = new double[weight.length];
double errate = merrate();
double newerrate = 0;
for (int i = 0; i < weight.length; i++) {
weight[i] += step;
newerrate = merrate();
dw[i] = (newerrate - errate) / step;
weight[i] -= step;
}
}

// 更新权重
public void updateweight() {
for (int i = 0; i < dw.length; i++) {
weight[i] -= dw[i] * trainrate;
}

}

public double getTrainrate() {
return trainrate;
}

// 调整权重time次
public void train(int time) {
for (int i = 0; i < time; i++) {
train();
}
}

// 调整权重直到指定误差值
public void train(double d) {
while (errate() > d) {
train();
}
}
//----------------------调整权重---------------------------------------

// 激励函数
public double sigmoid(double input) {
return 1f / (1f + Math.pow(Math.E, -1 * input));
}
}



神经网络层类

/**
* 单个神经元
*
* @author SXC 2020年8月14日 下午9:21:20
*/
public class NetWork {
private int NeuronsC[];// 每个隐藏层神经元个数，new时初始化
private double nowoutput[];
Neurons AllNeurons[];
double input[];// 实时输入输出 input new时初始化
double expectation[];// 设定值
double trainrate = 1;// 学习率

NetWork(int m[], int in, int out) {// 隐藏层||...||隐藏层 共m层，每层m[i]个
input = new double[in];
NeuronsC = m;
int n = 0;
if (m[m.length-1]!=out) {
System.out.println("数据输入存在问题！！");
}
for (int i = 0; i < m.length; i++) {
n += m[i];
}
AllNeurons = new Neurons[n];
int index = 0;
for (int i = 0; i < m.length; i++) {
for (int j = 0; j < m[i]; j++) {
if (i == 0) {
AllNeurons[index] = new Neurons(in);//
index++;
} else {
AllNeurons[index] = new Neurons(m[i - 1]);
index++;
}
}
}
nowoutput = new double[out];
expectation = new double[out];
System.out.println("生成" + n + "个神经元");
}

public void setInput(double[] input) {
this.input = input;
}

public void setInputandLable(double[] inputandlable) {
for (int i = 0; i < input.length ; i++) {
input[i] = inputandlable[i];
}
for (int i = 0; i < expectation.length; i++) {
this.expectation[i] = inputandlable[i + input.length];
}

}

public void setExpectation(double expectation) {
this.expectation[0] = expectation;
}

public double err() {
double err=0;
for (int i = 0; i < expectation.length; i++) {
err+=(expectation[i] - forward_pass(i));
}
return err;

}

// 前向传播
public double forward_pass(int p) {
// 逐层传播
double newinput[] = null;// 除第一列外的输入数据
for (int i = 0; i < NeuronsC.length; i++) {// 一列一列来
for (int j = 0; j < NeuronsC[i]; j++) {
if (i == 0) {
getNeurons(1, j + 1).setInput(input);// 第一列用外部输入的输入数据
} else {
if (j == 0) {// 每列更新一次输入数据
newinput = new double[NeuronsC[i - 1]];
for (int k = 0; k < NeuronsC[i - 1]; k++) {
newinput[k] = getNeurons(i, k + 1).calaOutput();
}
}
getNeurons(i + 1, j + 1).setInput(newinput);// 除一列外输入的输入数据使用上一列的输出
}
}
}
for (int i = 0; i < nowoutput.length; i++) {
nowoutput[i] = getNeurons(NeuronsC.length, i + 1).calaOutput();
}

return nowoutput[p];// 输出最后一列第一个神经元的输出
}

// 反向传播 更新权重
public void update_weights() {
double[] nowoutput = getNowoutput();
// 从输出层开始 遍历各层
for (int i = NeuronsC.length; i > 0; i--) {
if (i == NeuronsC.length) {// 输出层特殊计算 暂时设定为一个神经元
for (int g = 0; g < NeuronsC[i - 1]; g++) {
Neurons Neurons = getNeurons(NeuronsC.length, g+1);
Neurons.setEz((nowoutput[g] - this.expectation[g]) * active_derivative(Neurons.getNowoutput()));
double ew[] = new double[Neurons.getWeight().length];
for (int j = 0; j < ew.length - 1; j++) {// 遍历各个权重
ew[j] = Neurons.getEz() * Neurons.getInput()[j];
}
ew[ew.length - 1] = Neurons.getEz();
Neurons.setEw(ew);
}

} else {// 计算除输出层外的ew
for (int j = 1; j < NeuronsC[i - 1] + 1; j++) {// 遍历各个该层各个神经元 i列j个神经元
Neurons Neurons = getNeurons(i, j);
// 计算ez=上一层ez*对应到上一层的权重w+....+上一层ez*对应到上一层的权重w
double ea = 0;// e对输出的导数
for (int k = 1; k < NeuronsC[i] + 1; k++) {
ea += getNeurons(i + 1, k).getEz() * getNeurons(i + 1, k).getWeight()[j - 1];
}
Neurons.setEz(ea * active_derivative(Neurons.getNowoutput()));
double ew[] = new double[Neurons.getWeight().length];
for (int l = 0; l < ew.length - 1; l++) {// 遍历各个权重
ew[l] = Neurons.getEz() * Neurons.getInput()[l];
}
ew[ew.length - 1] = Neurons.getEz();
Neurons.setEw(ew);
}
}
}
// 开始更新
for (Neurons neurons : AllNeurons) {
for (int i = 0; i < neurons.getWeight().length; i++) {
neurons.getWeight()[i] -= neurons.getEw()[i] * trainrate;
}
}
}

public double[] getNowoutput() {
forward_pass(0);
return nowoutput;
}

public double getNowoutput(int i) {
return nowoutput[i];
}

// --------------------输出打印---------------------------------------------

public void getweighttostring() {
for (Neurons neurons : AllNeurons) {
neurons.getweighttostring();
}
}

public void getEwtostring() {
for (Neurons neurons : AllNeurons) {
neurons.getEwtostring();
}
}

public void getEztostring() {
for (Neurons neurons : AllNeurons) {
neurons.getEztostring();
}
}

public void getinputtostring() {
for (Neurons neurons : AllNeurons) {
neurons.getinputtostring();
}

}

public void getoutnputtostring() {
for (Neurons neurons : AllNeurons) {
neurons.getoutnputtostring();
}
}

// 激励函数
public double active(double input) {
return 1f / (1f + Math.pow(Math.E, -1 * input));
}

// 激励函数
public double active_derivative(double input) {
return input * (1 - input);
}

// --------------------输出打印---------------------------------------------

// 返回col列,cow行的神经元,都从1开始
public Neurons getNeurons(int col, int row) {
if (row > NeuronsC[col - 1]) {
System.out.println("该层没有这么多神经元！！请求" + col + "列" + row + "行神经元");
} else {
int n = 0;
for (int i = 0; i < col - 1; i++) {
n += NeuronsC[i];
}
n += row - 1;
// System.out.println("请求"+col+"列"+row+"行神经元");
return AllNeurons[n];
}

return null;

}
}


main类

public class t {

public static void main(String[] args) {
int a[] = { 5, 5, 4, 7, 9, 2 };
double b[] = { 1, 1 };
double data0[] = { 1, 1, 1, 1 };
double data1[] = { 1, 0, 1, 0 };
double data2[] = { 0, 1, 1, 0 };
double data3[] = { 0, 0, 0, 1 };
//		double data4[] = { 1, 0, 0, 0 };
//		double data5[] = { 0, 1, 0, 0 };
//		double data6[] = { 0, 0, 1, 0 };
//		double data7[] = { 0, 0, 0, 0 };
NetWork NetWork = new NetWork(a, 2, 2);
double err = 1;
int i;
for (i = 0; err >= 0.08; i++) {
err = 0;
NetWork.setInputandLable(data0);
NetWork.update_weights();
err += Math.abs(NetWork.err());
NetWork.setInputandLable(data1);
NetWork.update_weights();
err += Math.abs(NetWork.err());
NetWork.setInputandLable(data2);
NetWork.update_weights();
err += Math.abs(NetWork.err());
NetWork.setInputandLable(data3);
NetWork.update_weights();
err += Math.abs(NetWork.err());
//			NetWork.setInputandLable(data4);
//			NetWork.update_weights();
//
//			NetWork.setInputandLable(data5);
//			NetWork.update_weights();
//
//			NetWork.setInputandLable(data6);
//			NetWork.update_weights();
//
//			NetWork.setInputandLable(data7);
//			NetWork.update_weights();
}
System.out.println("误差：" + err);
System.out.println("运行次数：" + i);
NetWork.setInputandLable(data0);
err += Math.abs(NetWork.err());
System.out.println(NetWork.getNowoutput(0) + "   " + NetWork.getNowoutput(1));
NetWork.setInputandLable(data1);
err += Math.abs(NetWork.err());
System.out.println(NetWork.getNowoutput(0) + "   " + NetWork.getNowoutput(1));
NetWork.setInputandLable(data2);
err += Math.abs(NetWork.err());
System.out.println(NetWork.getNowoutput(0) + "   " + NetWork.getNowoutput(1));
NetWork.setInputandLable(data3);
err += Math.abs(NetWork.err());
System.out.println(NetWork.getNowoutput(0) + "   " + NetWork.getNowoutput(1));
//		NetWork.setInputandLable(data4);
//		err += Math.abs(NetWork.err());
//		System.out.println(NetWork.getNowoutput()[0]);
//		NetWork.setInputandLable(data5);
//		err += Math.abs(NetWork.err());
//		System.out.println(NetWork.getNowoutput()[0]);
//		NetWork.setInputandLable(data6);
//		err += Math.abs(NetWork.err());
//		System.out.println(NetWork.getNowoutput()[0]);
//		NetWork.setInputandLable(data7);
//		err += Math.abs(NetWork.err());
//		System.out.println(NetWork.getNowoutput()[0]);

System.out.println("误差：" + err);
// NetWork.getweighttostring();
drawnet(a);
}

private static void drawnet(int[] a) {
System.out.println("----------------------------------------------------------------------------------------------");
System.out.println("神经网络图:");
int max = 0;
for (int i = 0; i < a.length; i++) {
if (max < a[i]) {
max = a[i];
}
}
for (int i = 0; i < max; i++) {// 行
String string = "";
for (int j = 0; j < a.length; j++) {// 列
if (i>=(max-a[j])/2&&i<(max+a[j])/2) {
string += "     ●     ";
} else {
string += "           ";
}
}
System.out.println(string);
}
System.out.println("----------------------------------------------------------------------------------------------");
}
}



输出结果：

生成32个神经元
误差：0.079968261269626
运行次数：31782
0.9999784568902769   0.9746964043839443
0.9915416453943027   0.026059584935733092
0.9915361463055753   0.026071465598939452
0.01106848775432035   0.9694260287169286
误差：0.16000772575870634
----------------------------------------------------------------------------------------------
神经网络图:
●
●          ●
●          ●          ●          ●          ●
●          ●          ●          ●          ●          ●
●          ●          ●          ●          ●          ●
●          ●          ●          ●          ●
●          ●                     ●          ●
●          ●
●
----------------------------------------------------------------------------------------------

更多相关内容
• 文章目录常见的‘融合’操作具有输入输出的模型ResNet 模型 常见的‘融合’操作 复杂神经网络模型的实现离不开"融合"操作。常见融合操作如下： （1）求和，求差 # 求和 layers.Add(inputs) # 求差 layers....

# 常见的‘融合’操作

复杂神经网络模型的实现离不开"融合"操作。常见融合操作如下：

（1）求和，求差

# 求和
layers.Add(inputs)
# 求差
layers.Subtract(inputs)


inputs: 一个输入张量的列表（列表大小至少为 2）,列表的shape必须一样才能进行求和(求差)操作。

例子：

input1 = keras.layers.Input(shape=(16,))
x1 = keras.layers.Dense(8, activation='relu')(input1)
input2 = keras.layers.Input(shape=(32,))
x2 = keras.layers.Dense(8, activation='relu')(input2)
added = keras.layers.add([x1, x2])

out = keras.layers.Dense(4)(added)
model = keras.models.Model(inputs=[input1, input2], outputs=out)


（2）乘法

# 输入张量的逐元素乘积(对应位置元素相乘，输入维度必须相同)
layers.multiply(inputs)
# 输入张量样本之间的点积
layers.dot(inputs, axes, normalize=False)


dot即矩阵乘法，例子1：

x = np.arange(10).reshape(1, 5, 2)

y = np.arange(10, 20).reshape(1, 2, 5)

# 三维的输入做dot通常像这样指定axes,表示矩阵的第一维度和第二维度参与矩阵乘法，第0维度是batchsize
tf.keras.layers.Dot(axes=(1, 2))([x, y])
# 输出如下：
<tf.Tensor: shape=(1, 2, 2), dtype=int64, numpy=
array([[[260, 360],
[320, 445]]])>


例子2：

x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
dotted = tf.keras.layers.Dot(axes=1)([x1, x2])
dotted.shape
TensorShape([5, 1])


（3）联合：

# 所有输入张量通过 axis 轴串联起来的输出张量。
layers.add(inputs,axis=-1)

• inputs: 一个列表的输入张量（列表大小至少为 2）。
• axis: 串联的轴。

例子：

x1 = tf.keras.layers.Dense(8)(np.arange(10).reshape(5, 2))
x2 = tf.keras.layers.Dense(8)(np.arange(10, 20).reshape(5, 2))
concatted = tf.keras.layers.Concatenate()([x1, x2])
concatted.shape
TensorShape([5, 16])


（4）统计操作

求均值layers.Average()

input1 = tf.keras.layers.Input(shape=(16,))
x1 = tf.keras.layers.Dense(8, activation='relu')(input1)
input2 = tf.keras.layers.Input(shape=(32,))
x2 = tf.keras.layers.Dense(8, activation='relu')(input2)
avg = tf.keras.layers.Average()([x1, x2])
# x_1 x_2 的均值作为输出
print(avg)
# <tf.Tensor 'average/Identity:0' shape=(None, 8) dtype=float32>

out = tf.keras.layers.Dense(4)(avg)
model = tf.keras.models.Model(inputs=[input1, input2], outputs=out)


layers.Maximum()用法相同。

# 具有多个输入和输出的模型

假设要构造这样一个模型：

（1）模型具有以下三个输入

• 工单标题（文本输入），
• 工单的文本正文（文本输入），以及
• 用户添加的任何标签（分类输入）

（2）模型将具有两个输出：

• 介于 0 和 1 之间的优先级分数（标量 Sigmoid 输出）
• 应该处理工单的部门（部门范围内的 Softmax 输出）。

模型大概长这样：

接下来开始创建这个模型。

（1）模型的输入

num_tags = 12
num_words = 10000
num_departments = 4

title_input = keras.Input(shape=(None,), name="title")  # Variable-length sequence of ints
body_input = keras.Input(shape=(None,), name="body")  # Variable-length sequence of ints
tags_input = keras.Input(shape=(num_tags,), name="tags")  # Binary vectors of size num_tags



（2）将输入的每一个词进行嵌入成64-dimensional vector

title_features  = layers.Embedding(num_words,64)(title_input)
body_features  = layers.Embedding(num_words,64)(body_input)


（3）处理结果输入LSTM模型，得到 128-dimensional vector

title_features = layers.LSTM(128)(title_features)
body_features = layers.LSTM(32)(body_features)


（4）concatenate融合所有的特征

x = layers.concatenate([title_features, body_features, tags_input])



（5）模型的输出

# 输出1，回归问题
priority_pred = layers.Dense(1,name="priority")(x)

# 输出2，分类问题
department_pred = layers.Dense(num_departments,name="department")(x)


（6）定义模型

model = keras.Model(
inputs=[title_input, body_input, tags_input],
outputs=[priority_pred, department_pred],
)


（7）模型编译

编译此模型时，可以为每个输出分配不同的损失。甚至可以为每个损失分配不同的权重，以调整其对总训练损失的贡献。

model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss={
"priority": keras.losses.BinaryCrossentropy(from_logits=True),
"department": keras.losses.CategoricalCrossentropy(from_logits=True),
},
loss_weights=[1.0, 0.2],
)


（8）模型的训练

# Dummy input data
title_data = np.random.randint(num_words, size=(1280, 10))
body_data = np.random.randint(num_words, size=(1280, 100))
tags_data = np.random.randint(2, size=(1280, num_tags)).astype("float32")

# Dummy target data
priority_targets = np.random.random(size=(1280, 1))
dept_targets = np.random.randint(2, size=(1280, num_departments))

# 通过字典的形式将数据fit到模型
model.fit(
{"title": title_data, "body": body_data, "tags": tags_data},
{"priority": priority_targets, "department": dept_targets},
epochs=2,
batch_size=32,
)


# ResNet 模型

通过add来实现融合操作，模型的基本结构如下：

# 实现第一个块
_input = keras.Input(shape=(32,32,3))
x = layers.Conv2D(32,3,activation='relu')(_input)
x = layers.Conv2D(64,3,activation='relu')(x)
block1_output = layers.MaxPooling2D(3)(x)

# 实现第二个块
x = layers.Conv2D(64,3,padding='same',activation='relu')(block1_output)
x = layers.Conv2D(64,3,padding='same',activation='relu')(x)
block2_output = layers.add([x,block1_output])

# 实现第三个块
x = layers.Conv2D(64, 3, activation="relu", padding="same")(block2_output)
x = layers.Conv2D(64, 3, activation="relu", padding="same")(x)
block_3_output = layers.add([x, block2_output])

# 进入全连接层
x = layers.Conv2D(64,3,activation='relu')(block_3_output)
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(256, activation="relu")(x)
x = layers.Dropout(0.5)(x)
outputs = layers.Dense(10)(x)


模型的定义与编译：


model = keras.Model(_input,outputs,name='resnet')

model.compile(
optimizer=keras.optimizers.RMSprop(1e-3),
loss='sparse_categorical_crossentropy',
metrics=["acc"],
)



模型的训练

(x_train, y_train), (x_test, y_test) = keras.datasets.mnist.load_data()
# 归一化
x_train = x_train.astype("float32") / 255
x_test = x_test.astype("float32") / 255
model.fit(tf.expand_dims(x_train,-1), y_train, batch_size=64, epochs=1, validation_split=0.2)


注：当loss = =keras.losses.CategoricalCrossentropy(from_logits=True)时，需对标签进行one-hot：

y_train = keras.utils.to_categorical(y_train, 10)

展开全文
• 输入输出数据维度都在0-3范围。 我的思路是这样，做一个8输入1输出的网络。做6个网络并行输入。或者做一个直接8-6的网络。前者就是输入单输出，后者就是一个直接的映射。 2神经网络 输入层节点数取决于输入...

1 项目背景
一个数据集，满足多对多 的对应关系。他希望用神经网络解决它的数据集逆问题。他给了我一个8输出，6输出的一个excel表格，前六列是输出后8列是输入。这样我利用matlab将表格导入为’.mat’文件。输入输出数据维度都在0-3范围。
或者做一个直接8-6的网络。前者就是多输入单输出，后者就是一个直接多对多的映射。
2神经网络
输入层节点数取决于输入向量长度
隐含层取决于数据集复杂程度，不宜过多不宜过少。
输出层，希望映射的数据节点。
学习率固定。
iteration+epoch，参数自定义
神经网络使用梯度下降算法
3数据集data.mat中的数据格式

前六列为输出数据，后8列为输出对应，一共950行。维度950*14；
4，数据处理
将数据先随机打乱，之后瓜分数据集，900训练，50测试。不进行归一化，直接输入。（如果要归一化，那么记得保存训练的均值和方差，在测试的时候需要使用。）
5 主要问题
1激活函数使用。我使用f=tanh（x）其中导函数f^ = (1-f^2).

2输出层需要激活函数吗？
a输出层如果没设置非线性激活函数（tanh,sigmoid）。如果考虑到输出的数据大小，不在激活的范围值域内{-1-1}，那么不需要激活函数。那么计算梯度的时候这一层就是线性的，计算梯度时候需要认为梯度是1。输出层是线性的方便在于，多元非线性拟合，或者数据预测时，不用反归一化。数据输出就是我们希望的目标数据。
并且求梯度的时候，方便了输出层的上一层。上一层隐含层输出的梯度计算
隐含层误差梯度=（输出层误差x激活函数导数） ，那么隐含层到输出层权值的变化量就是delat_w=学习率x隐含层误差梯度x隐含层输出，激活为线性的函数，那么导数为1.delat_W=学习率x输出误差x隐含层输出。这将大大简化编程和计算量。（利用神经网络的容错性。误差梯度不完全计算反向的非线性传导，按照权值矩阵分配有时候不失为一种好的方法，这就是为什么有些多层神经网络的隐含层层的误差梯度计算，有的是按照线性的误差传递）。

我试了一下按照线性误差比例反传梯度，和按照非线性激活函数反传的对比试验效果基本是一样的。（）

b输出层设置非线性激活函数的时候，通常网络上常见的都是输出值域在（-1，1）或者是sigmoid的（0-1），，这时候我们需要计算他的反向传播的梯度。但是，但是，但是，我见过，使用了激活函数sigmoid输出，但是反传的时候。依旧按照线性梯度为1计算的，忽视梯度的变化，由于输出数据范围满足激活函数值域（0-1）。并且利用网络的容错性，可以实现线性传到输出到隐含层。只要隐含层网络中有非线性一个层就好，就可以实现收敛。当然如果非线性层多，那么就能够拟合更复杂的函数结构。
（那么全部按照线性传误差梯度，实现多层网络的非线性计算就变成了可能。神经网络神奇之处）
4 matlab神经网络主程序

 %% 主函数
clear
Err_squ=[]
m=0;                  %迭代次数初始化定义
Err_record=[];        %每个数据的第一次迭代误差一共epoch*length（Y——train）个
MSE_train=[];         %mse 的每轮记录
Y_train_exp = [];     %训练集实验结果
Y_test_exp  = [];     %测试集实验结果

%%  写数据
[X_train, Y_train ,X_test ,Y_test]= writeindata(900,50); %打乱数据输入，制作数据集

%% 神经网络参数定义
In=length(X_train(1,:));                                         %输入层神经元数当前6+4小时+平均
H=100;
Out=6;                                          %输出层神经元数

w1=unifrnd(-1,1,In,H);      %初始化的方式大小可修改,高斯分布，随机分布
w2=unifrnd(-1,1,H,Out);         %随机初始化的范围可修改（-1，1） （-0.5 ，0.5） （0，1 ）等等

Epoch=10;       %数据集的重复次数代训练
Iteration=100; %一个batch训练迭代次数
Lr=0.001;    %learning rate学习率%自适应学习率

%% 训练旧数据
while (m<=Epoch)               % 外部的训练集epoch循环
m=m+1
for  i=1:size(Y_train,1)   % 串行训练从第一个数据开始
for j=1:Iteration       % 每一个数据迭代的次数
%% 前向传播
In=X_train(i,:) ;       %in的维度[1,8]

H_1i=In*w1;             %h的维度[1,100] w1[8,100]
H_1o=tanh(H_1i);

outi=H_1o*w2;
outo=outi;              %o的维度[1,6]

%误差函数E=1./2*(sum((Y_train(i)-outo).^2));

%% 反向传播
e=Y_train(i,:)-outo;        %误差函数求导后的误差，符号与反向梯度合并，所以省略不写了。

Dout=e.*1;
Dh=(e*w2').*(1-H_1o.^2);    %注意1matlab中（.*）是优先级高于*计算的.2（*）的顺序不应该改变（和矩阵维度行列的相乘有关）。

w2=w2+Lr*H_1o'*Dout;         %权值变化=学习率x输入x误差梯度符号在求e时候合并，这里*的顺序很重要。
w1=w1+Lr*In'*Dh;             %

if (j==1)
E=1./2*(sum((Y_train(i)-outo).^2));%记录每一个数据的第一次迭代时误差
Err_squ = [Err_squ E];            %记录数据集均方误差变化

end
end
end%进行一轮的迭代

%%  %记录一代过程所有数据计算的均方误差画图
if(length(Err_squ)==length(Y_train))
MSE_train=[MSE_train sum(Err_squ)/length(Y_train)];%所有代的mse记录录
Err_squ=[];%MSE%误差矩阵 循环的归零
end

end

%% 画损失函数图（不有参考意义）

plotloss(MSE_train,'MSE',Epoch);%

%% 训练数据拟合
%[Y_train_exp,MSE_trainlast,R_square_train]=test1(w1,w2,w3,X_train,Y_train);
%plotc(Y_train(1:length(Y_train),:),Y_train_exp(1:length(Y_train),:),which,R_square_train,1);%1是变化坐标0是不变化坐标
%% 测试数据拟合
[Y_test_exp,MSE_train,R_square_test]=test2(w1,w2,X_test,Y_test);

for i=1:6
plotact(Y_test(:,i),Y_test_exp(:,i),i);
end
[a1,a2,a3,a4]=test2(w1,w2,X_test(2,:),Y_test(2,:))
string=['测试输出:',num2str(a1),'\n','  实际对比: ',num2str(Y_test(2,:))]
string=['最小均方误差EMIN是：',num2str(min( MSE_train)),' r参数：',num2str(R_square_test)]



4matlab用到的程序函数
1自定义的数据集划分函数writeindata
2自定义的画图函数plotloss plotact
3自定义的测试函数test1，test2

5 测试集输出的拟合效果，前两个变量分别对应拟合。画出前两个输出拟合曲线，结果与希望对应。

测试0.58对应0.6，0.400069对应0.4，0.04对应0.。精度可以达到1%甚至0.1%。
7 程序整体链接
https://download.csdn.net/download/qq_43158059/16720744

展开全文
• 回归预测 | MATLAB实现RNN(循环神经网络)多输入多输出 目录回归预测 | MATLAB实现RNN(循环神经网络)多输入多输出基本介绍程序设计1程序设计2参考资料致谢 基本介绍 MATLAB实现深度学习多输入多输出，主要是输入多...
• 输入一组包含个因变量和个自变量的数据时，自训练估计因果关系，在输入另一组自变量时，预测个因变量
• 利用RBF网络（隐含层神经单元个数和学习率等参数可在内部修改，不作为输入参数）学习和训练，并对输入的测试样本做出响应。 输入输出维数可以多维。 实际运行，逼近y=sin(t)函数效果不错。
• 一个具有两个输入和两个输出的模型： 我们试图预测 Twitter 上的一条新闻标题有多少转发和点赞数。模型的主要输入将是新闻标题本身，即一系列词语，但是为了增添趣味，我们的模型还添加了其他的辅助输入来接收额外的...
• 一、粒子群算法及BP神经网络简介 由于BP神经网络在应用过程中初始权值和阈值随机选取,容易出现局部收敛极小点,从而降低拟合...%粒子群优化多输入多输出BP神经网络代码 clear clc tic global SamIn SamOut HiddenUnitNu
• 回归预测 | MATLAB实现CNN(卷积神经网络)多输入输出 目录回归预测 | MATLAB实现CNN(卷积神经网络)多输入输出基本介绍模型背景程序设计拓展学习发展历程主要节点参考资料致谢 基本介绍 MATLAB实现CNN(卷积神经...
• 多输入通道：当输入数据含有个通道时，我们需要构造一个输入通道数与输入数据通道数相同的卷积核，从而能够与含有输入数据做...多输出通道：通过1乘1卷积核来调整网络层之间的通道数，并控制模型的复杂度。 ...
• 之前说到的的输入输出都是二维数组（即只有两个维度：高、宽）。而真实数据实际上有很维度。比如，彩色图像除了高、宽，还有RGB三个颜色通道。所以，彩色图像在内存中表示为一个形状为3∗hx∗wx3*h_x*w_x3∗hx​∗...
• 回归预测 | MATLAB实现长短期记忆神经网络多输入输出 环境准备 清理工作区间及命令窗口 clc;clear; warning off; 导入数据 准备输入输出训练数据 input =data(:,1:4)'; output=data(:,5)'; nwhole =size...
• 简单神经网络输入为标量 对于一个最简单的神经网络而言，它的一个神经元通常长这个样子： 假设我们有a1, a2, ... , an共n个输入，对于每个...得到了SUM这个输出神经元后，我们通常会在后面加一个激活函数（上
• 上图为本文所考虑的简单的 单层多输入输出BP神经网络输入变量个数：n 隐含层神经元个数：k 输出变量个数：1输入变量：x 输出变量：y 期望输出：t 样本数量：m 隐含层-输入层连接权值：ωjp\omega _{jp} ...
• 用比较精炼的话概括就是： 输入通道指的是输入了几个二维信息，也就是很直观的rgb图有r，g，b三个...输出通道是指卷积（关联）运算之后的输出通道数目，它决定了有几个卷积核，即需要输出通道数为几，就需要几个卷积
• 回归预测 | MATLAB实现Bayes-LSTM(贝叶斯优化长短期记忆神经网络)多输入输出 目录回归预测 | MATLAB实现Bayes-LSTM(贝叶斯优化长短期记忆神经网络)多输入输出基本介绍模型介绍Bayes模型LSTM模型Bayes-LSTM模型...
• 回归预测 | MATLAB实现CNN-LSTM(卷积长短期记忆神经网络)多输入输出 目录回归预测 | MATLAB实现CNN-LSTM(卷积长短期记忆神经网络)多输入输出基本介绍模型背景CNN-LSTM模型CNN模型LSTM模型CNN-LSTM模型数据下载...
• https://zhidao.baidu.com/question/1882929579529248508.html
• 假设输入图片尺寸是 H×WH \times WH×W，卷积核（池化窗口）大小为 kh×kwk_h \times k_wkh​×kw​ 卷积层： 假设填充为 (ph,pw)(p_h, p_w)(ph​,pw​)，步幅为 (sh,sw)(s_h, s_w)(sh​,sw​)，则卷积层输出特征...
• 前文中了解到，神经网络个神经单元组成，而本篇博客将会了解到深度学习由神经网络组成，并且分为 输入层、隐藏层和输出层，隐藏层涉及到的知识点最多，是本文的重点 正文 阶层型的神经网络主要...
• logistics回归，逻辑回归问题。 图像在计算机中如何保存？要保存一张图像，要保存三个独立矩阵，对应三原色通道。...图片的特征向量x作为输入，预测输出的结果标签为y。 用一个单独的(x,y)作为一个单独的输入样本...
• 神经网络-反向传播算法 神经网络-激活函数 神经网络是将许多个神经元按一定的层次结构连接起来的网络结构。不同的层次结构会产出不同类型神经网络，比如前馈神经网络和递归神经网络。 神经元 神经元是神经网络最...
• MATLAB实现BiLSTM(双向长短期记忆神经网络)多输入输出 目录MATLAB实现BiLSTM(双向长短期记忆神经网络)多输入输出BiLSTM介绍BiLSTM回归参数设置方法学习单元设定单层BiLSTM多层BiLSTMBiLSTM程序参考资料致谢 Bi...
• 看到网上有很计算神经网络各种层的输入输出尺寸的公式，但是往往只是直接给出公式，并没有教给我们如何得到这种公式的，自己学习的时候，做一下记录以及图解 卷积层 首先给出公式，这里肯定假设输入图像是等宽高的...
• 博主对于神经网络输出神经元个数的问题，起源于“识别手写数字的神经网络为什么需要10个输出而不是四个？”. 实际上，这是两种不同的编码方式，两种的网络架构都是可行的，但是我们选择十个神经元而不是四个...
• 深度学习——吴恩达（1）_binary_classification主要内容神经网络输入输出问题 主要内容 神经网络输入输出问题 输入一个5 ×\times× 5大小的rgb图像，将图像转换成一个5×\times× 5×\times× 3 = 75 大小的...
• 如果在Tensorflow中构建一个自己的神经网络，框架会自动进行后向传播，所以只需要搭建好前向传播的部分，这里面维度必须对应好，其他的调用函数就行，现在总结一下维度问题。 从最简单的说：如下图，X是一个全是...
• 作者主页(文火冰糖的硅基工坊)：文火冰糖（王文兵）的博客_文火冰糖的硅基工坊_CSDN博客 本文网址： ...2.4 步骤2-4：神经网络输出 第3章 后向运算模型定义 3.1 步骤3-1：定义loss函数 3.2 步...
• 回归预测分析 | MATLAB实现LSTM多输入多输出

...