eprime提示范式如何设计才能避免实验数据偏差与被试反应定势

引言:理解实验设计中的关键挑战
在心理学和认知神经科学实验中,E-Prime作为一款广泛使用的实验设计软件,其提示范式(Cueing Paradigm)设计直接关系到实验数据的质量和可靠性。实验数据偏差和被试反应定势是两个最常见的实验设计问题,它们会严重影响实验结果的科学性和有效性。本文将详细探讨如何在E-Prime中设计提示范式,以有效避免这些潜在问题。
实验数据偏差通常源于实验设计的系统性缺陷,如刺激呈现的不均衡、时间参数的不合理设置等。而被试反应定势则是指被试在实验过程中形成的固定反应模式,这种模式可能掩盖真实的认知过程。在E-Prime环境中,我们可以通过精确控制实验流程、合理设置参数和采用适当的随机化策略来解决这些问题。
一、E-Prime提示范式的基本结构与潜在问题
1.1 提示范式的核心组件
一个标准的E-Prime提示范式通常包含以下关键组件:
提示刺激(Cue)
:用于引导被试注意或预期的刺激
目标刺激(Target)
:被试需要做出反应的关键刺激
反应记录
:准确记录被试反应的机制
填充试次(Filler trials)
:用于平衡实验设计的额外试次
1.2 常见的数据偏差来源
在E-Prime提示范式中,数据偏差主要来自以下几个方面:
刺激呈现偏差
:提示刺激和目标刺激的呈现位置、时间间隔不一致
反应模式偏差
:反应按键设置过于简单,导致被试形成固定反应模式
时间参数偏差
:刺激呈现时间过短或过长,影响被试的自然反应
实验顺序效应
:试次顺序未充分随机化,导致学习效应
二、避免实验数据偏差的E-Prime设计策略
2.1 刺激呈现的精确控制
在E-Prime中,精确控制刺激呈现是避免数据偏差的基础。以下是具体实现方法:
2.1.1 使用List对象进行试次管理
E-Prime的List对象是管理试次的核心工具。通过合理设置List的属性,可以确保刺激呈现的均衡性:
‘ 在E-Prime中,List对象的属性设置示例
‘ 1. 设置随机化:将List的Randomize属性设为True
‘ 2. 设置循环次数:确保每个条件都有足够的试次
‘ 3. 设置不放回抽样:确保每个刺激只出现一次

‘ 示例代码(E-Prime Script):
Set cList = New List
cList.Randomize = True ‘ 启用随机化
cList.Balance = True ‘ 启用平衡
cList.Cycles = 1 ‘ 设置循环次数
2.1.2 时间参数的精确设置
时间参数的设置对数据质量至关重要。以下是关键参数:
‘ 提示刺激呈现时间:通常设置为500-1000ms
‘ 目标刺激呈现时间:根据实验任务设置,通常为2000ms或直到反应
‘ 刺激间隔(ISI):使用随机化避免预期

‘ 在E-Prime中设置时间参数的示例:
‘ 提示刺激(Cue)的Duration属性:500ms
‘ 目标刺激(Target)的Duration属性:0(表示持续到反应)
‘ 刺激间隔(ISI)的Duration属性:使用Random函数生成
‘ 例如:Random(500, 1000) 生成500-1000ms的随机间隔
2.2 反应记录的优化设计
2.2.1 反应键的平衡设置
避免被试形成固定反应模式的关键是平衡反应键:
‘ 反应键平衡策略:
‘ 1. 左右手平衡:将不同条件的反应分配到左右手
‘ 2. 反应键随机化:在不同试次中交换反应键含义
‘ 3. 使用填充试次:引入不需要反应的试次

‘ E-Prime实现示例:
‘ 在List中创建两个子条件:
‘ 条件A:左键反应(”d”键)
‘ 条件B:右键反应(”k”键)
‘ 通过Randomize属性确保两种条件随机出现
2.2.2 反应时间窗口的合理设置
‘ 反应时间窗口设置原则:
‘ 1. 足够长:通常至少1500-2000ms,避免压迫感
‘ 2. 足够短:避免被试过度思考
‘ 3. 明确反馈:提供反应是否正确的反馈(如果实验设计需要)

‘ 在E-Prime中设置反应时间窗口:
‘ Response对象的属性:
‘ – Duration: 2000 (反应时间窗口)
‘ – ErrorFeedback: True/False (是否提供错误反馈)
2.3 随机化与平衡策略
2.3.1 完全随机化 vs. 部分随机化
在E-Prime中,随机化策略的选择直接影响数据质量:
‘ 完全随机化:适用于大多数情况
‘ 部分随机化:适用于需要避免连续相同条件出现的情况

‘ E-Prime中实现部分随机化的代码示例:
‘ 使用Script对象编写自定义随机化逻辑
Sub OnExperimentStart()
‘ 创建随机化序列
Dim seq(1 To 100) As Integer
For i = 1 To 100
seq(i) = i Mod 2 ‘ 0和1交替
Next

‘ 打乱序列,但避免连续相同
Randomize
For i = 1 To 99
If seq(i) = seq(i+1) Then
‘ 交换相邻元素
temp = seq(i)
seq(i) = seq(i+1)
seq(i+1) = temp
End If
Next
End Sub
2.3.2 填充试次的使用
填充试次是避免被试发现实验规律的重要手段:
‘ 填充试次设计原则:
‘ 1. 数量:通常占总试次的20-30%
‘ 2. 类型:与实验试次相似但不相同
‘ 3. 分布:随机分布在实验中

‘ 在E-Prime中实现填充试次:
‘ 在List中添加额外的行,标记为Filler
‘ 使用Script控制填充试次的呈现逻辑
三、避免被试反应定势的E-Prime设计策略
3.1 反应模式多样化设计
3.1.1 多反应模式切换
‘ 设计多种反应模式,定期切换:
‘ 模式1:按键反应(左/右)
‘ 模式2:口头报告(记录反应时间)
‘ 梦模式3:计数任务(在刺激呈现期间计数特定事件)

‘ E-Prime实现示例:
‘ 在List中设置不同的Response对象
‘ 使用Script在不同block之间切换反应模式

‘ 示例代码:
Sub SwitchResponseMode(blockNum As Integer)
If blockNum Mod 2 = 0 Then
‘ 偶数block使用模式1
Set resp = DisplayObjects(“Response1”)
resp.Enabled = True
DisplayObjects(“Response2”).Enabled = False
Else
‘ 奇数block使用模式2
Set resp = DisplayObjects(“Response2”)
resp.Enabled =1
DisplayObjects(“Response1”).Enabled = False
End If
End Sub
3.1.2 引入双重任务
‘ 双重任务设计:
‘ 主任务:提示范式反应
‘ 次任务:记忆任务或计数任务

‘ E-Prime实现:
‘ 在刺激呈现期间插入次任务
‘ 例如:在提示刺激呈现时,要求被试记忆一个数字
‘ 在试次结束后要求回忆该数字

‘ 代码示例:
‘ 在Cue刺激的OnsetScript中:
Sub OnCueOnset()
‘ 生成随机数字
memoryNumber = Int(10 * Rnd) + 1
‘ 存储到UserVariables
UserVariables(“MemoryNumber”) = memoryNumber
End Sub

‘ 在试次结束后的Response中:
Sub OnResponse()
‘ 要求被试回忆数字
‘ 记录回忆准确性和反应时间
End Sub
3.2 注意力监控与数据质量控制
3.2.1 眼动监控(如果条件允许)
‘ 虽然E-Prime本身不直接支持眼动仪,
‘ 但可以通过脚本与眼动仪通信

