当为sigmoid函数分别实现猜测和失效率时,curve_fit图生成一条直线

时间:2016-03-10 13:25:09

标签: python matplotlib scipy

我需要为一系列数据生成心理测量拟合图,我有一个工作脚本,当我: -

时能够这样做

1)使用默认的sigmoid公式和 2)将猜测率设置为0,将失效率添加到sigmoid函数上。

但是,在公式之外设置大于0的猜测率会导致平线。如果我将sigmoid函数外的失效率设置为独立但固定的变量,则不会发生这种情况。知道这里出了什么问题吗?

以下代码是生成两条直线的代码。 这个特定情节的数据是: -

[0,2.0,9.0,11.0,14.0]值插入到ysdata

[3.0,7.0,14.0,19.0,20.0]值插入ycdata

import numpy as np
import pylab
from scipy.optimize import curve_fit
from matplotlib.pyplot import *
import os
import csv

C1adaptS = 0
CN2adaptS = 0
N3adaptS = 0
NS4adaptS = 0
S5adaptS = 0
C1adaptC = 0
CN2adaptC = 0
N3adaptC = 0
NS4adaptC = 0
S5adaptC = 0

#Paste filename to be analysised here (The .csv file)
filename = 'PartID_AA_20160302_1332.csv'

#Change directory to file's location
os.chdir('C:\Users\Aaron\Dropbox\JitterAdapt\Dotty Simplified (latest dot exp)\Dotty Simplified (Full Experiment Folder)')

loadcsv = open(filename, 'r')
for line in loadcsv.readlines():
    line = line.strip()
    #Split the words within the line
    trialnum, stimulus, stimulus_location, response, more_sin_like, sin_adapt = line.split(',')
    if stimulus == 'C1' and more_sin_like == '1' and sin_adapt == '1':
        C1adaptS += 1.
    elif stimulus == 'CN2' and more_sin_like == '1' and sin_adapt == '1':
        CN2adaptS += 1.
    elif stimulus == 'N3' and more_sin_like == '1' and sin_adapt == '1':
        N3adaptS += 1.
    elif stimulus == 'NS4' and more_sin_like == '1' and sin_adapt == '1':
        NS4adaptS += 1.
    elif stimulus == 'S5' and more_sin_like == '1' and sin_adapt == '1':
        S5adaptS += 1.
    elif stimulus == 'C1' and more_sin_like == '1' and sin_adapt == '0':
        C1adaptC += 1.
    elif stimulus == 'CN2' and more_sin_like == '1' and sin_adapt == '0':
        CN2adaptC += 1.
    elif stimulus == 'N3' and more_sin_like == '1' and sin_adapt == '0':
        N3adaptC += 1.
    elif stimulus == 'NS4' and more_sin_like == '1' and sin_adapt == '0':
        NS4adaptC += 1.
    elif stimulus == 'S5' and more_sin_like == '1' and sin_adapt == '0':
        S5adaptC += 1.

SinAdaptList = [C1adaptS, CN2adaptS, N3adaptS, NS4adaptS, S5adaptS]
ConsAdaptList = [C1adaptC, CN2adaptC, N3adaptC, NS4adaptC, S5adaptC]

n = 20 #divide y-axis data by the number of trials in the experiment

guess = 0.05 #Set the minimum chance level
#lapse = 0.05 #The lapse rate. 0.01 = 1%

# The sigmoid function as defined is only applicable to a simple experiment where a single stimulus is 
# detected (nor not) and where the participant makes no errors. We need two new values;
# a ‘guessing’ value, that is the probability that the participant with get correct if they simply guess, 
# and a ‘lapsing’ probability, that is the estimated number of trials in which the participant will make a mistake.
# As an example, a 2AFC (two alternative forced choice) task forces the participant to choose between two stimuli, 
# the probability of getting the correct stimuli by chance is 0.5 so we set the value of the guess variable to 0.5. 
# The lapse variable can be found from the data. These two variables need to shift and scale the Sigmoid function.
# Instead of having a minima at 0 we need the minima of our sigmoid to match the guessing rate (0.5) 
# in our example so we add 0.5. We then need to scale the sigmoid to fit (adding 0.5 to 1 is 1.5 so 
# we need to rescale back to 1), this is achieved by dividing by (1-guessing rate) that is the bit left 
# over between 0 and 1 when the guess it taken out. Finally we can account for the lapse rate by taking a 
# ‘bit off the top’     

#The scaled sigmoid function
def sigmoidscaled(x, x0, k, lapse):
    F = (1 + np.exp(-k*(x-x0))) 
    z = guess + (1-guess-lapse)/F
    return z


#The data points in x-y coordinates
xdata = np.array([ 1.0, 2.0, 3.0, 4.0, 5.0])
ysdata = np.array([C1adaptS/n, CN2adaptS/n, N3adaptS/n, NS4adaptS/n, S5adaptS/n])
ycdata = np.array([C1adaptC/n, CN2adaptC/n, N3adaptC/n, NS4adaptC/n, S5adaptC/n])


#popt = 50% point. pcov = covariance. Fit the sigmoid function to the data.
popt, pcov = curve_fit(sigmoidscaled, xdata, ysdata)
popt2, pcov2 = curve_fit(sigmoidscaled, xdata, ycdata)

#Start and End of x-axis, in spaces of n. The higher the n, the smoother the curve.
x = np.linspace(1,5,20)
#The sigmoid values along the y-axis, generated in relation to the x values and the 50% point.
#The * in front of popt when you plot will expand out the terms into the x0 and k that func is expecting.
ys = sigmoidscaled(x, *popt)
yc = sigmoidscaled(x, *popt2)

pylab.plot(xdata, ysdata, 'o', label='sin adapted', color = 'blue')
pylab.plot(xdata, ycdata, 'o', label='cons adapted', color = 'red')
pylab.plot(x,ys, label='sin fit', color = 'blue')
pylab.plot(x,yc, label='cons fit', color = 'red')
#y axis range.
pylab.ylim(0, 1)
#Replace x-axis numbers as labels and y-axis numbers as percentage
xticks([1., 2., 3., 4., 5.], ['C1','CN2','N3','CN4','S5'])
yticks([0.0, 0.2, 0.4, 0.6, 0.8, 1.0], ['0%','20%','40%','60%','80%','100%'])
pylab.legend(loc='best')
pylab.show()

enter image description here enter image description here

0 个答案:

没有答案