class DenseNeuronNetwork {
constructor(opt) {
this.layers = opt?.layers
this.func = opt?.func
let initFn = opt?.initParamsFn || (() => Math.random() - 0.5)
this.params = opt?.params
|| _.drop(this.layers, 1).map((n, i) => new Array((this.layers[i] + 1) * n).fill(0).map(initFn))
}
setParams(p, autoChunk) {
if (!autoChunk) {
this.params = p
return
}
let acc = 0
this.params = _.drop(this.layers, 1)
.map((l,i) => {
let readLen = l * (this.layers[i] + 1)
let from = acc
let to = acc + readLen
acc += readLen
return p.slice(from, to)
})
}
getParams(flat) {
return flat
? _.flatten(this.params)
: this.params
}
metricMul(mData, mulTo) {
let colCount = mulTo.length
let rowCount = mData.length / colCount
if (!_.isInteger(_.round(rowCount, 4))) {
throw new Error(`can not mul: ${mData} * ${mulTo}`)
}
return _.chunk(mData, colCount).map(row => row.reduce((acc, m, i) => acc + m * mulTo[i], 0))
}
sigmoid(arr) {
let {pow, E} = Math
return arr.map(v => 1 / (1 + pow(E, -v)))
}
tanh(arr) {
let {tanh} = Math
return arr.map(v => tanh(v))
}
relu(arr) {
let {max} = Math
return arr.map(v => max(0, v))
}
calc(inputs) {
return this.params.reduce((acc, curr, i) => {
let a = this.metricMul(curr, [1, ...acc])
let fnName = this.func[i]
return this[fnName](a)
}, inputs)
}
cost(inputs, targets) {
let prediction = this.calc(inputs)
let square = v => v * v
return prediction.reduce((acc, v, i) => acc + square(targets[i] - v), 0)
}
calcR2() {
return this.getParams(1).reduce((acc,v)=>acc+v*v,0)
}
}