‘ 示例:使用E-Prime的SerialPort对象与眼动仪同步
Sub SetupEyeTracking()
Set sp = New SerialPort
sp.Port = 1
sp.BaudRate = 9600
sp.Open
‘ 发送开始标记
sp.Write “START” & vbCrLf
End Sub

‘ 在每个试次开始时发送标记
Sub OnTrialStart()
sp.Write “TRIAL_” & UserVariables(“TrialType”) & vbCrLf
End Sub
3.2.2 反应一致性检查
‘ 实时监控被试反应模式
‘ 如果发现被试连续多次以固定模式反应,插入提醒

‘ E-Prime实现:
‘ 在每个block结束后检查反应模式
Sub CheckResponsePattern()
Dim reactionTimes(1 To 10) As Double
‘ 获取最近10次反应时间
For i = 1 To 10
reactionTimes(i) = UserVariables(“RT_” & (UserVariables(“CurrentTrial”) – i))
Next

‘ 计算变异系数
meanRT = Average(reactionTimes)
stdRT = StDev(reactionTimes)
cv = stdRT / meanRT

‘ 如果变异系数过小(<0.1),提示被试注意 If cv < 0.1 Then ShowMessage "请保持自然反应,避免固定模式" End If End Sub 3.3 实验流程的动态调整 3.3.1 自适应实验设计 ' 根据被试表现动态调整难度 ' 如果被试准确率过高,增加任务难度 ' E-Prime实现: Sub AdjustDifficulty() ' 计算最近20个试次的准确率 accuracy = CalculateAccuracy(20) If accuracy > 0.9 Then
‘ 降低刺激清晰度或缩短呈现时间
UserVariables(“StimulusDuration”) = UserVariables(“StimulusDuration”) * 0.9
ShowMessage “任务难度已调整”
ElseIf accuracy < 0.7 Then ' 增加刺激清晰度或延长呈现时间 UserVariables("StimulusDuration") = UserVariables("StimulusDuration") * 1.1 End If End Sub 3.3.2 插入注意力检查试次 ' 定期插入注意力检查试次 ' 这些试次有明确的正确答案,用于检测被试是否认真 ' E-Prime实现: ' 在List中每隔N个试次插入一个注意力检查试次 ' 使用Script控制插入逻辑 ' 示例代码: Sub InsertAttentionCheck() ' 每15个试次插入一个检查 If UserVariables("CurrentTrial") Mod 15 = 0 Then ' 显示注意力检查刺激 DisplayObjects("AttentionCheckStim").Visible = True ' 要求特定反应(如按空格键) DisplayObjects("AttentionCheckResp").Enabled = True ' 记录反应 If UserVariables("AttentionCheckRT") > 3000 Then
‘ 反应过慢,提示被试
ShowMessage “请集中注意力”
End实验
End If
End Sub
四、E-Prime高级技术实现细节
4.1 使用E-Prime的Script对象进行精细控制
Script对象是E-Prime中实现复杂逻辑的核心工具:
‘ Script对象的使用示例
‘ 在E-Prime的Script编辑器中编写

‘ 全局变量声明
Dim trialSequence() As Integer
Dim currentBlock As Integer
Dim attentionCheckCounter As Integer

Sub OnExperimentStart()
‘ 初始化实验参数
Randomize ‘ 初始化随机数生成器
currentBlock = 1
attentionCheckCounter = 0

‘ 创建平衡的试次序列
CreateBalancedSequence
End Sub

Sub CreateBalancedSequence()
‘ 创建包含所有条件的平衡序列
Dim conditions(1 To 4) As Integer
conditions(1) = 1 ‘ 条件1:提示有效
conditions(2) = 2 ‘ 条件2:提示无效
conditions(3) = 3 ‘ 条件3:中性提示
conditions(4) = 4 ‘ 条件4:填充试次

‘ 使用随机排列算法
ReDim trialSequence(1 To 80) ‘ 80个试次
Dim i As Integer
For i = 1 To 80
trialSequence(i) = conditions(Int(4 * Rnd) + 1)
Next

‘ 确保没有连续3个相同条件
For i = 1 To 78
If trialSequence(i) = trialSequence(i+1) And _
trialSequence(i+1) = trialSequence(i+2) Then
‘ 交换第i+2个元素
temp = trialSequence(i+2)
trialSequence(i+2) = trialSequence(i+3)
trialSequence(i+3) = temp
End If
Next
End Sub

Sub OnTrialStart()
‘ 根据序列设置当前试次条件
UserVariables(“Condition”) = trialSequence(UserVariables(“CurrentTrial”))

‘ 更新注意力检查计数器
attentionCheckCounter = attentionCheckCounter + 1
If attentionCheckCounter >= 15 Then
InsertAttentionCheck
attentionCheckCounter = 0
End If
End Sub
4.2 使用E-Prime的Inline Script进行实时计算
‘ Inline Script的使用:实时计算和调整

‘ 在E-Prime的Inline Script中:
‘ 计算被试的平均反应时间
Function CalculateAverageRT(lastN As Integer) As Double
Dim sum As Double
Dim count As Integer
sum = 0
count = 0

For i = UserVariables(“CurrentTrial”) – lastN + 1 To UserVariables(“CurrentTrial”)
If UserVariables(“RT_” & i) > 0 Then
sum = sum + UserVariables(“RT_” & i)
count = count + 1
End If
Next

If count > 0 Then
CalculateAverageRT = sum / count
Else
CalculateAverageRT = 0
End If
End Function

‘ 使用该函数调整刺激呈现时间
Sub AdjustStimulusDuration()
avgRT = CalculateAverageRT(20)
If avgRT > 800 Then
‘ 反应过慢,缩短刺激时间
UserVariables(“CurrentDuration”) = 500
Else
UserVariables(“CurrentDuration”) = 800
End If
End Sub
4.3 数据输出与质量控制
‘ 在实验结束后进行数据质量检查
Sub OnExperimentEnd()
‘ 计算关键指标
totalTrials = UserVariables(“TotalTrials”)
validTrials = 0
sumRT = 0
sumAcc = 0

For i = 1 To totalTrials
If UserVariables(“Valid_” & i) = 1 Then
validTrials = validTrials + 1
sumRT = sumRT + UserVariables(“RT_” & i)
sumAcc = sumAcc + UserVariables(“Accuracy_” & i)
End If
Next

‘ 计算平均值
avgRT = sumRT / validTrials
avgAcc = sumAcc / validTrials

‘ 输出质量报告
Open “DataQualityReport.txt” For Output As #1
Print #1, “总试次数: ” & totalTrials
Print #1, “有效试次数: ” & validTrials
Print #1, “平均反应时间: ” & avgRT & “ms”
Print #1, “平均准确率: ” & avgAcc * 100 & “%”
Print #1, “数据质量: ” & IIf(avgAcc > 0.8 And avgRT > 200, “良好”, “需要检查”)
Close #1
End Sub
五、实际案例:完整的E-Prime提示范式设计
5.1 实验设计概述
假设我们要设计一个视觉空间提示范式,研究注意提示对目标检测的影响:
实验条件
:有效提示(80%)、无效提示(10%)、中性提示(10%)
试次总数
:160个试次(包括16个填充试次)
反应方式
:左右手按键平衡
目标
:避免被试形成”预期”反应模式
5.2 E-Prime实现步骤
步骤1:创建实验结构
‘ 实验结构:
‘ 1. 指导语屏幕
‘ 2. 练习block(16试次)
‘ 3. 正式实验block(144试次,分3个block)
‘ 4. 注意力检查(每block插入4次)
‘ 5. 结束屏幕

