为什么我只能访问数组的 39.9%?
How come I can only access 39.9% of my array?
我有一个包含 1000 个数据的数组,但由于某些原因,我只能访问其中 39.9% 的数据。
这个问题出现在我使用名为 jsPsych 的 JavaScript 库编码的反应时间游戏中。在游戏中,用户必须在图像从屏幕上消失之前单击一个按钮。游戏被操纵,以便用户在试验中保持 20% 的成功率。
我使用前高斯数据完成了这个装配。具体来说,我有一个包含 1000 个非高斯数据的数组,在每次试验开始时,我从这些数据的底部 20% 中选择一个数字来表示图像将在用户屏幕上持续多长时间。结果是用户只有 20% 的机会足够快地响应图像。此过程的目标是强制用户在试验中获得 20% 的成功率。
如果用户的持续成功率恰好大于 20%,我将每次试验成功的可能性降低 5%,直到成功率为 0.2。同样,如果用户的持续成功率低于20%,我将尝试成功的可能性提高5%,直到成功率为0.2。
问题是我无法将成功可能性提高到 0.399 以上。它应该能够一直上升到 1.0,在这种情况下,我将从我所有的前高斯数据中采样。但是,如果我允许我的游戏 运行 而不触摸按钮,则成功可能性会以 0.5 的增量增加——这是应该的——直到达到 0.399。然后,它停止增加。
我不知道为什么会这样,或者为什么成功的可能性在应该以 0.5 的增量增加时甚至可以达到 0.399。
您可以在下面查看我的代码。 请注意,您需要检查我登录到控制台的数据,才能清楚地了解我遇到的问题。
// this is just some supporting code
const jsPsych = initJsPsych();
const game = {};
// the ex-Gaussian data, sorted in ascending order
const dist = [];
for (let i = 0; i < 1000; i++) {
dist.push(jsPsych.randomization.sampleExGaussian(180, 20, 1, positive = true))
}
dist.sort(function(a, b) {
return a - b
})
console.log("Array of ex-Gaussian data:" + dist)
// initial success likelihood = 20%
let success_likelihood = 0.2;
game.timeline = [{
timeline: [{
// wait for image to appear
type: jsPsychHtmlButtonResponse,
stimulus: "<div style='visibility:hidden;'>image</div>",
choices: ["Click me!"],
trial_duration: 1000,
response_ends_trial: false,
// place feedback element here, albeit hidden, to keep page formatting consistent
prompt: "<div>Click the button as soon as the image appears.</div><div style='visibility:hidden; background-color:green; padding:20px;'>Success</div>",
},
{
// show image
type: jsPsychHtmlButtonResponse,
stimulus: "<div>image</div>",
choices: ["Click me!"],
trial_duration: function() {
// player must click button within trial duration to succeed
// player has x% chance of success on each trial
// sample trial duration from lower x% of rt distribution
let cutoff = 1000 * success_likelihood;
// subtract cutoff - 1 because array index starts at 0
return dist[cutoff - 1];
},
data: {
type: "game"
},
prompt: "<div>Click the button as soon as the image appears.</div><div style='visibility:hidden; background-color:green; padding:20px;'>Success</div>",
},
{
// feedback
type: jsPsychHtmlButtonResponse,
stimulus: "<div style='visibility:hidden;'>image</div>",
choices: ["Click me!"],
trial_duration: 2000,
response_ends_trial: false,
prompt: function() {
var last_trial = jsPsych.data.getLastTrialData();
var rt = last_trial.trials[0].rt;
// if rt === null, player failed to press button within span of trial
if (rt != null) {
return "<div>Click the button as soon as the image appears.</div><div style='background-color:green; padding:20px;'>Success</div>";
} else {
return "<div>Click the button as soon as the image appears.</div><div style='background-color:red; padding:20px;'>Missed</div>";
}
},
}
],
on_timeline_finish: function() {
// re-evaluate success rate after each trial
let total_trials = jsPsych.data.get().filter({
type: "game"
});
let success_trials = total_trials.select('rt').subset(function(x) {
return x != null;
});
let success_rate = success_trials.count() / total_trials.count();
console.log("Success rate:" + success_rate)
// adjust success likelihood +-5% until it reaches 0.2
if (success_rate > 0.2) {
success_likelihood -= 0.05;
} else if (success_rate < 0.2) {
success_likelihood += 0.05;
}
console.log("Success likelihood:" + success_likelihood)
},
loop_function: function(data) {
// stop game once player attains 12 success trials
let success_trials = jsPsych.data.get().filter({
type: "game"
}).select('rt').subset(function(x) {
return x != null;
}).count();
if (success_trials != 12) {
return true;
} else {
return false;
}
}
}]
// run code
jsPsych.run([game])
<!DOCTYPE html>
<html lang="en-CA">
<head>
<meta charset="UTF-8" />
<title>Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/jspsych@7.1.2/dist/index.browser.min.js"></script>
<link href="https://unpkg.com/jspsych@7.1.2/css/jspsych.css" rel="stylesheet" />
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@1.1.0/dist/index.browser.min.js"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.0/dist/index.browser.min.js"></script>
</head>
<body></body>
</html>
有谁知道为什么我的阵列访问受到限制?
success_likelihood根据这个只会变小,不会变大?
if (success_rate > 0.2) {
success_likelihood -= 0.05;
} else if (success_rate < 0.2) {
success_likelihood;
}
首先,您根本没有增加 success_likelyhood
,但这可能只是一个错字。
你的第二个问题是这段代码
let cutoff = 1000 * success_likelihood;
return dist[cutoff - 1];
由于浮点运算的工作原理,您的 success_likelihood
迟早会是一个小数点后 3 位以上的数字。当发生这种情况时,1000 * success_likelihood
将类似于 399.999999
,因此 dist[cutoff -1]
将 return undefined
导致您的代码停止。使用
let cutoff = Math.round(1000 * success_likelihood)
您的 success_likelihood
从 0.2 开始,每次用户成功时减少 0.05。这意味着如果用户连续答对 4 次,您的 success_likelihood
将降为零,导致 trial_duration
被设置为 undefined
。浮点舍入错误很常见,因此您的 0.399 可能更像是 0.3999999,或者 10 分之 4。
您可以考虑通过乘以 0.95 而不是减去 0.05,每次将当前剩余 success_likelihood
值减少 5%。
我有一个包含 1000 个数据的数组,但由于某些原因,我只能访问其中 39.9% 的数据。
这个问题出现在我使用名为 jsPsych 的 JavaScript 库编码的反应时间游戏中。在游戏中,用户必须在图像从屏幕上消失之前单击一个按钮。游戏被操纵,以便用户在试验中保持 20% 的成功率。
我使用前高斯数据完成了这个装配。具体来说,我有一个包含 1000 个非高斯数据的数组,在每次试验开始时,我从这些数据的底部 20% 中选择一个数字来表示图像将在用户屏幕上持续多长时间。结果是用户只有 20% 的机会足够快地响应图像。此过程的目标是强制用户在试验中获得 20% 的成功率。
如果用户的持续成功率恰好大于 20%,我将每次试验成功的可能性降低 5%,直到成功率为 0.2。同样,如果用户的持续成功率低于20%,我将尝试成功的可能性提高5%,直到成功率为0.2。
问题是我无法将成功可能性提高到 0.399 以上。它应该能够一直上升到 1.0,在这种情况下,我将从我所有的前高斯数据中采样。但是,如果我允许我的游戏 运行 而不触摸按钮,则成功可能性会以 0.5 的增量增加——这是应该的——直到达到 0.399。然后,它停止增加。
我不知道为什么会这样,或者为什么成功的可能性在应该以 0.5 的增量增加时甚至可以达到 0.399。
您可以在下面查看我的代码。 请注意,您需要检查我登录到控制台的数据,才能清楚地了解我遇到的问题。
// this is just some supporting code
const jsPsych = initJsPsych();
const game = {};
// the ex-Gaussian data, sorted in ascending order
const dist = [];
for (let i = 0; i < 1000; i++) {
dist.push(jsPsych.randomization.sampleExGaussian(180, 20, 1, positive = true))
}
dist.sort(function(a, b) {
return a - b
})
console.log("Array of ex-Gaussian data:" + dist)
// initial success likelihood = 20%
let success_likelihood = 0.2;
game.timeline = [{
timeline: [{
// wait for image to appear
type: jsPsychHtmlButtonResponse,
stimulus: "<div style='visibility:hidden;'>image</div>",
choices: ["Click me!"],
trial_duration: 1000,
response_ends_trial: false,
// place feedback element here, albeit hidden, to keep page formatting consistent
prompt: "<div>Click the button as soon as the image appears.</div><div style='visibility:hidden; background-color:green; padding:20px;'>Success</div>",
},
{
// show image
type: jsPsychHtmlButtonResponse,
stimulus: "<div>image</div>",
choices: ["Click me!"],
trial_duration: function() {
// player must click button within trial duration to succeed
// player has x% chance of success on each trial
// sample trial duration from lower x% of rt distribution
let cutoff = 1000 * success_likelihood;
// subtract cutoff - 1 because array index starts at 0
return dist[cutoff - 1];
},
data: {
type: "game"
},
prompt: "<div>Click the button as soon as the image appears.</div><div style='visibility:hidden; background-color:green; padding:20px;'>Success</div>",
},
{
// feedback
type: jsPsychHtmlButtonResponse,
stimulus: "<div style='visibility:hidden;'>image</div>",
choices: ["Click me!"],
trial_duration: 2000,
response_ends_trial: false,
prompt: function() {
var last_trial = jsPsych.data.getLastTrialData();
var rt = last_trial.trials[0].rt;
// if rt === null, player failed to press button within span of trial
if (rt != null) {
return "<div>Click the button as soon as the image appears.</div><div style='background-color:green; padding:20px;'>Success</div>";
} else {
return "<div>Click the button as soon as the image appears.</div><div style='background-color:red; padding:20px;'>Missed</div>";
}
},
}
],
on_timeline_finish: function() {
// re-evaluate success rate after each trial
let total_trials = jsPsych.data.get().filter({
type: "game"
});
let success_trials = total_trials.select('rt').subset(function(x) {
return x != null;
});
let success_rate = success_trials.count() / total_trials.count();
console.log("Success rate:" + success_rate)
// adjust success likelihood +-5% until it reaches 0.2
if (success_rate > 0.2) {
success_likelihood -= 0.05;
} else if (success_rate < 0.2) {
success_likelihood += 0.05;
}
console.log("Success likelihood:" + success_likelihood)
},
loop_function: function(data) {
// stop game once player attains 12 success trials
let success_trials = jsPsych.data.get().filter({
type: "game"
}).select('rt').subset(function(x) {
return x != null;
}).count();
if (success_trials != 12) {
return true;
} else {
return false;
}
}
}]
// run code
jsPsych.run([game])
<!DOCTYPE html>
<html lang="en-CA">
<head>
<meta charset="UTF-8" />
<title>Demo</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<script src="https://unpkg.com/jspsych@7.1.2/dist/index.browser.min.js"></script>
<link href="https://unpkg.com/jspsych@7.1.2/css/jspsych.css" rel="stylesheet" />
<script src="https://unpkg.com/@jspsych/plugin-html-button-response@1.1.0/dist/index.browser.min.js"></script>
<script src="https://unpkg.com/@jspsych/plugin-html-keyboard-response@1.1.0/dist/index.browser.min.js"></script>
</head>
<body></body>
</html>
有谁知道为什么我的阵列访问受到限制?
success_likelihood根据这个只会变小,不会变大?
if (success_rate > 0.2) {
success_likelihood -= 0.05;
} else if (success_rate < 0.2) {
success_likelihood;
}
首先,您根本没有增加 success_likelyhood
,但这可能只是一个错字。
你的第二个问题是这段代码
let cutoff = 1000 * success_likelihood;
return dist[cutoff - 1];
由于浮点运算的工作原理,您的 success_likelihood
迟早会是一个小数点后 3 位以上的数字。当发生这种情况时,1000 * success_likelihood
将类似于 399.999999
,因此 dist[cutoff -1]
将 return undefined
导致您的代码停止。使用
let cutoff = Math.round(1000 * success_likelihood)
您的 success_likelihood
从 0.2 开始,每次用户成功时减少 0.05。这意味着如果用户连续答对 4 次,您的 success_likelihood
将降为零,导致 trial_duration
被设置为 undefined
。浮点舍入错误很常见,因此您的 0.399 可能更像是 0.3999999,或者 10 分之 4。
您可以考虑通过乘以 0.95 而不是减去 0.05,每次将当前剩余 success_likelihood
值减少 5%。