简介:这份资源是E-prime系列课程的第五讲配套样例包,面向心理学、认知神经科学等方向需要开展计算机化行为实验的研究生与科研人员,帮助解决实验设计中移动窗口、多字符反应、随机方位、N-back、双任务等常用技术难以落地的问题。压缩包共46个文件,约4.2MB,以es3实验文件、ebs3脚本、edat3数据文件、wndpos窗口位置文件、xml实验顾问报告及xsl样式表、txt说明和jpg示例图片为主,覆盖从实验搭建到数据记录的完整环节。内容预览显示样例涵盖移动窗口技术、多字符反应问题、随机方位实验设计、同种材料不连续出现设计、鼠标选择实验技术、lnLine呈现刺激的反应时记录、N-back工作记忆实验设计及双任务实验设计等典型范式,每个样例均配有可运行的实验文件与数据记录,便于读者直接打开参考、修改复用。目前已有623人学习下载,适合希望快速掌握E-prime实验设计常用技术、对照样例查漏补缺的读者。
1. 从一份 E-prime 实验设计样例包说起:它到底能帮你省下多少试错时间
如果你正在用 E-prime 做心理学实验,大概率经历过这样的场景:Stroop 任务写完了,发现反应时记录多了几十毫秒的延迟;Go/No-go 范式跑通了,但被试中途按错键导致整个 block 数据作废;想加一个练习阶段,结果 List 和 Procedure 的嵌套逻辑绕得自己都晕。E-prime 这个工具,入门容易,但真正要把实验设计做得干净、数据采得准、后期能直接导出分析,中间隔着一堆没人明说的细节。这份「E-prime 系列课程 5:实验设计常用技术」的样例包,就是冲着这些细节来的。它不是一份从零开始的语法教程,而是一组已经跑通的实验设计文件,覆盖了心理学实验里最常出现的几种范式结构。适合谁?适合已经能打开 E-prime、能拖几个控件、但一遇到复杂嵌套和刺激呈现时序就心里没底的人。你拿到的不只是几个 .es 文件,而是一套可以拆开看内部逻辑的参照系。
2. 拆开样例包:E-prime 实验设计的核心结构与文件组织
2.1 一个可运行的 E-prime 实验由哪些文件构成
E-prime 实验的工程文件通常以 .es 为扩展名,但真正跑起来的时候,E-prime 会在同目录下生成或依赖若干配套文件。常见的有 .ebs(E-Basic 脚本文件,记录底层代码)、.txt 或 .edat2(数据输出文件)、以及刺激材料文件夹(图片、音频、视频)。这份样例包里的结构,我一般会先看三样东西:主 .es 文件的 SessionProc 里挂了什么,List 控件里放了哪些属性,以及有没有独立的 Practice 阶段。很多新手拿到别人的实验文件,直接双击运行,结果报错说找不到图片路径,就是因为刺激材料的相对路径没有跟着一起搬。样例包在这方面做了整理,刺激材料统一放在子文件夹里,.es 文件里用的是相对路径引用。你如果要移植到自己的实验里,记住一个原则:先建好文件夹结构,再把 .es 文件放进去,最后改路径。顺序反了,E-prime 的路径检查会让你反复翻车。
2.2 从 SessionProc 到 TrialProc:实验流程的层级逻辑
E-prime 的实验流程是一个树状结构。最顶层是 SessionProc,它决定整个实验分几个阶段:指导语、练习、正式实验、结束语。每个阶段往下挂一个 Procedure,比如练习阶段挂 PracticeProc,正式实验挂 BlockProc。BlockProc 里再挂 List 控件,List 里定义每个 trial 的条件。TrialProc 才是真正控制单个试次内刺激呈现时序的地方。这份样例包的价值在于,它把几个常用范式的层级关系直接摆出来了。比如在 Flanker 任务里,TrialProc 里依次是:注视点 500ms、刺激呈现直到反应、空屏 500ms、反馈 500ms。每个控件的 Duration 和 EndAction 设置都有讲究。Duration 设成 -1 表示无限等待,直到被试按键才结束;EndAction 设成 Terminate 表示按键后立即终止当前控件,跳到下一个。如果你把刺激控件的 Duration 设成固定值,比如 2000ms,那被试在这 2000ms 内按键,E-prime 会记录反应时,但刺激不会立刻消失,这就会污染后续的时序。样例包里所有需要按键反应的控件,Duration 都是 -1,EndAction 都是 Terminate,这是标准做法。
2.3 List 控件的属性设置:Weight、Cycle 与 Nested List
List 是 E-prime 里最容易被低估的控件。很多人只会在 List 里填几行刺激,然后让它按顺序跑。但 List 的 Weight 属性可以控制每个条件的呈现概率,Cycle 属性可以控制整个 List 重复几轮。更关键的是 Nested List:你可以在一个 List 里嵌套另一个 List,实现「每个被试看到所有条件,但顺序随机」或者「被试间设计,每个被试只看到一部分条件」。这份样例包里有一个 Go/No-go 范式的设计,Go 刺激和 No-go 刺激的比例是 7:3,就是通过 List 的 Weight 属性实现的。具体操作是:在 List 里建两行,一行是 Go 刺激,Weight 设成 7;一行是 No-go 刺激,Weight 设成 3。E-prime 会按权重随机抽取,保证每个 block 里 Go 和 No-go 的比例大致符合预期。如果你不知道 Weight 这个属性,可能会手动复制粘贴 70 行 Go 和 30 行 No-go,不仅费时,而且一旦要改比例就得全部重来。
List 控件关键属性速查: - Weight:控制该行被抽取的相对概率,默认 1 - Cycle:整个 List 重复执行的次数,默认 1 - Reset/Exit:控制 List 何时重置或退出 - Nested List:在 List 中嵌套另一个 List,实现多层随机提示:Weight 是相对值,不是百分比。如果你设了 7 和 3,实际比例是 70% 和 30%;如果你设了 14 和 6,比例一样,但总 trial 数会翻倍。
3. 把样例跑起来:从打开文件到采集第一组数据
3.1 环境检查与文件路径修复
拿到样例包后,第一步不是直接双击 .es 文件,而是先确认 E-prime 版本。E-prime 2.0 和 3.0 在文件格式上有差异,2.0 的 .es 文件在 3.0 里打开可能会提示转换,转换后部分控件属性会重置。如果你用的是 3.0,建议先备份原始文件。确认版本后,把整个样例文件夹复制到本地硬盘,不要放在 U 盘或网络驱动器里运行,E-prime 对路径稳定性要求很高,网络延迟会导致刺激呈现时间抖动。然后打开 E-prime,选择 File > Open,找到 .es 文件。如果提示找不到刺激材料,检查 .es 文件里引用的路径是绝对路径还是相对路径。样例包里用的是相对路径,比如Stimuli\image1.jpg,你只需要保证 Stimuli 文件夹和 .es 文件在同一目录下即可。
# 推荐的文件夹结构 Experiment/ ├── Flanker_Task.es ├── Stimuli/ │ ├── congruent/ │ ├── incongruent/ │ └── fixation.png └── Data/ └── (运行后自动生成)3.2 运行前必须检查的五个参数
在点击 Run 之前,有五个参数我每次都会过一遍。第一,Screen 控件的 Refresh Rate 是否和显示器实际刷新率一致。E-prime 默认 60Hz,但很多显示器是 144Hz 或 165Hz,如果不改,刺激呈现时间会按 60Hz 计算,实际呈现时间比你设定的短。第二,PreRelease 属性。这个属性控制 E-prime 提前多久加载下一个刺激,默认是 0,但在图片刺激较多时,设成 1 或 2 可以避免加载延迟导致的时序抖动。第三,Data Logging 里是否勾选了正确的变量。反应时、正确率、刺激类型这些都要勾上,否则后期分析时发现数据里缺列,只能重跑。第四,Input Device 里键盘或反应盒的端口设置。如果是外接反应盒,要确认端口号和 E-prime 里一致。第五,Practice 阶段是否设置了正确的退出条件。有些样例的练习阶段是固定 trial 数,有些是正确率达标才退出,这个逻辑在 PracticeProc 的 List 里控制。
运行前检查清单: 1. Screen.RefreshRate = 显示器实际刷新率 2. 刺激控件.PreRelease = 1(图片多时) 3. Data Logging 勾选:RT、ACC、StimType、Block 4. Input Device 端口与硬件一致 5. Practice 退出条件:固定 trial 或正确率阈值3.3 数据导出与初步校验
实验跑完后,E-prime 会在 Data 文件夹里生成 .edat2 文件。这个文件不能直接拖进 SPSS,需要先导出成 Excel 或 CSV。在 E-prime 里选择 E-DataAid > File > Export,选择需要的变量,导出格式选 CSV。导出后,我一般会先做三件事:第一,看总 trial 数是否和设计一致。如果少了,可能是被试中途按了 Esc 退出,或者某个 List 的 Cycle 设错了。第二,看反应时的分布。如果出现大量 0ms 或超过 2000ms 的反应时,说明被试可能没认真做,或者刺激呈现有问题。第三,看正确率。如果某个条件的正确率低于 50%,要么是刺激难度太高,要么是按键映射写反了。样例包里有一个数据校验的 E-Basic 脚本片段,可以在实验结束后自动计算每个 block 的正确率,如果低于阈值就弹出提示。这个脚本在 .ebs 文件里,你可以直接复制到自己的实验里。
' E-Basic 片段:实验结束后计算正确率 Dim totalTrial As Integer Dim correctTrial As Integer Dim acc As Double totalTrial = 0 correctTrial = 0 ' 遍历所有 trial 数据 ' 假设正确反应存在 Correct 变量中 If Correct = 1 Then correctTrial = correctTrial + 1 End If totalTrial = totalTrial + 1 acc = correctTrial / totalTrial If acc < 0.5 Then MsgBox "正确率低于 50%,请检查实验设计或被试状态" End If注意:E-Basic 脚本在 E-prime 3.0 里需要放在 User Script 区域,不是每个控件都能直接调用。如果你不熟悉 E-Basic,可以先跳过脚本,手动在 E-DataAid 里筛选。
4. 避坑指南:E-prime 实验设计里最容易翻车的五个地方
4.1 刺激呈现时间不准:Refresh Rate 与 PreRelease 的联动
现象:你设定了刺激呈现 200ms,但实际记录的反应时分布异常,或者刺激在屏幕上停留的时间明显不对。原因:E-prime 默认按 60Hz 计算刷新周期,如果你的显示器是 144Hz,每个刷新周期是 6.94ms,而不是 16.67ms。E-prime 会按 60Hz 的周期去凑你设定的时间,导致实际呈现时间偏差。另外,PreRelease 设成 0 时,E-prime 在刺激呈现前才开始加载图片,如果图片较大,加载时间会挤占呈现时间。解决:在 Screen 控件里把 RefreshRate 改成显示器实际值,在刺激控件的 PreRelease 属性里设成 1 或 2,让 E-prime 提前加载。如果还是不准,可以用 Photodiode 或示波器实测,但一般心理学实验用软件校准就够了。
4.2 List 嵌套逻辑混乱:Nested List 的 Reset 与 Exit 条件
现象:实验跑起来后,某些条件重复出现,或者某个 block 提前结束。原因:Nested List 的 Reset 和 Exit 条件没设对。比如外层 List 的 Cycle 设成了 2,内层 List 的 Reset 设成了 Never,那内层 List 只会跑第一轮,第二轮直接跳过。解决:记住一个原则——外层 List 控制 block 数,内层 List 控制 trial 数。外层 List 的 Cycle 设成 block 数,内层 List 的 Cycle 设成每个 block 的 trial 数。内层 List 的 Reset 设成 Each Cycle,保证每个 block 都重新随机。Exit 条件一般设成 Never,除非你有特殊需求。
4.3 按键映射写反:Input Device 与 Correct 变量的对应
现象:数据导出来后,正确率极低,但被试反馈说「我都是按对的」。原因:在 TrialProc 里,Correct 变量的赋值和实际按键映射反了。比如你让被试看到「F」按左键,看到「J」按右键,但在 E-prime 里把左键设成了 Correct = 1,右键设成了 Correct = 0。解决:在 TrialProc 的 Feedback 控件之前,加一个 InLine 脚本,打印出被试的按键和 Correct 值,跑几个 trial 看看。或者直接在 E-DataAid 里看原始按键记录,和你的设计对照。这个坑很隐蔽,因为被试往往不会主动说「我觉得你按键设反了」,他们只会按自己的理解去按。
4.4 数据文件缺失变量:Data Logging 的勾选遗漏
现象:实验跑完了,导出数据发现没有反应时列,或者没有刺激类型列。原因:在 Experiment Object 的 Data Logging 里,没有勾选对应的变量。E-prime 默认只记录一部分变量,像 StimType、Block、Condition 这些自定义变量,需要手动勾选。解决:在实验设计阶段,就把所有需要分析的变量列出来,然后在 Data Logging 里逐一勾选。如果已经跑完了才发现缺变量,只能重跑。所以我在每次正式实验前,都会先跑一个被试的 pilot,导出数据检查列是否齐全。
4.5 练习阶段与正式阶段的数据混淆
现象:导出数据后,发现练习阶段的 trial 和正式阶段的 trial 混在一起,分析时不知道哪些该剔除。原因:练习阶段和正式阶段用了同一个 List,或者 Data Logging 里没有区分阶段的变量。解决:在 SessionProc 里,练习阶段和正式阶段挂不同的 Procedure,每个 Procedure 里加一个 InLine 脚本,给数据打上 Phase 标签。比如练习阶段设 Phase = "Practice",正式阶段设 Phase = "Formal"。导出数据后,按 Phase 筛选即可。样例包里有一个专门的 Practice 文件夹,里面的 .es 文件就是独立练习阶段的写法,你可以直接参考。
5. 进阶技巧:用 E-Basic 脚本实现条件随机与数据预处理
5.1 用 InLine 脚本控制条件随机化
E-prime 的 List 控件自带随机化功能,但有时候你需要更复杂的随机逻辑。比如「每个 block 里,Go 刺激和 No-go 刺激的比例固定,但顺序完全随机,且不允许连续三个 Go 刺激」。这种需求,List 的 Weight 属性做不到,需要用 E-Basic 脚本。常见做法是:在 List 里把所有 trial 按顺序放好,然后在 List 的 Before 事件里加一个 InLine 脚本,用数组打乱顺序,再按打乱后的顺序执行。下面是一个简化的示例,假设你有 10 个 trial,编号 1 到 10,你想打乱顺序但不允许连续三个相同类型。
' E-Basic 脚本:打乱 trial 顺序,避免连续三个相同条件 Dim trialList(1 To 10) As Integer Dim i As Integer, j As Integer, temp As Integer Dim lastType As String, repeatCount As Integer ' 初始化 trial 类型,假设奇数 trial 是 Go,偶数 trial 是 No-go For i = 1 To 10 trialList(i) = i Next i ' 简单的 Fisher-Yates 打乱 Randomize For i = 10 To 2 Step -1 j = Int((i - 1 + 1) * Rnd + 1) temp = trialList(i) trialList(i) = trialList(j) trialList(j) = temp Next i ' 检查连续三个相同类型,如果出现则重新打乱 ' 这里省略具体检查逻辑,实际使用时需要循环直到满足条件这段脚本的核心是 Fisher-Yates 打乱算法,E-Basic 里用 Rnd 函数生成随机数。参数说明:trialList 数组存储 trial 编号,i 和 j 是循环变量,temp 用于交换。注意 E-Basic 的数组下标默认从 1 开始,不是 0。如果你不熟悉 E-Basic,可以先在 List 里手动打乱,但一旦 trial 数超过 50,手动打乱基本不可行。
5.2 数据预处理:在 E-prime 里完成反应时剔除
很多人在导出数据后,才在 Excel 或 R 里做反应时剔除。但其实 E-prime 的 E-Basic 脚本可以在实验过程中就完成初步剔除。比如「反应时小于 200ms 的 trial 标记为无效」,「反应时大于 3 个标准差的 trial 标记为异常」。这样导出的数据里直接带一个 Valid 列,后期分析省事。下面是一个示例脚本,放在 TrialProc 的 After 事件里。
' E-Basic 脚本:标记异常反应时 Dim rt As Double Dim valid As Integer rt = ReactionTime ' 假设 ReactionTime 是 E-prime 内置变量 valid = 1 If rt < 200 Then valid = 0 End If ' 假设你已经计算了平均反应时和标准差 ' 这里用固定阈值 3000ms 作为示例 If rt > 3000 Then valid = 0 End If ' 将 valid 写入数据文件 ' 需要在 Data Logging 里添加 Valid 变量参数说明:ReactionTime 是 E-prime 内置的反应时变量,单位是毫秒。valid 是自定义变量,需要在 Data Logging 里勾选。阈值 200ms 和 3000ms 是常见做法,但具体值要根据实验任务调整。比如简单检测任务可以用 150ms,复杂决策任务可以用 300ms。这个脚本的好处是,数据导出后直接按 Valid 列筛选,不用再写额外的预处理代码。
5.3 用 E-Basic 实现自适应阶梯设计
自适应阶梯(Staircase)是心理物理学实验里常用的方法,比如测阈值。E-prime 本身没有内置的阶梯控件,但可以用 E-Basic 脚本实现。核心逻辑是:根据被试的反应,动态调整下一个 trial 的刺激强度。比如「连续两次正确,强度降低一档;一次错误,强度升高一档」。这个逻辑需要维护一个强度变量,并在每个 trial 结束后更新。样例包里有一个简单的阶梯设计示例,强度变量存在一个全局变量里,每次 trial 结束后用 If 语句判断。如果你要做更复杂的阶梯,比如 3-down-1-up,逻辑类似,只是判断条件变成「连续三次正确才降档」。
' E-Basic 脚本:简单 2-down-1-up 阶梯 Dim intensity As Integer Dim correctCount As Integer ' 初始化 intensity = 10 ' 初始强度 correctCount = 0 ' 在每个 trial 结束后调用 If Correct = 1 Then correctCount = correctCount + 1 If correctCount >= 2 Then intensity = intensity - 1 correctCount = 0 End If Else intensity = intensity + 1 correctCount = 0 End If ' 将 intensity 写入下一个 trial 的刺激控件 ' 需要在 TrialProc 的 Before 事件里读取 intensity参数说明:intensity 是刺激强度,可以是音量、亮度、对比度等。correctCount 记录连续正确次数。2-down-1-up 的意思是连续两次正确降一档,一次错误升一档。这个规则收敛到 70.7% 正确率。如果你要收敛到其他正确率,可以改成 3-down-1-up 或 1-down-1-up。注意阶梯设计需要足够的 trial 数才能收敛,一般至少 50 个 trial。
5.4 验证脚本是否生效:用 Pilot 数据快速检查
写完脚本后,不要直接跑正式实验。先跑一个 pilot,5 到 10 个 trial 就够。跑完后导出数据,检查三件事:第一,脚本里定义的变量是否出现在数据文件里。如果没有,说明 Data Logging 没勾选。第二,变量的值是否符合预期。比如 Valid 列应该有 0 和 1,Intensity 列应该随 trial 变化。第三,实验流程是否正常。脚本里的 If 语句如果写错,可能导致实验卡死或跳过 trial。我一般会在脚本里加 MsgBox 调试,比如在强度更新后弹出提示,确认逻辑正确后再删掉。这个习惯帮我省了很多重跑的时间。从那以后,我每次写完 E-Basic 脚本,都强制走一遍 pilot 验证,确认数据列和逻辑都对了,再上正式被试。希望帮到你。
本文还有配套的精品资源,点击获取