‘ 在E-Prime中创建以下对象:
‘ – SessionProc: 实验主流程
‘ – Instr: 指导语
‘ – PracticeBlock: 练习block
‘ – MainBlock1, MainBlock2, MainBlock3: 正式实验block
‘ – EndScreen: 结束屏幕
步骤2:设计试次结构
‘ 每个试次包含:
‘ 1. Fixation: 注视点(500ms)
‘ 2. Cue: 提示刺激(500ms)
‘ 3. ISI: 随机间隔(500-1000ms)
‘ 4. Target: 目标刺激(持续到反应或2000ms)
‘ 5. Feedback: 反馈(500ms,仅练习block)

‘ 在E-Prime中设置:
‘ – Fixation: Text对象,显示”+”
‘ – Cue: Image对象,显示提示(左箭头、右箭头、双箭头)
‘ – ISI: Blank对象,Duration = Random(500, 1000)
‘ – Target: Image对象,显示目标(左或右位置)
‘ – Feedback: Text对象,显示”正确”或”错误”
步骤3:编写Script实现复杂逻辑
‘ 在SessionProc的Script中:

‘ 全局变量
Dim blockTrialCount As Integer
Dim currentBlock As Integer
Dim attentionCheckInterval As Integer

Sub OnExperimentStart()
Randomize
currentBlock = 1
blockTrialCount = 0
attentionCheckInterval = 15 ‘ 每15个试次检查一次

‘ 初始化UserVariables
UserVariables.Add “CurrentTrial”, 0
UserVariables.Add “Condition”, 0
UserVariables.Add “TargetPosition”, 0
UserVariables.Add “ReactionTime”, 0
UserVariables.Add “Accuracy”, 0
UserVariables.Add “ValidTrial”, 1
End Sub

Sub OnBlockStart()
blockTrialCount = 0
‘ 每个block开始时平衡反应键
If currentBlock Mod 2 = 0 Then
UserVariables(“LeftKey”) = “d”
UserVariables(“RightKey”) = “k”
Else
UserVariables(“LeftKey”) = “k”
UserVariables(“RightKey”) = “d”
End If
End Sub

Sub OnTrialStart()
‘ 增加试次计数
UserVariables(“CurrentTrial”) = UserVariables(“CurrentTrial”) + 1
blockTrialCount = blockTrialCount + 1

‘ 检查是否需要插入注意力检查
If blockTrialCount Mod attentionCheckInterval = 0 Then
UserVariables(“IsAttentionCheck”) = 1
SetupAttentionCheckTrial
Else
UserVariables(“IsAttentionCheck”) = 0
SetupNormalTrial
End If
End Sub

Sub SetupNormalTrial()
‘ 设置正常试次的条件
Dim rand As Double
rand = Rnd

‘ 根据概率分配条件
If rand < 0.8 Then UserVariables("Condition") = 1 ' 有效提示 ElseIf rand < 0.9 Then UserVariables("Condition") = 2 ' 无效提示 Else UserVariables("Condition") = 3 ' 中性提示 End If ' 设置目标位置(随机) UserVariables("TargetPosition") = IIf(Rnd < 0.5, 1, 2) ' 1=左, 2=右 ' 设置提示类型 If UserVariables("Condition") = 1 Then ' 有效提示:提示方向与目标位置一致 If UserVariables("TargetPosition") = 1 Then UserVariables("CueType") = "LeftArrow" Else UserVariables("CueType") = "RightArrow" End If ElseIf UserVariables("Condition") = 2 Then ' 无效提示:提示方向与目标位置相反 If UserVariables("TargetPosition") = 1 Then UserVariables("CueType") = "RightArrow" Else UserVariables("CueType") = "LeftArrow" End If Else ' 中性提示:双箭头 UserVariables("CueType") = "DoubleArrow" End If ' 设置ISI时间(随机化) UserVariables("ISI_Duration") = Int(500 + 500 * Rnd) ' 500-1000ms ' 设置反应键(平衡) If UserVariables("TargetPosition") = 1 Then UserVariables("CorrectKey") = UserVariables("LeftKey") Else UserVariables("CorrectKey") = UserVariables("RightKey") End If End Sub Sub SetupAttentionCheckTrial() ' 设置注意力检查试次 UserVariables("Condition") = 99 ' 特殊条件码 UserVariables("CueType") = "AttentionCheck" UserVariables("TargetPosition") = 0 ' 无目标 UserVariables("CorrectKey") = "space" ' 必须按空格键 UserVariables("ISI_Duration") = 800 End Sub Sub OnTrialEnd() ' 记录数据 If UserVariables("IsAttentionCheck") = 0 Then ' 正常试次:记录反应时间和准确性 UserVariables("RT_" & UserVariables("CurrentTrial")) = UserVariables("ReactionTime") UserVariables("Accuracy_" & UserVariables("CurrentTrial")) = UserVariables("Accuracy") UserVariables("Valid_" & UserVariables("CurrentTrial")) = 1 Else ' 注意力检查试次:检查反应是否正确 If UserVariables("Accuracy") = 1 Then UserVariables("Valid_" & UserVariables("CurrentTrial")) = 1 Else UserVariables("Valid_" & UserVariables("CurrentTrial")) = 0 ShowMessage "请注意!检测到注意力不集中" End If End If ' 检查是否需要调整难度 If UserVariables("CurrentTrial") Mod 20 = 0 Then AdjustDifficulty End If End Sub Sub OnBlockEnd() ' block结束后计算表现 Dim blockAcc As Double Dim blockRT As Double blockAcc = CalculateBlockAccuracy(currentBlock) blockRT = CalculateBlockRT(currentBlock) ' 显示block反馈 ShowMessage "Block " & currentBlock & " 完成!\n准确率: " & Format(blockAcc * 100, "0.0") & "%\n平均反应时间: " & Format(blockRT, "0") & "ms" ' 增加block计数 currentBlock = currentBlock + 1 ' 如果准确率过低,延长休息时间 If blockAcc < 0.7 Then ShowMessage "准确率较低,请休息更长时间" Wait 5000 ' 额外5秒休息 End If End Sub Sub OnExperimentEnd() ' 实验结束后的数据质量检查 Dim totalValid As Integer Dim totalTrials As Integer totalTrials = UserVariables("CurrentTrial") totalValid = 0 For i = 1 To totalTrials If UserVariables("Valid_" & i) = 1 Then totalValid = totalValid + 1 End If Next ' 生成数据质量报告 Open "DataQuality_" & UserVariables("SubjectID") & ".txt" For Output As #1 Print #1, "被试ID: " & UserVariables("SubjectID") Print #1, "总试次数: " & totalTrials Print #1, "有效试次数: " & totalValid Print #1, "有效率: " & Format(totalValid / totalTrials * 100, "0.0") & "%" If totalValid / totalTrials < 0.9 Then Print #1, "警告:数据有效率低于90%,建议重新实验" Else Print #1, "数据质量良好" End If Close #1 End Sub ' 辅助函数 Function CalculateBlockAccuracy(blockNum As Integer) As Double Dim sum As Integer Dim count As Integer sum = 0 count = 0 For i = 1 To UserVariables("CurrentTrial") If UserVariables("Block_" & i) = blockNum And UserVariables("IsAttentionCheck_" & i) = 0 Then sum = sum + UserVariables("Accuracy_" & i) count = count + 1 End If Next If count > 0 Then
CalculateBlockAccuracy = sum / count
Else
CalculateBlockAccuracy = 0
End If
End Function

