2017-11-07 6 views
1

値だから私はこの方程式にデータポイントのセットに合うようにしようとしていますのために働いていません1)---ショックリーダイオードの式scipyのダウンロードカーブフィットの最適化は、対数スケールが

私は与えられたデータの束に。 VとIの値を知っているので、Ioとnの値を最適化して、私が与えられたデータセットと密接に一致するデータを取得する必要があります。

しかし、scipy最適化曲線フィットは、私にはn =〜1.15とIo =〜1.8E-13の値を与えず、代わりにn = 2.12とI = 2.11E-11を与えます。私はこれがデータセットの値が非常に小さいので、最適化を乱していると思われますが、初期の推測値をn = 1.15、Io = 1.8E-13に設定しても最適化値は変わりません。

これを修正する方法についてのヒントはありますか?グラフの

import numpy as np 
import math 
import matplotlib.pyplot as plt 
from scipy.optimize import curve_fit 


Voltage = np.array([-0.5 , -0.49, -0.48, -0.47, -0.46, -0.45, -0.44, -0.43, -0.42, 
     -0.41, -0.4 , -0.39, -0.38, -0.37, -0.36, -0.35, -0.34, -0.33, 
     -0.32, -0.31, -0.3 , -0.29, -0.28, -0.27, -0.26, -0.25, -0.24, 
     -0.23, -0.22, -0.21, -0.2 , -0.19, -0.18, -0.17, -0.16, -0.15, 
     -0.14, -0.13, -0.12, -0.11, -0.1 , -0.09, -0.08, -0.07, -0.06, 
     -0.05, -0.04, -0.03, -0.02, -0.01, 0. , 0.01, 0.02, 0.03, 
     0.04, 0.05, 0.06, 0.07, 0.08, 0.09, 0.1 , 0.11, 0.12, 
     0.13, 0.14, 0.15, 0.16, 0.17, 0.18, 0.19, 0.2 , 0.21, 
     0.22, 0.23, 0.24, 0.25, 0.26, 0.27, 0.28, 0.29, 0.3 , 
     0.31, 0.32, 0.33, 0.34, 0.35, 0.36, 0.37, 0.38, 0.39, 0.4 ]) 
Current = np.array([ 6.99000000e-13, 6.83000000e-13, 6.57000000e-13, 
     6.46000000e-13, 6.19000000e-13, 6.07000000e-13, 
     5.86000000e-13, 5.73000000e-13, 5.55000000e-13, 
     5.37000000e-13, 5.27000000e-13, 5.08000000e-13, 
     4.92000000e-13, 4.75000000e-13, 4.61000000e-13, 
     4.43000000e-13, 4.32000000e-13, 4.18000000e-13, 
     3.99000000e-13, 3.91000000e-13, 3.79000000e-13, 
     3.66000000e-13, 3.54000000e-13, 3.43000000e-13, 
     3.34000000e-13, 3.18000000e-13, 3.06000000e-13, 
     2.96000000e-13, 2.86000000e-13, 2.77000000e-13, 
     2.66000000e-13, 2.59000000e-13, 2.54000000e-13, 
     2.43000000e-13, 2.33000000e-13, 2.22000000e-13, 
     2.16000000e-13, 2.07000000e-13, 2.00000000e-13, 
     1.94000000e-13, 1.85000000e-13, 1.77000000e-13, 
     1.68000000e-13, 1.58000000e-13, 1.48000000e-13, 
     1.35000000e-13, 1.21000000e-13, 1.03000000e-13, 
     7.53000000e-14, 4.32000000e-14, 2.33000000e-15, 
     6.46000000e-14, 1.57000000e-13, 2.82000000e-13, 
     4.58000000e-13, 7.07000000e-13, 1.06000000e-12, 
     1.57000000e-12, 2.28000000e-12, 3.29000000e-12, 
     4.75000000e-12, 6.80000000e-12, 9.76000000e-12, 
     1.39000000e-11, 1.82000000e-11, 2.57000000e-11, 
     3.67000000e-11, 5.21000000e-11, 7.39000000e-11, 
     1.04000000e-10, 1.62000000e-10, 2.27000000e-10, 
     3.21000000e-10, 4.48000000e-10, 6.21000000e-10, 
     8.70000000e-10, 1.20000000e-09, 1.66000000e-09, 
     2.27000000e-09, 3.08000000e-09, 4.13000000e-09, 
     5.46000000e-09, 7.05000000e-09, 8.85000000e-09, 
     1.11000000e-08, 1.39000000e-08, 1.74000000e-08, 
     2.05000000e-08, 2.28000000e-08, 2.52000000e-08, 
     2.91000000e-08]) 

