File size: 1,976 Bytes
5c6c847 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 | """常用函数。softmax / log_softmax / gelu 写成融合算子(手写反向),更快也更数值稳定。"""
import numpy as np
from .tensor import Tensor
def relu(x):
return x.relu()
def tanh(x):
return x.tanh()
def sigmoid_np(a):
"""数值稳定:只对 -|a| 求 exp,永远不会溢出。"""
e = np.exp(-np.abs(a))
return np.where(a >= 0, 1 / (1 + e), e / (1 + e))
def sigmoid(x):
out = sigmoid_np(x.data)
return Tensor._op(out, (x,), lambda g: (g * out * (1 - out),))
def gelu(x):
"""GELU(tanh 近似,GPT-2 同款)。"""
c = np.sqrt(2 / np.pi)
a = x.data
inner = c * (a + 0.044715 * a ** 3)
t = np.tanh(inner)
out = 0.5 * a * (1 + t)
def backward(g):
dinner = c * (1 + 3 * 0.044715 * a ** 2)
return (g * (0.5 * (1 + t) + 0.5 * a * (1 - t ** 2) * dinner),)
return Tensor._op(out.astype(a.dtype), (x,), backward)
def softmax(x, axis=-1):
e = np.exp(x.data - x.data.max(axis=axis, keepdims=True))
s = e / e.sum(axis=axis, keepdims=True)
return Tensor._op(s, (x,), lambda g: (s * (g - (g * s).sum(axis=axis, keepdims=True)),))
def log_softmax(x, axis=-1):
shifted = x.data - x.data.max(axis=axis, keepdims=True)
out = shifted - np.log(np.exp(shifted).sum(axis=axis, keepdims=True))
s = np.exp(out)
return Tensor._op(out, (x,), lambda g: (g - s * g.sum(axis=axis, keepdims=True),))
def cross_entropy(logits, targets):
"""logits: (N, C);targets: (N,) 整数类别。返回平均负对数似然。"""
targets = targets.data if isinstance(targets, Tensor) else np.asarray(targets)
logp = log_softmax(logits, axis=-1)
return -logp[np.arange(len(targets)), targets].mean()
def mse_loss(pred, target):
return ((pred - target) ** 2).mean()
def dropout(x, p, training=True):
if not training or p == 0:
return x
mask = (np.random.rand(*x.shape) >= p).astype(x.dtype) / (1 - p)
return x * Tensor(mask)
|