Function CalculateBlockRT(blockNum As Integer) As Double
Dim sum As Double
Dim count As Integer
sum = 0
count = 0

For i = 1 To UserVariables(“CurrentTrial”)
If UserVariables(“Block_” & i) = blockNum And UserVariables(“IsAttentionCheck_” & i) = 0 And UserVariables(“Accuracy_” & i) = 1 Then
sum = sum + UserVariables(“RT_” & i)
count = count + 1
End If
Next

If count > 0 Then
CalculateBlockRT = sum / count
Else
CalculateBlockRT = 0
End If
End Function

Function AdjustDifficulty()
‘ 根据最近20个试次的表现调整难度
Dim recentAcc As Double
recentAcc = CalculateBlockAccuracy(UserVariables(“CurrentBlock”))

If recentAcc > 0.9 Then
‘ 减少刺激呈现时间
UserVariables(“TargetDuration”) = Max(100, UserVariables(“TargetDuration”) – 50)
ShowMessage “难度提升:刺激时间缩短”
ElseIf recentAcc < 0.7 Then ' 增加刺激呈现时间 UserVariables("TargetDuration") = Min(2000, UserVariables("TargetDuration") + 100) ShowMessage "难度降低:刺激时间延长" End If End Function 步骤4:设置反应对象 ' 在Target刺激后的Response对象设置: ' Response对象属性: ' - ObjectName: TargetResponse ' - Duration: 2000 (反应时间窗口) ' - ContinueMode: 0 (等待反应) ' - AllowedKeys: 变量设置 ' 在Script中动态设置: ' TargetResponse.AllowedKeys = UserVariables("CorrectKey") ' - ErrorFeedback: False (正式实验不显示,练习可显示) ' - OnsetScript: 记录刺激呈现时间 ' - OffsetScript: 记录反应时间 ' 在Response对象的OnsetScript中: Sub OnTargetResponseOnset() UserVariables("TargetOnsetTime") = Timer End Sub ' 在Response对象的OffsetScript中: Sub OnTargetResponseOffset() ' 记录反应时间 If UserVariables("TargetOnsetTime") > 0 Then
UserVariables(“ReactionTime”) = Timer – UserVariables(“TargetOnsetTime”)
End If

‘ 判断反应是否正确
If UserVariables(“IsAttentionCheck”) = 1 Then
‘ 注意力检查试次
If UserVariables(“ResponseKey”) = “space” Then
UserVariables(“Accuracy”) = 1
Else
UserVariables(“Accuracy”) = 0
End If
Else
‘ 正常试次
If UserVariables(“ResponseKey”) = UserVariables(“CorrectKey”) Then
UserVariables(“Accuracy”) = 1
Else
UserVariables(“Accuracy”) = 0
End If
End If

‘ 记录反应键
UserVariables(“ResponseKey”) = UserVariables(“ResponseKey”)
End Sub
5.3 实验流程控制
‘ 在SessionProc的流程控制:

‘ 1. 指导语屏幕
‘ – 显示实验说明
‘ – 强调准确性和自然反应
‘ – 显示反应键说明(根据block变化)

‘ 2. 练习block(16试次)
‘ – 显示反馈
‘ – 允许重复练习直到掌握
‘ – 设置最小准确率阈值(如>80%)

‘ 3. 正式实验block(3个block)
‘ – 每个block后休息
‘ – 显示当前进度
‘ – 插入注意力检查

‘ 4. 结束屏幕
‘ – 显示整体表现
‘ – 感谢被试
六、数据清理与分析前的质量控制
6.1 数据清理标准
在E-Prime数据导出后,需要进行以下清理:
# Python示例:数据清理脚本
import pandas as pd
import numpy as np

def clean_eprime_data(df):
“””
清理E-Prime数据,去除异常值和无效试次
“””
# 1. 去除反应时间异常值
# 反应时间 < 100ms 或 > 2000ms 视为异常
df = df[(df[‘RT’] >= 100) & (df[‘RT’] <= 2000)] # 2. 去除注意力检查失败的试次 df = df[df['IsAttentionCheck'] == 0] # 3. 去除连续相同反应模式 # 计算反应时间的移动标准差 df['RT_moving_std'] = df['RT'].rolling(window=5).std() # 如果连续5次反应时间标准差过小(<50ms),视为反应定势 df = df[df['RT_moving_std'] >= 50]

# 4. 去除准确率过低的被试
subject_acc = df.groupby(‘SubjectID’)[‘Accuracy’].mean()
valid_subjects = subject_acc[subject_acc > 0.7].index
df = df[df[‘SubjectID’].isin(valid_subjects)]

return df

# 使用示例
df = pd.read_csv(‘experiment_data.csv’)
cleaned_df = clean_eprime_data(df)
cleaned_df.to_csv(‘cleaned_data.csv’, index=False)
6.2 反应定势检测算法
# 检测反应定势的算法

def detect_response_bias(df, window=10, threshold=0.8):
“””
检测被试是否存在反应定势
window: 检测窗口大小
threshold: 定势阈值(如80%相同反应)
“””
results = {}

for subject in df[‘SubjectID’].unique():
subject_data = df[df[‘SubjectID’] == subject]

# 计算每个窗口内的反应模式
reaction_pattern = []
for i in range(len(subject_data) – window + 1):
window_data = subject_data.iloc[i:i+window]
# 统计最常见的反应
mode_reaction = window_data[‘ResponseKey’].mode()[0]
mode_freq = (window_data[‘ResponseKey’] == mode_reaction).mean()
reaction_pattern.append(mode_freq)

# 判断是否存在定势
max_bias = max(reaction_pattern)
has_bias = max_bias > threshold

results[subject] = {
‘max_bias’: max_bias,
‘has_bias’: has_bias,
‘recommendation’: ‘Exclude’ if has_bias else ‘Include’
}

return results