def diode_function(V, n, Io): 
    kt = 300 * 1.38 * math.pow(10, -23) 
    q = 1.60 * math.pow(10, -19) 
    I_final = Io * (np.exp((q * V)/(n * kt)) - 1) 
    return abs(I_final) 


p0 = [1.15, 1.8e-13] 
popt, pcov = curve_fit(diode_function, Voltage, Current, p0 = p0) 

print(popt) 

fig = plt.figure() 
ax = fig.add_subplot(121) 
ax.set_title('I_d vs V_d') 
ax.set_xlabel('V_d') 
ax.set_ylabel('I_d') 
ax.set_yscale('log') 
plt.plot(Voltage, Current, 'ko', label="Original Data") 
plt.plot(Voltage, diode_function(Voltage, *popt), 'r-', label="Fitted Curve") 
plt.legend(loc='best') 



ax = fig.add_subplot(122) 
ax.set_title('I_d vs V_d') 
ax.set_xlabel('V_d') 
ax.set_ylabel('I_d') 
ax.set_yscale('log') 
popt = [1.15,1.8e-13] 
plt.plot(Voltage, Current, 'ko', label="Original Data") 
plt.plot(Voltage, diode_function(Voltage, *popt), 'r-', label="Fitted Curve") 
plt.legend(loc='best') 
plt.show() 

画像: enter image description here

左のグラフは、scipyのダウンロードの最適化であり、右のグラフは使用して、私はあなたが正しい軌道に乗っていると思い、私は

+0

私は、データセットの最後の15個の値を切り出すときに、それは私より良いフィット感を提供します。関数が、最初の値よりも最後の2つの値がより重要であると信じている理由を確信していない – User33029

+0

通常、最小二乗適合の場合、より大きな値はより多く重み付けされます。ここでの最後の値は、より高い値です。これを補うために、フィットに重み付けを導入することができます。しかし、私はそれが本当にプログラミングに関する質問ではないと思っています。 – ImportanceOfBeingErnest

+0

私の質問は、どのようにしてcurve_fitをより低い値の重み付けにするかです。私は 'np.log10(現在)'を使って現在のデータを対数に変換し、 'return np.log10(abs(I_final))'関数を作成しようとしましたが、ログを使って電圧のゼロ値が問題になります – User33029

答えて

1

をしたいものですその差がはるかに小さくなるようにデータをスケールする対数。対数の問題を防ぐために、通常のオプションの1つは定数を追加することです。 log(x)の代わりにlog(x+constant)を使用します。この定数は1以上にする必要があります。

異なる定数を使用すると、やはり大きな値が最小二乗法でより高い重み付けされるため、異なる結果が得られます。

# imports and data as in question 

def diode_function(V, n, Io): 
    kt = 300 * 1.38e-23 
    q = 1.60e-19 
    I_final = Io * (np.exp((q * V)/(n * kt)) - 1) 
    return np.abs(I_final) 

p0 = [1.15, 1.8e-13] 
popt, pcov = curve_fit(diode_function, Voltage, Current, p0 = p0) 

fig, ax = plt.subplots() 
ax.set_title('I_d vs V_d') 
ax.set_xlabel('V_d') 
ax.set_ylabel('I_d') 
ax.set_yscale('log') 
ax.plot(Voltage, Current, 'ko', label="Original Data") 

offsets = [1,15] 
colors = ["limegreen", "crimson"] 
for offset, color in zip(offsets,colors): 
    logdf = lambda V,n,Io: np.log10(diode_function(V, n, Io)+offset) 
    poptn, pcovn = curve_fit(logdf, Voltage, np.log10(Current+offset), p0 = p0) 
    ax.plot(Voltage, 10**(logdf(Voltage, *poptn))-offset, 
      color=color, label="fit (offset: {})".format(offset)) 

ax.legend(loc='best') 
plt.show() 

enter image description here

関連する問題