我想寻求帮助。
我的目标是使用 tensorflow.js 中的非线性回归方法确定 R^2 -> R 函数中 6 个参数的值(因此具有两个自变量 x1 和 x2)。
使用TensorFlow可以达到这个结果吗?
现在我写了这个脚本:
<html>
<head>
<script src="https://cdn.jsdelivr.net/npm/@tensorflow/tfjs@latest/dist/tf.min.js"></script>
</head>
<body>
<h4>Tensorflow.js<hr/></h4>
<script>
// Create a simple model.
const x1 = tf.tensor2d([10, 11, 12], [3, 1]);
const x2 = tf.tensor2d([8, 21, 4], [3, 1]);
const y = tf.tensor2d([8, 21, 4], [3, 1]);
function Ulberg(initial_params, x1, x2, y) {
[r1_i, r2_i, s_i, t1_i, t2_i, t3_i] = initial_params;
const Vrev = tf.scalar(1.0);
const A = tf.scalar(1.0);
const r1 = tf.variable(tf.scalar(r1_i));
const r2 = tf.variable(tf.scalar(r2_i));
const s = tf.variable(tf.scalar(s_i));
const t1 = tf.variable(tf.scalar(t1_i));
const t2 = tf.variable(tf.scalar(t2_i));
const t3 = tf.variable(tf.scalar(t3_i));
const Blocco1 = tf.div(Vrev, A);
const Blocco2 = tf.add(r1, tf.mul(r2, x2));
const Blocco3 = tf.mul(Blocco1, Blocco2, x1);
const Blocco4 = tf.mul(Blocco3, s);
const Blocco5 = tf.div(t2, x1);
const Blocco6 = tf.div(t3, tf.pow(x1, 2));
const Blocco7 = tf.add(t1, Blocco5)
const Blocco8 = tf.add(Blocco7, Blocco6);
const Blocco9 = tf.log(tf.add(Blocco8, 1));
const funzione = tf.add(Blocco4, Blocco9);
const error = tf.losses.meanSquaredError(funzione.arraySync(), y.arraySync()).arraySync();
return error;
}
const initial_params = [1.0, 1.0, 1.0, 1.0, 1.0, 1.0];
console.log(Ulberg(initial_params, x1, x2, y));
const result = tf.train.minimize(() => Ulberg(initial_params, x1, x2, y), true);
console.log(result);
const optimizedParams = result.x.arraySync();
console.log("Optimized Params:", optimizedParams);
</script>
</body>
</html>
我得到:Uncaught TypeError: tf.train.minimize is not a function
我现在该如何计算这六个参数?
然后我有一个由 Vrev、I 和 T 组成的数据集,我想找到完全适合该函数的参数
我通过自己编写代码解决了这个问题,没有使用 TensorFlow。 老实说,文档非常差,使用使事情复杂化而不是简化事情的库会适得其反。
使用说明
可以通过重命名各处出现的“Ulberg”并插入您选择的函数名称来修改代码。当然,功能本身也必须改变。
如果您想增加或减少参数的数量,只需使用具有不同数量的“1”的initial_params向量开始代码即可。
向量 x1, x2,... xn, y 可以根据您的数据集具有您喜欢的大小,只要它们彼此同构即可。
除了在“ulberg”函数中添加或删除参数之外,不需要更改任何代码。
<script>
function Ulberg(initial_params, x1, x2, y) {
result = [];
if(!((x1.length == x2.length) || (x2.length == y.length))){
console.log("I vettori hanno grandezze diverse");
}
const [r1_i, r2_i, s_i, t1_i, t2_i, t3_i] = initial_params;
const Vrev = 12;
const A = 1;
const r1 = r1_i;
const r2 = r2_i;
const s = s_i ;
const t1 = t1_i;
const t2 = t2_i;
const t3 = t3_i;
// Prima elaborazione
for(i = 0; i < y.length; i++){
//Funzione completa
const valore_funzione = (Vrev) + ((r1 + r2*x1[i])/A)*x2[i] + s*Math.log10(1 + ((t1 + (t2/x1[i]) + (t3/(x1[i]*x1[i])))/A)*x2[i]);
result.push(valore_funzione);
}
//console.log(result);
//console.log("Sono stata eseguita");
return result;
}
function meanSquaredError(actual, experimental){
if(!(actual.length == experimental.length)){
console.log("I vettori hanno grandezze diverse, impossibile determinare il mean squared error.");
}
error = 0;
for(i = 0; i < actual.length; i++){
error += Math.pow((actual[i] - experimental[i]), 2);
//console.log("Errore parziale");
//console.log(error);
}
return error/actual.length;
}
function addVector(a, b){
return a.map((e,i) => e + b[i]);
}
function subtractVector(a, b){
return a.map((e,i) => e - b[i]);
}
function multiplyVector(a, b){
return a.map((e,i) => e * b[i]);
}
function divideVector(a, b){
return a.map((e,i) => e / b[i]);
}
function elevateVector(a, power){
return a.map((e,i) => Math.pow(e, power));
}
function sqrtVector(a){
return a.map((e,i) => Math.sqrt(e));
}
function multiplyScalar(a, vector){
return vector.map((e,i) => e * a);
}
/* Your data. Please make sure that all vectors have the same dimension */
const x1 = [55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55];
const x2 = [0.001256,0.007716,0.01337,0.019026,0.027493,0.033133,0.050034,0.066534,0.086245,0.105553,0.125261,0.156229,0.189204,0.232631,0.265603,0.28812,0.32109,0.345216,0.377782,0.410752,0.433669,0.467039,0.488748];
const y = [15.5113,16.3797,17.1882,18.0416,18.8204,19.2249,19.8249,20.4399,20.9205,21.386,21.8068,22.3632,22.8748,23.4324,23.8543,24.1107,24.4727,24.7592,25.0613,25.4084,25.6349,25.9222,26.0588];
const h = 0.01;
const lambda = 0.01;
const beta1 = 0.9;
const beta2 = 0.999;
const noi = 100000; /* Number of iterations */
//let initial_params = [ 1, 1, 1, 1, 1, 1 ];
let m = [0, 0, 0, 0, 0, 0];
let v = [0, 0, 0, 0, 0, 0];
let m_hat = [0, 0, 0, 0, 0, 0];
let v_hat = [0, 0, 0, 0, 0, 0];
let epsilon = [0.00000001, 0.00000001, 0.00000001, 0.00000001, 0.00000001, 0.00000001, 0.00000001, 0.00000001];
/* Se vuoi ottenere l'immagine della funzione */
//console.log(Ulberg(initial_params, x1, x2, y));
var empty_array = [];
var explore_params = [];
var gradient = [];
//Calcolo le derivate parziali
console.log(Ulberg(initial_params, [55], [0.5], [9999999]));
for(j = 0; j < noi; j++){
for(t = 0; t < initial_params.length; t++){
//console.log(initial_params.length);
explore_params = initial_params.slice();
explore_params[t] = explore_params[t] + h;
y) - meanSquaredError(Ulberg(initial_params, x1, x2, y), y))/h);
gradient.push( ((meanSquaredError(Ulberg(explore_params, x1, x2, y), y) - meanSquaredError(Ulberg(initial_params, x1, x2, y), y))/h ) );
}
m = addVector(multiplyScalar(beta1, m), multiplyScalar((1 - beta1), gradient));
v = addVector(multiplyScalar(beta2, v), multiplyScalar((1 - beta2), multiplyVector(gradient, gradient)));
m_hat.slice();
v_hat.slice();
m_hat = multiplyScalar((1/(1 - Math.pow(beta1, j+1))), m);
v_hat = multiplyScalar((1/(1 - Math.pow(beta2, j+1))), v);
initial_params = subtractVector(initial_params, divideVector(multiplyScalar(lambda, m_hat), addVector(epsilon, elevateVector(v_hat, 0.5))));
/*for(k = 0; k < initial_params.length; k++){
initial_params[k] = initial_params[k] - Math.random() * lambda * gradient[k];
}
*/
gradient = empty_array.slice();
console.log("Sto per stampare i parametri iniziali modificati:");
console.log(initial_params);
console.log("Errore:");
console.log(meanSquaredError(Ulberg(initial_params, x1, x2, y), y));
}
有趣的是,如果不使用 ADAM 优化器,代码无法收敛。