# 使用示例
bias_results = detect_response_bias(cleaned_df)
for subject, result in bias_results.items():
if result[‘has_bias’]:
print(f”被试 {subject} 存在反应定势({result[‘max_bias’]:.1%}),建议排除”)
七、总结与最佳实践建议
7.1 设计检查清单
在完成E-Prime提示范式设计后,使用以下检查清单验证设计:
[ ]
随机化检查
:所有条件是否充分随机化?
[ ]
平衡检查
:反应键、刺激位置是否平衡?
[ ]
填充试次
:是否包含20-30%的填充试次?
[ ]
注意力检查
:是否每10-15个试次插入检查?
[ ]
时间参数
:ISI是否随机化?刺激时间是否合理?
[ ]
反应多样性
:是否避免了固定反应模式?
[ ]
数据记录
:是否记录了所有必要变量?
[ ]
质量控制
:是否包含实时数据质量监控?
1.2 最佳实践总结
充分的随机化
:使用E-Prime的List.Randomize属性,但避免完全随机导致的连续相同条件
动态调整
:根据被试表现实时调整实验参数
多重监控
:结合注意力检查、反应模式分析和数据清理
平衡设计
:在block间平衡反应键和刺激位置
详细记录
:记录所有可能影响结果的变量
预实验测试
:在正式实验前进行小规模预测试,检查设计缺陷
通过以上详细的E-Prime设计策略和实现代码,您可以构建一个高质量的提示范式实验,有效避免实验数据偏差和被试反应定势,从而获得可靠的科学数据。
# eprime提示范式如何设计才能避免实验数据偏差与被试反应定势
引言:理解实验设计中的关键挑战
在心理学和认知神经科学实验中,E-Prime作为一款广泛使用的实验设计软件,其提示范式(Cueing Paradigm)设计直接关系到实验数据的质量和可靠性。实验数据偏差和被试反应定势是两个最常见的实验设计问题,它们会严重影响实验结果的科学性和有效性。本文将详细探讨如何在E-Prime中设计提示范式,以有效避免这些潜在问题。
实验数据偏差通常源于实验设计的系统性缺陷,如刺激呈现的不均衡、时间参数的不合理设置等。而被试反应定势则是指被试在实验过程中形成的固定反应模式,这种模式可能掩盖真实的认知过程。在E-Prime环境中,我们可以通过精确控制实验流程、合理设置参数和采用适当的随机化策略来解决这些问题。
一、E-Prime提示范式的基本结构与潜在问题
1.1 提示范式的核心组件
一个标准的E-Prime提示范式通常包含以下关键组件:
提示刺激(Cue)
:用于引导被试注意或预期的刺激
目标刺激(Target)
:被试需要做出反应的关键刺激
反应记录
:准确记录被试反应的机制
填充试次(Filler trials)
:用于平衡实验设计的额外试次
1.2 常见的数据偏差来源
在E-Prime提示范式中,数据偏差主要来自以下几个方面:
刺激呈现偏差
:提示刺激和目标刺激的呈现位置、时间间隔不一致
反应模式偏差
:反应按键设置过于简单,导致被试形成固定反应模式
时间参数偏差
:刺激呈现时间过短或过长,影响被试的自然反应
实验顺序效应
:试次顺序未充分随机化,导致学习效应
二、避免实验数据偏差的E-Prime设计策略
2.1 刺激呈现的精确控制
在E-Prime中,精确控制刺激呈现是避免数据偏差的基础。以下是具体实现方法:
2.1.1 使用List对象进行试次管理
E-Prime的List对象是管理试次的核心工具。通过合理设置List的属性,可以确保刺激呈现的均衡性:
‘ 在E-Prime中,List对象的属性设置示例
‘ 1. 设置随机化:将List的Randomize属性设为True
‘ 2. 设置循环次数:确保每个条件都有足够的试次
‘ 3. 设置不放回抽样:确保每个刺激只出现一次

‘ 示例代码(E-Prime Script):
Set cList = New List
cList.Randomize = True ‘ 启用随机化
cList.Balance = True ‘ 启用平衡
cList.Cycles = 1 ‘ 设置循环次数
2.1.2 时间参数的精确设置
时间参数的设置对数据质量至关重要。以下是关键参数:
‘ 提示刺激呈现时间:通常设置为500-1000ms
‘ 目标刺激呈现时间:根据实验任务设置,通常为2000ms或直到反应
‘ 刺激间隔(ISI):使用随机化避免预期

‘ 在E-Prime中设置时间参数的示例:
‘ 提示刺激(Cue)的Duration属性:500ms
‘ 目标刺激(Target)的Duration属性:0(表示持续到反应)
‘ 刺激间隔(ISI)的Duration属性:使用Random函数生成
‘ 例如:Random(500, 1000) 生成500-1000ms的随机间隔
2.2 反应记录的优化设计
2.2.1 反应键的平衡设置
避免被试形成固定反应模式的关键是平衡反应键:
‘ 反应键平衡策略:
‘ 1. 左右手平衡:将不同条件的反应分配到左右手
‘ 2. 反应键随机化:在不同试次中交换反应键含义
‘ 3. 使用填充试次:引入不需要反应的试次

‘ E-Prime实现示例:
‘ 在List中创建两个子条件:
‘ 条件A:左键反应(”d”键)
‘ 条件B:右键反应(”k”键)
‘ 通过Randomize属性确保两种条件随机出现
2.2.2 反应时间窗口的合理设置
‘ 反应时间窗口设置原则:
‘ 1. 足够长:通常至少1500-2000ms,避免压迫感
‘ 2. 足够短:避免被试过度思考
‘ 3. 明确反馈:提供反应是否正确的反馈(如果实验设计需要)

‘ 在E-Prime中设置反应时间窗口:
‘ Response对象的属性:
‘ – Duration: 2000 (反应时间窗口)
‘ – ErrorFeedback: True/False (是否提供错误反馈)
2.3 随机化与平衡策略
2.3.1 完全随机化 vs. 部分随机化
在E-Prime中,随机化策略的选择直接影响数据质量:
‘ 完全随机化:适用于大多数情况
‘ 部分随机化:适用于需要避免连续相同条件出现的情况

‘ E-Prime中实现部分随机化的代码示例:
‘ 使用Script对象编写自定义随机化逻辑
Sub OnExperimentStart()
‘ 创建随机化序列
Dim seq(1 To 100) As Integer
For i = 1 To 100
seq(i) = i Mod 2 ‘ 0和1交替
Next

‘ 打乱序列,但避免连续相同
Randomize
For i = 1 To 99
If seq(i) = seq(i+1) Then
‘ 交换相邻元素
temp = seq(i)
seq(i) = seq(i+1)
seq(i+1) = temp
End If
Next
End Sub
2.3.2 填充试次的使用
填充试次是避免被试发现实验规律的重要手段:
‘ 填充试次设计原则:
‘ 1. 数量:通常占总试次的20-30%
‘ 2. 类型:与实验试次相似但不相同
‘ 3. 分布:随机分布在实验中

‘ 在E-Prime中实现填充试次:
‘ 在List中添加额外的行,标记为Filler
‘ 使用Script控制填充试次的呈现逻辑
三、避免被试反应定势的E-Prime设计策略
3.1 反应模式多样化设计
3.1.1 多反应模式切换
‘ 设计多种反应模式,定期切换:
‘ 模式1:按键反应(左/右)
‘ 模式2:口头报告(记录反应时间)
‘ 梦模式3:计数任务(在刺激呈现期间计数特定事件)

‘ E-Prime实现示例:
‘ 在List中设置不同的Response对象
‘ 使用Script在不同block之间切换反应模式

‘ 示例代码:
Sub SwitchResponseMode(blockNum As Integer)
If blockNum Mod 2 = 0 Then
‘ 偶数block使用模式1
Set resp = DisplayObjects(“Response1”)
resp.Enabled = True
DisplayObjects(“Response2”).Enabled = False
Else
‘ 奇数block使用模式2
Set resp = DisplayObjects(“Response2”)
resp.Enabled =1
DisplayObjects(“Response1”).Enabled = False
End If
End Sub
3.1.2 引入双重任务
‘ 双重任务设计:
‘ 主任务:提示范式反应
‘ 次任务:记忆任务或计数任务

‘ E-Prime实现:
‘ 在刺激呈现期间插入次任务
‘ 例如:在提示刺激呈现时,要求被试记忆一个数字
‘ 在试次结束后要求回忆该数字

‘ 代码示例:
‘ 在Cue刺激的OnsetScript中:
Sub OnCueOnset()
‘ 生成随机数字
memoryNumber = Int(10 * Rnd) + 1
‘ 存储到UserVariables
UserVariables(“MemoryNumber”) = memoryNumber
End Sub

‘ 在试次结束后的Response中:
Sub OnResponse()
‘ 要求被试回忆数字
‘ 记录回忆准确性和反应时间
End Sub
3.2 注意力监控与数据质量控制
3.2.1 眼动监控(如果条件允许)
‘ 虽然E-Prime本身不直接支持眼动仪,
‘ 但可以通过脚本与眼动仪通信

