首页 > 解决方案 > 当试验多于对象时,我的随机播放算法崩溃

问题描述

我正在尝试在文件夹中扫描图像的实验。对于每次试验,都会显示一个目标和一些 (7) 干扰图像。之后,在一半的试验中,人们会看到目标图像,而在另一半中,他们会看到之前显示中没有的图像。

我当前的代码有点工作,但前提是试验少于对象:

repeats = 20

# Scan dir for images
jpgs = []

for path, dirs, files in os.walk(directory):
    for f in files:
        if f.endswith('.jpg'):
            jpgs.append(f)

# Shuffle up jpgs
np.random.shuffle(jpgs)

# Create list with target and probe object, Half random, half identical
display = []
question = []
sameobject = []
position = np.repeat([0,1,2,3,4,5,6,7], repeats)
for x in range(1,(repeats*8)+1):
    display.append(jpgs[x])
    if x % 2 == 0:
        question.append(jpgs[-x])
        sameobject.append(0)
    else:
        question.append(jpgs[x])
        sameobject.append(1)

# Concatonate objects together
together = np.c_[display,question,position,sameobject] 
np.random.shuffle(together)

for x in together:
        # Shuffle and set image
        np.random.shuffle(jpgs)
        myList = [i for i in jpgs if i != together[trial,0]]
        myList = [i for i in myList if i != together[trial,1]]

        # Set correct image for target
        myList[int(together[trial,2])] = together[trial,0]

首先,我知道这是可怕的代码。但它粗略地完成了工作。使用 200 jpg 和 20 重复,它可以工作。如果重复设置为 30,它会崩溃。

这是一个重复太高的例子:

  File "H:\Code\Stims\BetaObjectPosition.py", line 214, in <module>
    display.append(jpgs[x])
IndexError: list index out of range

有没有办法以允许更多试验的方式更新我的代码,同时在整个实验中尽可能均匀地使用所有对象(一个对象不应显示 3 次而另一个对象显示 0 次)?

完整的、可重复的示例

如果任何人都可以看到一种明显的方法来平衡 7 个干扰图像的选择方式,则可以加分。

感谢您花时间阅读本文。我希望你能帮助我。

标签: pythonpsychopyexperimental-design

解决方案


更改代码最少的解决方案应该是将每次调用更改jpgs[x]jpgs[x % len(jpgs)]1。这应该摆脱IndexError; 它基本上将列表索引包裹在“边缘”,确保它永远不会太大。虽然我不确定它将如何与jpgs[-x]通话交互。

另一种方法是实现一个类,该类从较短的对象生成较长的对象序列。例子:

from random import shuffle


class InfiniteRepeatingSequence(object):
  def __init__(self, source_list):
      self._source = source_list
      self._current = []

  def next(self):
      if len(self._current) == 0:
          # copy the source
          self._current = self._source[:]

          shuffle(self._current)

      # get and remove an item from a list
      return self._current.pop()

此类无限期地重复列表。它确保在重新使用列表之前使用每个元素一次。它可以很容易地变成一个迭代器(尝试更改next__next__)。但要小心,因为上面的类会产生无限的元素序列。


1有关运算符的说明,请参阅“ Python 中的 % 是如何工作的? ” 。

编辑:添加了模问题的链接。


推荐阅读