193 lines
4.5 KiB
Plaintext
193 lines
4.5 KiB
Plaintext
package bot4cj.math
|
|
import std.math.*
|
|
import cangjie_tpc::matrix4cj.Matrix
|
|
|
|
/*
|
|
* -------- Activation Functions 激活函数族 --------
|
|
* TODO(20260516-qing): 增加序列化、反序列化工厂函数
|
|
* TODO(20260825-qing): 改为使用matrix4cj库
|
|
*/
|
|
public enum Af {
|
|
|
|
None | Sigmoid | ReLU | Leaky_ReLU(Float64) | Tanh
|
|
|
|
/* -------- 执行激活函数 -------- */
|
|
public func forward(x: Matrix) {
|
|
match(this) {
|
|
case None => none(x)
|
|
case Sigmoid => sigmoid(x)
|
|
case ReLU => relu(x)
|
|
case Leaky_ReLU(alpha) => leaky_relu(x, alpha)
|
|
case Tanh => tanh(x)
|
|
}
|
|
}
|
|
|
|
/* -------- 激活函数的导数 -------- */
|
|
public func backward(y: Matrix) {
|
|
match(this) {
|
|
case None => none_dot(y)
|
|
case Sigmoid => sigmoid_dot(y)
|
|
case ReLU => relu_dot(y)
|
|
case Leaky_ReLU(alpha) => leaky_relu_dot(y, alpha)
|
|
case Tanh => tanh_dot(y)
|
|
}
|
|
}
|
|
|
|
/* -------- 序列化与反序列化 -------- */
|
|
public func get_type(): String {
|
|
return match(this) {
|
|
case None => "None"
|
|
case Sigmoid => "Sigmoid"
|
|
case ReLU => "ReLU"
|
|
case Leaky_ReLU(alpha) => "Leaky_ReLU"
|
|
case Tanh => "Tanh"
|
|
}
|
|
}
|
|
|
|
/* NOTE(20260825-qing): 这个函数在序列化时可能会有用 */
|
|
public func get_value(): Float64 {
|
|
return match(this) {
|
|
case None => Float64(0.0f64)
|
|
case Sigmoid => Float64(0.0f64)
|
|
case ReLU => Float64(0.0f64)
|
|
case Leaky_ReLU(alpha) => alpha
|
|
case Tanh => Float64(0.0f64)
|
|
case Softmax => Float64(0.0f64)
|
|
}
|
|
}
|
|
|
|
/* -------- 空的激活函数 -------- */
|
|
private static func none(M: Matrix) {
|
|
return M.copy()
|
|
}
|
|
|
|
/* -------- 空激活函数的导数 -------- */
|
|
private static func none_dot(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
return Matrix(row, col, 1.0f64)
|
|
}
|
|
|
|
/* -------- S型生长曲线 -------- */
|
|
private static func sigmoid(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 = 1.0f64 / (1.0f64 + exp(-x1))
|
|
N.set(r, c, x2)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- S型生长曲线的导数 -------- */
|
|
private static func sigmoid_dot(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 = 1.0f64 / (1.0f64 + exp(-x1))
|
|
let x3 = x2 * (1.0f64 - x2)
|
|
N.set(r, c, x3)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- 线性整流单元 -------- */
|
|
private static func relu(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 =if (x1 > 0.0f64) { x1 } else{ 0.0f64 }
|
|
N.set(r, c, x2)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- 线性整流单元的导数 -------- */
|
|
private static func relu_dot(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 =if (x1 > 0.0f64) { 1.0f64 } else{ 0.0f64 }
|
|
N.set(r, c, x2)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- 带泄露的线性整流单元 -------- */
|
|
private static func leaky_relu(M: Matrix, alpha: Float64) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 =if (x1 > 0.0f64) { x1 } else{ x1 * alpha }
|
|
N.set(r, c, x2)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- 带泄露的整流单元导数 -------- */
|
|
private static func leaky_relu_dot(M: Matrix, alpha: Float64) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 =if (x1 > 0.0f64) { 1.0f64 } else{ alpha }
|
|
N.set(r, c, x2)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- 双曲正切函数 --------*/
|
|
private static func tanh(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let x1 = M.get(r, c)
|
|
let x2 = tanh(x1)
|
|
N.set(r, c, x2)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
/* -------- 双曲正切函数的导数 -------- */
|
|
private static func tanh_dot(M: Matrix) {
|
|
let row = M.getRowDimension()
|
|
let col = M.getColumnDimension()
|
|
let N = Matrix(row, col)
|
|
for (r in 0..row) {
|
|
for (c in 0..col) {
|
|
let y_val = M.get(r, c)
|
|
let rea = 1.0f64 - y_val * y_val
|
|
N.set(r, c, rea)
|
|
}
|
|
}
|
|
return N
|
|
}
|
|
|
|
}
|