‘ 示例:使用E-Prime的SerialPort对象与眼动仪同步
Sub SetupEyeTracking()
Set sp = New SerialPort
sp.Port = 1
sp.BaudRate = 9600
sp.Open
‘ 发送开始标记
sp.Write “START” & vbCrLf
End Sub

‘ 在每个试次开始时发送标记
Sub OnTrialStart()
sp.Write “TRIAL_” & UserVariables(“TrialType”) & vbCrLf
End Sub
3.2.2 反应一致性检查
‘ 实时监控被试反应模式
‘ 如果发现被试连续多次以固定模式反应,插入提醒

‘ E-Prime实现:
‘ 在每个block结束后检查反应模式
Sub CheckResponsePattern()
Dim reactionTimes(1 To 10) As Double
‘ 获取最近10次反应时间
For i = 1 To 10
reactionTimes(i) = UserVariables(“RT_” & (UserVariables(“CurrentTrial”) – i))
Next

‘ 计算变异系数
meanRT = Average(reactionTimes)
stdRT = StDev(reactionTimes)
cv = stdRT / meanRT

‘ 如果变异系数过小(<0.1),提示被试注意 If cv < 0.1 Then ShowMessage "请保持自然反应,避免固定模式" End If End Sub 3.3 实验流程的动态调整 3.3.1 自适应实验设计 ' 根据被试表现动态调整难度 ' 如果被试准确率过高,增加任务难度 ' E-Prime实现: Sub AdjustDifficulty() ' 计算最近20个试次的准确率 accuracy = CalculateAccuracy(20) If accuracy > 0.9 Then
‘ 降低刺激清晰度或缩短呈现时间
UserVariables(“StimulusDuration”) = UserVariables(“StimulusDuration”) * 0.9
ShowMessage “任务难度已调整”
ElseIf accuracy < 0.7 Then ' 增加刺激清晰度或延长呈现时间 UserVariables("StimulusDuration") = UserVariables("StimulusDuration") * 1.1 End If End Sub 3.3.2 插入注意力检查试次 ' 定期插入注意力检查试次 ' 这些试次有明确的正确答案,用于检测被试是否认真 ' E-Prime实现: ' 在List中每隔N个试次插入一个注意力检查试次 ' 使用Script控制插入逻辑 ' 示例代码: Sub InsertAttentionCheck() ' 每15个试次插入一个检查 If UserVariables("CurrentTrial") Mod 15 = 0 Then ' 显示注意力检查刺激 DisplayObjects("AttentionCheckStim").Visible = True ' 要求特定反应(如按空格键) DisplayObjects("AttentionCheckResp").Enabled = True ' 记录反应 If UserVariables("AttentionCheckRT") > 3000 Then
‘ 反应过慢,提示被试
ShowMessage “请集中注意力”
End实验
End If
End Sub
四、E-Prime高级技术实现细节
4.1 使用E-Prime的Script对象进行精细控制
Script对象是E-Prime中实现复杂逻辑的核心工具:
‘ Script对象的使用示例
‘ 在E-Prime的Script编辑器中编写

‘ 全局变量声明
Dim trialSequence() As Integer
Dim currentBlock As Integer
Dim attentionCheckCounter As Integer

Sub OnExperimentStart()
‘ 初始化实验参数
Randomize ‘ 初始化随机数生成器
currentBlock = 1
attentionCheckCounter = 0

‘ 创建平衡的试次序列
CreateBalancedSequence
End Sub

Sub CreateBalancedSequence()
‘ 创建包含所有条件的平衡序列
Dim conditions(1 To 4) As Integer
conditions(1) = 1 ‘ 条件1:提示有效
conditions(2) = 2 ‘ 条件2:提示无效
conditions(3) = 3 ‘ 条件3:中性提示
conditions(4) = 4 ‘ 条件4:填充试次

‘ 使用随机排列算法
ReDim trialSequence(1 To 80) ‘ 80个试次
Dim i As Integer
For i = 1 To 80
trialSequence(i) = conditions(Int(4 * Rnd) + 1)
Next

‘ 确保没有连续3个相同条件
For i = 1 To 78
If trialSequence(i) = trialSequence(i+1) And _
trialSequence(i+1) = trialSequence(i+2) Then
‘ 交换第i+2个元素
temp = trialSequence(i+2)
trialSequence(i+2) = trialSequence(i+3)
trialSequence(i+3) = temp
End If
Next
End Sub

Sub OnTrialStart()
‘ 根据序列设置当前试次条件
UserVariables(“Condition”) = trialSequence(UserVariables(“CurrentTrial”))

‘ 更新注意力检查计数器
attentionCheckCounter = attentionCheckCounter + 1
If attentionCheckCounter >= 15 Then
InsertAttentionCheck
attentionCheckCounter = 0
End If
End Sub
4.2 使用E-Prime的Inline Script进行实时计算
‘ Inline Script的使用:实时计算和调整

‘ 在E-Prime的Inline Script中:
‘ 计算被试的平均反应时间
Function CalculateAverageRT(lastN As Integer) As Double
Dim sum As Double
Dim count As Integer
sum = 0
count = 0

For i = UserVariables(“CurrentTrial”) – lastN + 1 To UserVariables(“CurrentTrial”)
If UserVariables(“RT_” & i) > 0 Then
sum = sum + UserVariables(“RT_” & i)
count = count + 1
End If
Next

If count > 0 Then
CalculateAverageRT = sum / count
Else
CalculateAverageRT = 0
End If
End Function

‘ 使用该函数调整刺激呈现时间
Sub AdjustStimulusDuration()
avgRT = CalculateAverageRT(20)
If avgRT > 800 Then
‘ 反应过慢,缩短刺激时间
UserVariables(“CurrentDuration”) = 500
Else
UserVariables(“CurrentDuration”) = 800
End If
End Sub
4.3 数据输出与质量控制
‘ 在实验结束后进行数据质量检查
Sub OnExperimentEnd()
‘ 计算关键指标
totalTrials = UserVariables(“TotalTrials”)
validTrials = 0
sumRT = 0
sumAcc = 0

For i = 1 To totalTrials
If UserVariables(“Valid_” & i) = 1 Then
validTrials = validTrials + 1
sumRT = sumRT + UserVariables(“RT_” & i)
sumAcc = sumAcc + UserVariables(“Accuracy_” & i)
End If
Next

‘ 计算平均值
avgRT = sumRT / validTrials
avgAcc = sumAcc / validTrials

‘ 输出质量报告
Open “DataQualityReport.txt” For Output As #1
Print #1, “总试次数: ” & totalTrials
Print #1, “有效试次数: ” & validTrials
Print #1, “平均反应时间: ” & avgRT & “ms”
Print #1, “平均准确率: ” & avgAcc * 100 & “%”
Print #1, “数据质量: ” & IIf(avgAcc > 0.8 And avgRT > 200, “良好”, “需要检查”)
Close #1
End Sub
五、实际案例:完整的E-Prime提示范式设计
5.1 实验设计概述
假设我们要设计一个视觉空间提示范式,研究注意提示对目标检测的影响:
实验条件
:有效提示(80%)、无效提示(10%)、中性提示(10%)
试次总数
:160个试次(包括16个填充试次)
反应方式
:左右手按键平衡
目标
:避免被试形成”预期”反应模式
5.2 E-Prime实现步骤
步骤1:创建实验结构
‘ 实验结构:
‘ 1. 指导语屏幕
‘ 2. 练习block(16试次)
‘ 3. 正式实验block(144试次,分3个block)
‘ 4. 注意力检查(每block插入4次)
‘ 5. 结束屏幕

