如何让Python自定义神经网络构造函数支持可变数量隐藏层?
从零实现多隐藏层神经网络:构造函数扩展方案
嘿,你已经从零搭起了单隐藏层神经网络,现在要扩展到多隐藏层对吧?咱们来把构造函数改成支持任意数量隐藏层的版本,同时兼容你原来的单隐藏层用法。
首先看你现有代码的核心需求:要让hidden_units和act_func支持可变数量的输入——用列表定义每个隐藏层的神经元数和对应激活函数,同时兼容单个值的输入(保持单隐藏层的用法不变)。
步骤1:参数鲁棒性处理
在构造函数开头,先把输入的参数统一成列表格式,避免用户传单个值时出错:
def __init__(self, input_len, hidden_units, output_len, act_func=None, loss_func=None, init_weights=np.zeros, output_func=None, random_seed=None): if random_seed: np.random.seed(random_seed) self.loss_func = loss_func self.output_func = output_func # --- 新增:处理隐藏层参数 --- # 如果传入单个整数,转为单元素列表(兼容原有单隐藏层用法) if isinstance(hidden_units, int): hidden_units = [hidden_units] self.hidden_layer_count = len(hidden_units) self.L = self.hidden_layer_count + 2 # 输入层 + 隐藏层 + 输出层 # --- 新增:处理激活函数参数 --- if act_func is not None: # 如果传入单个函数,所有隐藏层复用同一个 if not isinstance(act_func, list): act_func = [act_func] * self.hidden_layer_count # 检查激活函数数量和隐藏层数量匹配 if len(act_func) != self.hidden_layer_count: raise ValueError(f"激活函数列表长度({len(act_func)})必须和隐藏层数量({self.hidden_layer_count})一致") # 初始化层列表 self.layers = [] # 输入层:这里假设你的Layer类接受权重、偏置、激活函数,输入层用恒等激活 input_layer = Layer(np.identity(input_len), np.zeros(input_len), id_f) self.layers.append(input_layer)
步骤2:循环创建所有隐藏层
这部分你原来的代码其实已经支持列表遍历,只要参数处理好了,直接复用就行:
# --- 创建隐藏层 --- for neurons, func in zip(hidden_units, act_func): prev_neurons = self.layers[-1].num_neurons # 初始化权重矩阵:当前层神经元数 × 前一层神经元数 weight_mat = init_weights((neurons, prev_neurons)) biases = init_weights((neurons,)) current_layer = Layer(weight_mat, biases, func) self.layers.append(current_layer)
步骤3:补充输出层创建
你的代码片段里没看到输出层的创建,这里补上(确保网络结构完整):
# --- 创建输出层 --- prev_neurons = self.layers[-1].num_neurons output_weights = init_weights((output_len, prev_neurons)) output_biases = init_weights((output_len,)) # 输出层使用指定的输出激活函数(比如softmax分类、恒等函数回归) output_layer = Layer(output_weights, output_biases, self.output_func) self.layers.append(output_layer)
关键注意事项
- Layer类的
num_neurons属性:确保你的Layer类里正确定义了这个属性,比如:class Layer: def __init__(self, weights, biases, activation): self.weights = weights self.biases = biases self.activation = activation self.num_neurons = weights.shape[0] # 当前层神经元数量 = 权重矩阵行数 - 初始化函数
init_weights:建议不要用np.zeros(会导致梯度消失),换成随机初始化比如np.random.randn乘以小系数(比如0.01):def init_weights(shape): return np.random.randn(*shape) * 0.01
使用示例
现在你的构造函数已经支持任意数量的隐藏层了:
# 单隐藏层(兼容原有写法) nn_single = NeuralNetwork( input_len=784, hidden_units=128, output_len=10, act_func=sigmoid, output_func=softmax, init_weights=lambda s: np.random.randn(*s)*0.01 ) # 双隐藏层:每层用不同激活函数 nn_double = NeuralNetwork( input_len=784, hidden_units=[256, 128], output_len=10, act_func=[relu, sigmoid], output_func=softmax ) # 三隐藏层:所有隐藏层用同一个激活函数 nn_triple = NeuralNetwork( input_len=784, hidden_units=[512, 256, 64], output_len=10, act_func=relu, output_func=softmax )
内容的提问来源于stack exchange,提问作者Sam
相关产品推荐
相关产品推荐

