在机器学习和神经网络中,激活函数是一种用于决定神经元输出的非线性函数。
sigmoid 函数
sigmoid 函数是一种常用的激活函数,它将输入值压缩到 0 和 1 之间。
sigmoid 函数的实现可以使用以下代码:
import numpy as np
def sigmoid(x):
return 1 / (1 + np.exp(-x))
阶跃函数
阶跃函数是一种简单的激活函数,它将输入值分为两个类别。当输入值大于 0 时,输出值为 1,否则输出值为 0。
阶跃函数的实现可以使用以下代码:
def step(x):
return np.where(x >= 0, 1, 0)
sigmoid 函数与阶跃函数的比较
sigmoid 函数和阶跃函数都是常用的激活函数,但它们有不同的特点。sigmoid 函数可以将输入值映射到 0 和 1 之间,并且它是连续可导的,因此在反向传播算法中使用 sigmoid 函数可以更容易地计算梯度。另一方面,阶跃函数是不连续的,因此在反向传播算法中无法直接使用它。在实际应用中,sigmoid 函数通常比阶跃函数更受欢迎,因为它具有更好的性能和更广泛的应用场景。
ReLU 函数
ReLU 函数是一种常用的激活函数,它在输入值大于 0 时输出输入值本身,否则输出 0。
ReLU 函数的实现可以使用以下代码:
def relu(x):
return np.maximum(0, x)
三层神经网络各层间信号传递的实现
三层神经网络通常包括输入层、隐藏层和输出层。输入层将原始数据作为输入,隐藏层对输入数据进行转换和处理,输出层将最终的输出值计算出来。下面是三层神经网络各层间信号传递的实现:
import numpy as np
def initialize_parameters(n_x, n_h, n_y):
np.random.seed(2)
W1 = np.random.randn(n_h, n_x) * 0.01
b1 = np.zeros((n_h, 1))
W2 = np.random.randn(n_y, n_h) * 0.01
b2 = np.zeros((n_y, 1))
parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2}
return parameters
def forward_propagation(X, parameters):
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
Z1 = np.dot(W1, X) + b1
A1 = relu(Z1)
Z2 = np.dot(W2, A1) + b2
A2 = sigmoid(Z2)
cache = {"Z1": Z1, "A1": A1, "Z2": Z2, "A2": A2}
return A2, cache
def compute_cost(A2, Y):
m = Y.shape[1]
cost = -np.sum(Y*np.log(A2) + (1-Y)*np.log(1-A2)) / m
cost = np.squeeze(cost)
return cost
def backward_propagation(parameters, cache, X, Y):
m = X.shape[1]
W1 = parameters["W1"]
W2 = parameters["W2"]
A1 = cache["A1"]
A2 = cache["A2"]
dZ2 = A2 - Y
dW2 = np.dot(dZ2, A1.T) / m
db2 = np.sum(dZ2, axis=1, keepdims=True) / m
dZ1 = np.dot(W2.T, dZ2) * (1 - np.power(A1, 2))
dW1 = np.dot(dZ1, X.T) / m
db1 = np.sum(dZ1, axis=1, keepdims=True) / m
grads = {"dW1": dW1, "db1": db1, "dW2": dW2, "db2": db2}
return grads
def update_parameters(parameters, grads, learning_rate):
W1 = parameters["W1"]
b1 = parameters["b1"]
W2 = parameters["W2"]
b2 = parameters["b2"]
dW1 = grads["dW1"]
db1 = grads["db1"]
dW2 = grads["dW2"]
db2 = grads["db2"]
W1 -= learning_rate * dW1
b1 -= learning_rate * db1
W2 -= learning_rate * dW2
b2 -= learning_rate * db2
parameters = {"W1": W1, "b1": b1, "W2": W2, "b2": b2}
return parameters
def predict(parameters, X):
A2, cache = forward_propagation(X, parameters)
predictions = (A2 > 0.5)
return predictions
def nn_model(X, Y, n_h, num_iterations, learning_rate):
n_x = X.shape[0]
n_y = Y.shape[0]
parameters = initialize_parameters(n_x, n_h, n_y)
for i in range(num_iterations):
A2, cache = forward_propagation(X, parameters)
cost = compute_cost(A2, Y)
grads = backward_propagation(parameters, cache, X, Y)
parameters = update_parameters(parameters, grads, learning_rate)
if i % 1000 == 0:
print("Cost after iteration %i: %f" % (i, cost))
return parameters
这里的 initialize_parameters
函数是用来初始化神经网络的参数,输入参数 n_x
、n_h
和 n_y
分别表示输入层、隐藏层和输出层的神经元数量。我们使用随机值来初始化权重,使用 0 来初始化偏置。forward_propagation
函数用来计算神经网络的前向传播,compute_cost
函数用来计算代价函数,backward_propagation
函数用来计算反向传播过程中的梯度,update_parameters
函数用来更新神经网络的参数。最后,我们使用 nn_model
函数来组合所有这些函数来训练神经网络。
softmax的特征与实现
Softmax 是一种用来将一组数值转化为概率分布的函数,通常用于多分类问题中。
Softmax 函数的实现可以使用以下代码:
def softmax(z):
e_z = np.exp(z - np.max(z))
return e_z / np.sum(e_z, axis=0)
这里,我们首先使用 np.max 函数来防止指数溢出,然后使用 np.exp 函数来计算每个输入值的指数,最后将结果除以所有指数的总和即可得到概率分布。
批处理
在训练神经网络时,我们通常会采用批处理(batch processing)的方式来处理训练数据。批处理是将一组输入样本同时输入神经网络进行训练的方法,可以减少计算时间,并更好地利用计算资源。在批处理中,我们将训练数据分成一组组大小相同的小批次,然后对每个小批次进行训练。每个小批次的大小通常为 2 的幂次方,比如 32、64 等等。
以下是批处理的实现代码:
def nn_model(X, Y, n_h, num_iterations, learning_rate, batch_size):
n_x = X.shape[0]
n_y = Y.shape[0]
m = X.shape[1]
parameters = initialize_parameters(n_x, n_h, n_y)
for i in range(num_iterations):
minibatches = random_mini_batches(X, Y, batch_size)
for minibatch in minibatches:
(minibatch_X, minibatch_Y) = minibatch
A2, cache = forward_propagation(minibatch_X, parameters)
cost = compute_cost(A2, minibatch_Y)
grads = backward_propagation(parameters, cache, minibatch_X, minibatch_Y)
parameters = update_parameters(parameters, grads, learning_rate)
if i % 1000 == 0:
print("Cost after iteration %i: %f" % (i, cost))
return parameters
def random_mini_batches(X, Y, batch_size):
m = X.shape[1]
minibatches = []
permutation = list(np.random.permutation(m))
shuffled_X = X[:, permutation]
shuffled_Y = Y[:, permutation].reshape((Y.shape[0], m))
num_complete_minibatches = math.floor(m / batch_size)
for k in range(num_complete_minibatches):
minibatch_X = shuffled_X[:, k * batch_size : (k + 1) * batch_size]
minibatch_Y = shuffled_Y[:, k * batch_size : (k + 1) * batch_size]
minibatch = (minibatch_X, minibatch_Y)
minibatches.append(minibatch)
if m % batch_size != 0:
minibatch_X = shuffled_X[:, num_complete_minibatches * batch_size : m]
minibatch_Y = shuffled_Y[:, num_complete_minibatches * batch_size : m]
minibatch = (minibatch_X, minibatch_Y)
minibatches.append(minibatch)
return minibatches
这里,我们首先使用 random_mini_batches 函数将训练数据分成一组大小相同的小批次。然后,在主循环中,我们对每个小批次进行训练,并使用 update_parameters 函数来更新神经网络的参数。注意,我们使用了 math.floor 函数来计算完整的小批次数量,并且使用了 np.random.permutation 函数来随机打乱训练数据的顺序。