‘ 在E-Prime中创建以下对象:
‘ – SessionProc: 实验主流程
‘ – Instr: 指导语
‘ – PracticeBlock: 练习block
‘ – MainBlock1, MainBlock2, MainBlock3: 正式实验block
‘ – EndScreen: 结束屏幕
步骤2:设计试次结构
‘ 每个试次包含:
‘ 1. Fixation: 注视点(500ms)
‘ 2. Cue: 提示刺激(500ms)
‘ 3. ISI: 随机间隔(500-1000ms)
‘ 4. Target: 目标刺激(持续到反应或2000ms)
‘ 5. Feedback: 反馈(500ms,仅练习block)

‘ 在E-Prime中设置:
‘ – Fixation: Text对象,显示”+”
‘ – Cue: Image对象,显示提示(左箭头、右箭头、双箭头)
‘ – ISI: Blank对象,Duration = Random(500, 1000)
‘ – Target: Image对象,显示目标(左或右位置)
‘ – Feedback: Text对象,显示”正确”或”错误”
步骤3:编写Script实现复杂逻辑
‘ 在SessionProc的Script中:

‘ 全局变量
Dim blockTrialCount As Integer
Dim currentBlock As Integer
Dim attentionCheckInterval As Integer

Sub OnExperimentStart()
Randomize
currentBlock = 1
blockTrialCount = 0
attentionCheckInterval = 15 ‘ 每15个试次检查一次

‘ 初始化UserVariables
UserVariables.Add “CurrentTrial”, 0
UserVariables.Add “Condition”, 0
UserVariables.Add “TargetPosition”, 0
UserVariables.Add “ReactionTime”, 0
UserVariables.Add “Accuracy”, 0
UserVariables.Add “ValidTrial”, 1
End Sub

Sub OnBlockStart()
blockTrialCount = 0
‘ 每个block开始时平衡反应键
If currentBlock Mod 2 = 0 Then
UserVariables(“LeftKey”) = “d”
UserVariables(“RightKey”) = “k”
Else
UserVariables(“LeftKey”) = “k”
UserVariables(“RightKey”) = “d”
End If
End Sub

Sub OnTrialStart()
‘ 增加试次计数
UserVariables(“CurrentTrial”) = UserVariables(“CurrentTrial”) + 1
blockTrialCount = blockTrialCount + 1

‘ 检查是否需要插入注意力检查
If blockTrialCount Mod attentionCheckInterval = 0 Then
UserVariables(“IsAttentionCheck”) = 1
SetupAttentionCheckTrial
Else
UserVariables(“IsAttentionCheck”) = 0
SetupNormalTrial
End If
End Sub

Sub SetupNormalTrial()
‘ 设置正常试次的条件
Dim rand As Double
rand = Rnd

‘ 根据概率分配条件
If rand < 0.8 Then UserVariables("Condition") = 1 ' 有效提示 ElseIf rand < 0.9 Then UserVariables("Condition") = 2 ' 无效提示 Else UserVariables("Condition") = 3 ' 中性提示 End If ' 设置目标位置(随机) UserVariables("TargetPosition") = IIf(Rnd < 0.5, 1, 2) ' 1=左, 2=右 ' 设置提示类型 If UserVariables("Condition") = 1 Then ' 有效提示:提示方向与目标位置一致 If UserVariables("TargetPosition") = 1 Then UserVariables("CueType") = "LeftArrow" Else UserVariables("CueType") = "RightArrow" End If ElseIf UserVariables("Condition") = 2 Then ' 无效提示:提示方向与目标位置相反 If UserVariables("TargetPosition") = 1 Then UserVariables("CueType") = "RightArrow" Else UserVariables("CueType") = "LeftArrow" End If Else ' 中性提示:双箭头 UserVariables("CueType") = "DoubleArrow" End If ' 设置ISI时间(随机化) UserVariables("ISI_Duration") = Int(500 + 500 * Rnd) ' 500-1000ms ' 设置反应键(平衡) If UserVariables("TargetPosition") = 1 Then UserVariables("CorrectKey") = UserVariables("LeftKey") Else UserVariables("CorrectKey") = UserVariables("RightKey") End If End Sub Sub SetupAttentionCheckTrial() ' 设置注意力检查试次 UserVariables("Condition") = 99 ' 特殊条件码 UserVariables("CueType") = "AttentionCheck" UserVariables("TargetPosition") = 0 ' 无目标 UserVariables("CorrectKey") = "space" ' 必须按空格键 UserVariables("ISI_Duration") = 800 End Sub Sub OnTrialEnd() ' 记录数据 If UserVariables("IsAttentionCheck") = 0 Then ' 正常试次:记录反应时间和准确性 UserVariables("RT_" & UserVariables("CurrentTrial")) = UserVariables("ReactionTime") UserVariables("Accuracy_" & UserVariables("CurrentTrial")) = UserVariables("Accuracy") UserVariables("Valid_" & UserVariables("CurrentTrial")) = 1 Else ' 注意力检查试次:检查反应是否正确 If UserVariables("Accuracy") = 1 Then UserVariables("Valid_" & UserVariables("CurrentTrial")) = 1 Else UserVariables("Valid_" & UserVariables("CurrentTrial")) = 0 ShowMessage "请注意!检测到注意力不集中" End If End If ' 检查是否需要调整难度 If UserVariables("CurrentTrial") Mod 20 = 0 Then AdjustDifficulty End If End Sub Sub OnBlockEnd() ' block结束后计算表现 Dim blockAcc As Double Dim blockRT As Double blockAcc = CalculateBlockAccuracy(currentBlock) blockRT = CalculateBlockRT(currentBlock) ' 显示block反馈 ShowMessage "Block " & currentBlock & " 完成!\n准确率: " & Format(blockAcc * 100, "0.0") & "%\n平均反应时间: " & Format(blockRT, "0") & "ms" ' 增加block计数 currentBlock = currentBlock + 1 ' 如果准确率过低,延长休息时间 If blockAcc < 0.7 Then ShowMessage "准确率较低,请休息更长时间" Wait 5000 ' 额外5秒休息 End If End Sub Sub OnExperimentEnd() ' 实验结束后的数据质量检查 Dim totalValid As Integer Dim totalTrials As Integer totalTrials = UserVariables("CurrentTrial") totalValid = 0 For i = 1 To totalTrials If UserVariables("Valid_" & i) = 1 Then totalValid = totalValid + 1 End If Next ' 生成数据质量报告 Open "DataQuality_" & UserVariables("SubjectID") & ".txt" For Output As #1 Print #1, "被试ID: " & UserVariables("SubjectID") Print #1, "总试次数: " & totalTrials Print #1, "有效试次数: " & totalValid Print #1, "有效率: " & Format(totalValid / totalTrials * 100, "0.0") & "%" If totalValid / totalTrials < 0.9 Then Print #1, "警告:数据有效率低于90%,建议重新实验" Else Print #1, "数据质量良好" End If Close #1 End Sub ' 辅助函数 Function CalculateBlockAccuracy(blockNum As Integer) As Double Dim sum As Integer Dim count As Integer sum = 0 count = 0 For i = 1 To UserVariables("CurrentTrial") If UserVariables("Block_" & i) = blockNum And UserVariables("IsAttentionCheck_" & i) = 0 Then sum = sum + UserVariables("Accuracy_" & i) count = count + 1 End If Next If count > 0 Then
CalculateBlockAccuracy = sum / count
Else
CalculateBlockAccuracy = 0
End If
End Function

Function CalculateBlockRT(blockNum As Integer) As Double
Dim sum As Double
Dim count As Integer
sum = 0
count = 0

For i = 1 To UserVariables(“CurrentTrial”)
If UserVariables(“Block_” & i) = blockNum And UserVariables(“IsAttentionCheck_” & i) = 0 And UserVariables(“Accuracy_” & i) = 1 Then
sum = sum + UserVariables(“RT_” & i)
count = count + 1
End If
Next

If count > 0 Then
CalculateBlockRT = sum / count
Else
CalculateBlockRT = 0
End If
End Function

Function AdjustDifficulty()
‘ 根据最近20个试次的表现调整难度
Dim recentAcc As Double
recentAcc = CalculateBlockAccuracy(UserVariables(“CurrentBlock”))

If recentAcc > 0.9 Then
‘ 减少刺激呈现时间
UserVariables(“TargetDuration”) = Max(100, UserVariables(“TargetDuration”) – 50)
ShowMessage “难度提升:刺激时间缩短”
ElseIf recentAcc < 0.7 Then ' 增加刺激呈现时间 UserVariables("TargetDuration") = Min(2000, UserVariables("TargetDuration") + 100) ShowMessage "难度降低:刺激时间延长" End If End Function 步骤4:设置反应对象 ' 在Target刺激后的Response对象设置: ' Response对象属性: ' - ObjectName: TargetResponse ' - Duration: 2000 (反应时间窗口) ' - ContinueMode: 0 (等待反应) ' - AllowedKeys: 变量设置 ' 在Script中动态设置: ' TargetResponse.AllowedKeys = UserVariables("CorrectKey") ' - ErrorFeedback: False (正式实验不显示,练习可显示) ' - OnsetScript: 记录刺激呈现时间 ' - OffsetScript: 记录反应时间 ' 在Response对象的OnsetScript中: Sub OnTargetResponseOnset() UserVariables("TargetOnsetTime") = Timer End Sub ' 在Response对象的OffsetScript中: Sub OnTargetResponseOffset() ' 记录反应时间 If UserVariables("TargetOnsetTime") > 0 Then
UserVariables(“ReactionTime”) = Timer – UserVariables(“TargetOnsetTime”)
End If

‘ 判断反应是否正确
If UserVariables(“IsAttentionCheck”) = 1 Then
‘ 注意力检查试次
If UserVariables(“ResponseKey”) = “space” Then
UserVariables(“Accuracy”) = 1
Else
UserVariables(“Accuracy”) = 0
End If
Else
‘ 正常试次
If UserVariables(“ResponseKey”) = UserVariables(“CorrectKey”) Then
UserVariables(“Accuracy”) = 1
Else
UserVariables(“Accuracy”) = 0
End If
End If

‘ 记录反应键
UserVariables(“ResponseKey”) = UserVariables(“ResponseKey”)
End Sub
5.3 实验流程控制
‘ 在SessionProc的流程控制:

‘ 1. 指导语屏幕
‘ – 显示实验说明
‘ – 强调准确性和自然反应
‘ – 显示反应键说明(根据block变化)

‘ 2. 练习block(16试次)
‘ – 显示反馈
‘ – 允许重复练习直到掌握
‘ – 设置最小准确率阈值(如>80%)

‘ 3. 正式实验block(3个block)
‘ – 每个block后休息
‘ – 显示当前进度
‘ – 插入注意力检查

‘ 4. 结束屏幕
‘ – 显示整体表现
‘ – 感谢被试
六、数据清理与分析前的质量控制
6.1 数据清理标准
在E-Prime数据导出后,需要进行以下清理:
# Python示例:数据清理脚本
import pandas as pd
import numpy as np

def clean_eprime_data(df):
“””
清理E-Prime数据,去除异常值和无效试次
“””
# 1. 去除反应时间异常值
# 反应时间 < 100ms 或 > 2000ms 视为异常
df = df[(df[‘RT’] >= 100) & (df[‘RT’] <= 2000)] # 2. 去除注意力检查失败的试次 df = df[df['IsAttentionCheck'] == 0] # 3. 去除连续相同反应模式 # 计算反应时间的移动标准差 df['RT_moving_std'] = df['RT'].rolling(window=5).std() # 如果连续5次反应时间标准差过小(<50ms),视为反应定势 df = df[df['RT_moving_std'] >= 50]

# 4. 去除准确率过低的被试
subject_acc = df.groupby(‘SubjectID’)[‘Accuracy’].mean()
valid_subjects = subject_acc[subject_acc > 0.7].index
df = df[df[‘SubjectID’].isin(valid_subjects)]

return df

# 使用示例
df = pd.read_csv(‘experiment_data.csv’)
cleaned_df = clean_eprime_data(df)
cleaned_df.to_csv(‘cleaned_data.csv’, index=False)
6.2 反应定势检测算法
# 检测反应定势的算法

def detect_response_bias(df, window=10, threshold=0.8):
“””
检测被试是否存在反应定势
window: 检测窗口大小
threshold: 定势阈值(如80%相同反应)
“””
results = {}

for subject in df[‘SubjectID’].unique():
subject_data = df[df[‘SubjectID’] == subject]

# 计算每个窗口内的反应模式
reaction_pattern = []
for i in range(len(subject_data) – window + 1):
window_data = subject_data.iloc[i:i+window]
# 统计最常见的反应
mode_reaction = window_data[‘ResponseKey’].mode()[0]
mode_freq = (window_data[‘ResponseKey’] == mode_reaction).mean()
reaction_pattern.append(mode_freq)

# 判断是否存在定势
max_bias = max(reaction_pattern)
has_bias = max_bias > threshold

results[subject] = {
‘max_bias’: max_bias,
‘has_bias’: has_bias,
‘recommendation’: ‘Exclude’ if has_bias else ‘Include’
}

return results

# 使用示例
bias_results = detect_response_bias(cleaned_df)
for subject, result in bias_results.items():
if result[‘has_bias’]:
print(f”被试 {subject} 存在反应定势({result[‘max_bias’]:.1%}),建议排除”)
七、总结与最佳实践建议
7.1 设计检查清单
在完成E-Prime提示范式设计后,使用以下检查清单验证设计:
[ ]
随机化检查
:所有条件是否充分随机化?
[ ]
平衡检查
:反应键、刺激位置是否平衡?
[ ]
填充试次
:是否包含20-30%的填充试次?
[ ]
注意力检查
:是否每10-15个试次插入检查?
[ ]
时间参数
:ISI是否随机化?刺激时间是否合理?
[ ]
反应多样性
:是否避免了固定反应模式?
[ ]
数据记录
:是否记录了所有必要变量?
[ ]
质量控制
:是否包含实时数据质量监控?
1.2 最佳实践总结
充分的随机化
:使用E-Prime的List.Randomize属性,但避免完全随机导致的连续相同条件
动态调整
:根据被试表现实时调整实验参数
多重监控
:结合注意力检查、反应模式分析和数据清理
平衡设计
:在block间平衡反应键和刺激位置
详细记录
:记录所有可能影响结果的变量
预实验测试
:在正式实验前进行小规模预测试,检查设计缺陷
通过以上详细的E-Prime设计策略和实现代码,您可以构建一个高质量的提示范式实验,有效避免实验数据偏差和被试反应定势,从而获得可靠的科学数据。