「信頼性工学のはなし―信頼度99.9999…%をめざして」7章
大村平「信頼性工学のはなし―信頼度99.9999…%をめざして」日科技連 の読後行間補充メモ
同書籍は、印刷数表による信頼性工学の啓蒙書。
本稿では、同書籍の設例について、Python [Google Colaboratory]による演算処理例を示す。
7章 データで信頼性を判断する
p149 図7.1上図 3種類の分布 故障率kのグラフ
ワイブル故障分布(p151)
\begin{eqnarray*} f(t)&=&k(t)\times R(t)\\&=&\cfrac{m}{\eta}\left(\cfrac{t-\gamma}{\eta}\right)^{m-1} \times e^{-\left( \cfrac{t-\gamma}{\eta}\right)^m}\end{eqnarray*}
を構成する故障率関数
- \(m\) …形状パラメータ
- \(\eta\) …尺度パラメータ
- \(\gamma\) …位置パラメータ
- 初期故障期間 \(m<1\)
- 偶発故障期間 \(m=1\)
- 摩耗故障期間 \(m>1\)
# 故障確率k
import numpy as np
import math
from matplotlib import pyplot as plt
# 設定値
m_list = [0.5, 1, 10] # 形状パラメータ(初期、偶発、摩耗)
eta_value = 1 # 尺度パラメータ(半減期、時定数)
gamma_value = 0 # 位置パラメータ
# 各時期(初期、偶発、摩耗)のパラメータ設定
g_wide =1.3 # グラフ横幅
step = 0.0001 # グラフ描画刻み
p1 = [0, g_wide, m_list[0], eta_value, gamma_value] # 始点、終点、形状、尺度、位置
p2 = [0, g_wide, m_list[1], eta_value, gamma_value]
p3 = [0, g_wide, m_list[2], eta_value, gamma_value]
graph_list = [p1,p2,p3] # リスト化
# 関数 故障確率 k (ワイブル)
def k_weibull(m_value,eta_value,gamma_value,time): # 形状、尺度、位置、時間
khead = m_value/eta_value
ktail = (time - gamma_value)/eta_value
kpower = m_value -1
y_value = khead * ktail ** kpower
return y_value
# 関数 グラフ用データ
def xylist(function,start,end,m_value,eta_value,gamma_value): # 関数、始点、終点、形状、尺度、位置
x_list = []
y_list = []
for time in np.arange(start,end,step):
x_list.append(time) # 時間リスト
y_list.append(function(m_value,eta_value,gamma_value,time)) # 演算結果リスト
return x_list, y_list
# 各グラフのパラメータを関数(グラフ用データ)に渡して、描画
ky_lists = []
for graph in graph_list:
x_data = xylist(k_weibull, graph[0],graph[1],graph[2],graph[3],graph[4])[0]
y_data = xylist(k_weibull, graph[0],graph[1],graph[2],graph[3],graph[4])[1]
plt.plot(x_data, y_data, linestyle="--")
ky_lists.append(y_data)
# バスタブ曲線
ky_lists[2] = np.nan_to_num(ky_lists[2], nan=0) # nan を0に置換
ky_sums = [x+y+z for (x,y,z) in zip(ky_lists[0], ky_lists[1],ky_lists[2])] # 3データを合計
plt.plot(x_data, ky_sums, label="Observed Hazard Rate", color='red', linewidth=3)
# グラフ凡例等
plt.xlim(0,g_wide)
plt.ylim(0,15)
plt.yticks([])
plt.xlabel('time')
plt.ylabel('k [/t]')
plt.legend()
plt.title('Hazard Rate')
plt.show()
- 初期故障期間の故障率が高く、時間経過とともに急減する。
- 偶発故障期間は低め安定となる。
- 摩耗故障期間は、故障率が増加傾向に転じる。
p149 信頼度R のグラフ
ワイブル故障分布(p151)
\begin{eqnarray*} f(t)&=&k(t)\times R(t)\\&=&\cfrac{m}{\eta}\left(\cfrac{t-\gamma}{\eta}\right)^{m-1} \times e^{-\left( \cfrac{t-\gamma}{\eta}\right)^m}\end{eqnarray*}
を構成する信頼度関数
# コードは上記の続き
# 関数 信頼度R (ワイブル)
def R_weibull(m_value,eta_value,gamma_value,time): # 形状、尺度、位置、時間
r_core = ((time - gamma_value)/eta_value) ** m_value
y_value = math.exp(-r_core)
return y_value
# 各グラフのパラメータを関数(グラフ用データ)に渡して、描画
R_ylist = []
for graph in graph_list:
x_data = xylist(R_weibull,graph[0],graph[1],graph[2],graph[3],graph[4])[0]
y_data = xylist(R_weibull,graph[0],graph[1],graph[2],graph[3],graph[4])[1]
plt.plot(x_data, y_data, linestyle="--")
R_ylist.append(y_data)
# 観測R曲線
R_ylist[2] = np.nan_to_num(R_ylist[2], nan=0) # nan を0に置換
Ry_sums = [x+y+z for (x,y,z) in zip(R_ylist[0], R_ylist[1],R_ylist[2])] # 3データを合計
plt.plot(x_data, Ry_sums, label="Observed Degree of Reliability", color='red', linewidth=2)
# グラフ凡例等
plt.xlim(0,)
plt.ylim(0,)
plt.yticks([])
plt.xlabel('time')
plt.ylabel('R [%]')
plt.legend()
plt.title('Degree of Reliability')
plt.show()
- 初期故障期間に信頼度が強く下がる。
- 偶発故障期間は漸減傾向にある。
- 摩耗故障期間に入ると減少傾向が強まる。
p149 図7.1下図 =p157 図7.6上図 3種類の分布 故障分布f のグラフ
ワイブル故障分布の関数(p151)
\begin{eqnarray*} f(t)&=&k(t)\times R(t)\\&=&\cfrac{m}{\eta}\left(\cfrac{t-\gamma}{\eta}\right)^{m-1} \times e^{-\left( \cfrac{t-\gamma}{\eta}\right)^m}\end{eqnarray*}
を使用する。
# コードは上記の続き
# 関数 信頼度 f (ワイブル)
def F_weibull(m_value,eta_value,gamma_value,time): # 形状、尺度、位置、時間
R_value = math.exp(-(((time - gamma_value)/eta_value) ** m_value))
k_value = (m_value/eta_value) * ((time - gamma_value)/eta_value) ** (m_value -1)
return R_value * k_value
# 各グラフのパラメータを関数(グラフ用データ)に渡して、描画
f_ylists = []
for graph in graph_list:
x_data = xylist(F_weibull, graph[0],graph[1],graph[2],graph[3],graph[4])[0]
y_data = xylist(F_weibull, graph[0],graph[1],graph[2],graph[3],graph[4])[1]
plt.plot(x_data, y_data, linestyle="--")
f_ylists.append(y_data)
# 観測f曲線
f_ylists[2] = np.nan_to_num(f_ylists[2], nan=0) # nan を0に置換
fy_sums = [x+y+z for (x,y,z) in zip(f_ylists[0], f_ylists[1],f_ylists[2])] # 3データを合計
plt.plot(x_data, fy_sums, label="Observed failure rate", color='red', linewidth=2)
# グラフ凡例等
plt.xlim(0,)
plt.ylim(0,5)
plt.yticks([])
plt.xlabel('time')
plt.ylabel('f [%/t]')
plt.legend()
plt.title('f probability distribution')
plt.show()
- 初期故障期間の故障率は高い。
- 偶発故障期間の故障率は低めで安定する。
- 摩耗故障期間の故障率が一時増加するが、残数減に伴い収束する。
p149 =p157 図7.6下図 故障割合F のグラフ
- 信頼度\(R\) の補数として計算。
- 故障分布\(f\) を積分することでも、同じ値が得られる。
# コードは上記の続き
# 観測F曲線
Fy_sums = [Ry_sums[0]-Ry for Ry in Ry_sums] # Rの補数
plt.plot(x_data, Fy_sums, label="Cumulative Failure rate", color='red', linewidth=2)
# グラフ凡例等
plt.xlim(0,)
plt.ylim(0,)
plt.yticks([])
plt.xlabel('time')
plt.ylabel('F [%]')
plt.legend()
plt.title('Failure rate')
plt.show()
p149とp157 の各グラフの位置づけ(=p71 グラフ ① ~ ⑥ の相互関係)
- ① 残存数\(y\)
- ② 新規故障数\(\Delta y\)
- ③ 新規故障の対全体割合(故障の分布)\(f\)
- ④ 故障数の対全体割合\(F\)
- ⑤ 故障数の累計\(\sum \Delta y\)
- ⑥ 残存割合(信頼度)\(R\)
- 新規故障の対残存割合(故障率)\(k\)
残存系①⑥ vs 故障系②③④⑤
- 総数 \(A\) で除する: ①②⑤平面[個数] \(\Longrightarrow\) ⑥③④平面[割合]
- 故障率 \(k\) を乗ずる: ①⑥軸 \(\Longrightarrow\) ②③軸[瞬間故障]
- 補数をとる: ①⑥軸 \(\Longrightarrow\) ⑤④軸[故障累計]
- 微分する: ⑤④軸 \(\Longrightarrow\) ②③軸
p152 図7.3 ワイブル分布の例
# 図7.3
import numpy as np
import math
import matplotlib.pyplot as plt
# 関数(Weibull distribution)
def Weibull(m,eta,gamma,time):
return ((m*(time-gamma)**(m-1))/eta**m) * (math.e)**(-((time-gamma)/eta)**m)
# 関数(時間と故障率)
def Weibul_Data(eta,m,gamma):
time = [] #時間
fr = [] #故障率
for t in np.arange(0,4,0.01):
time.append(t)
WE = Weibull(m,eta,gamma,t)
fr.append(WE)
return time,fr
# パラメータ
m_value = 2 #形状
eta = 1 #尺度(指数分布のMTBFに相当)
gamma = 1 #位置(無故障の期間)
# グラフの描画
time_data = Weibul_Data(eta,m_value,gamma)[0]
fr_data = Weibul_Data(eta,m_value,gamma)[1]
plt.plot(time_data, fr_data,label= f'm={m_value}\neta={eta}\ngamma={gamma}')
plt.xlabel('time')
plt.ylabel('failure rate')
plt.xlim(0,4)
plt.ylim(0,)
plt.yticks([])
plt.legend()
plt.title(f'Weibul')
p153 図7.4 ワイブル分布の例(形状パラメータ m による違い)
# 図7.3
import numpy as np
import math
import matplotlib.pyplot as plt
# 関数(Weibull distribution)
def Weibull(m,eta,gamma,time):
return ((m*(time-gamma)**(m-1))/eta**m) * (math.e)**(-((time-gamma)/eta)**m)
# 関数(時間と故障率)
def Weibul_Data(eta,m,gamma):
time = [] #時間
fr = [] #故障率
for t in np.arange(0,4,0.01):
time.append(t)
WE = Weibull(m,eta,gamma,t)
fr.append(WE)
return time,fr
# パラメータ
m_value = 2 #形状
eta = 1 #尺度(指数分布のMTBFに相当)
gamma = 1 #位置(無故障の期間)
# グラフの描画
time_data = Weibul_Data(eta,m_value,gamma)[0]
fr_data = Weibul_Data(eta,m_value,gamma)[1]
plt.plot(time_data, fr_data,label= f'm={m_value}\neta={eta}\ngamma={gamma}')
plt.xlabel('time')
plt.ylabel('failure rate')
plt.xlim(0,4)
plt.ylim(0,)
plt.yticks([])
plt.legend()
plt.title(f'Weibul')
p160 故障時刻 t と故障割合 F(t)
import pandas as pd t_value = [1, 3, 7, 18] # 故障時刻(横下軸) denominator = len(t_value)+1 #要素数 F_value = [] # 累積故障割合(縦左軸) for item in range(1,denominator): # 要素数繰り返す F_value.append(item/denominator) DF = pd.DataFrame([t_value,F_value]).T DF.columns =['Time','F(t)'] DF
Time F(t) 0 1.0 0.2 1 3.0 0.4 2 7.0 0.6 3 18.0 0.8
p160 図7.7 =p166 図7.10 mと η を求める実例 その1
検査対象が、初期故障・偶発故障・摩耗故障期間のいずれの状態にあるかを判定するため、\(m\) を算出する。
(作業工程)
- ワイブル確率紙の画面を設定する(対数表示によるデータの直線化判定のため)
- 観測値をプロットし、近似直線を描画(直線判定→ワイブル分布と認定)
- 形状パラメータ\(m\) を\(y\)軸切片の負数として取得
- 尺度パラメータ\(\eta\) を\(x\) 軸切片として取得
from matplotlib import pyplot as plt
import matplotlib as mpl
import numpy as np
fig = plt.figure()
ax1 = fig.subplots()
ax2 = ax1.twiny()
ax3 = ax2.twinx()
# 観測値のプロット(X軸Y軸の平面へ)
ax3.scatter(X_value, Y_value, c="red", s =60 ,label="X_Y")
ax3.scatter(1, 0, c="blue", s=60, label="Estimated point of m")
# 近似直線
a_value, b_value = np.polyfit(X_value, Y_value, 1)
X2_value = np.linspace(-2,4)
Y2_value = [a_value * Xs +b_value for Xs in X2_value]
ax3.plot(X2_value, Y2_value, linestyle = '--', color = 'red')
# 座標(1,0)の点m を通る直線 (y-0)=a(x-1)
Y3_value = [a_value * Xs -a_value for Xs in X2_value]
ax3.plot(X2_value, Y3_value, linestyle = '--', color = 'blue')
# 上記直線のy切片
y_intercept = a_value * 0 -a_value # 直線式に x=0 を代入した値
print(f'傾きm= -(切片値):{-round(y_intercept,2)}')
# 近似直線のx切片
x_intercept = -b_value/a_value # 近似式に y=0 を代入した値
tx_intercept = math.exp(x_intercept) # t値に換算
print(f'尺度η=:{round(tx_intercept,2)}')
# t軸、F軸のスケール
ax1.set_xscale('log')
ax1.yaxis.set_ticks([])
# X軸、Y軸のスケール
ax3.set_xscale('linear')
ax3.set_yscale('linear')
# 目盛り
ax1.set_xlim(0.1, 100)
ax3.set_xlim(-2, 4)
ax3.set_ylim(-7, 2)
# 軸名
ax1.set_xlabel('t [ln]')
ax1.set_ylabel('F [lnln]')
ax2.set_xlabel(r'$X=ln(t)$')
ax3.set_ylabel(r'$Y=lnln\left(\frac{1}{1-F}\right)$')
# X軸、Y軸
ax2.axvline(x=0, color='black')
ax3.axhline(y=0, color='black')
# 補助線
ax1.grid()
ax2.grid()
ax3.grid()
# 凡例
h1, l1 = ax1.get_legend_handles_labels()
h3, l3 = ax3.get_legend_handles_labels()
ax1.legend(h1 + h3, l1 + l3, loc='right')
plt.show()
傾きm= -(切片値):0.69 尺度η=:8.45
p162 図7.8 mを求める実例(その2)
import pandas as pd
import numpy as np
import math
from matplotlib import pyplot as plt
import matplotlib as mpl
t_value = [5, 7, 9, 11, 14] # 故障経過日(横下軸)
denominator = len(t_value)+1 #要素数
F_value = [] # 累積故障割合(縦左軸)
for item in range(1,denominator): # 要素数繰り返す
F_value.append(item/denominator)
F_per = [round(Fs*100,1) for Fs in F_value]
DF = pd.DataFrame([t_value, F_per]).T
DF.columns =['Time [Days]','F(t) [%]']
display(DF)
X_value = [round(math.log(t),2) for t in t_value] # 横上軸
Y_value = [round(math.log(math.log(1/(1-F))),2) for F in F_value] # 縦右軸
# グラフ
fig = plt.figure()
ax1 = fig.subplots()
ax2 = ax1.twiny()
ax3 = ax2.twinx()
# 観測値のプロット(X軸Y軸の平面へ)
ax3.scatter(X_value, Y_value, c="red", s =60 ,label="X_Y")
ax3.scatter(1, 0, c="blue", s=60, label="Estimated point of m")
# 近似直線
a_value, b_value = np.polyfit(X_value, Y_value, 1)
X2_value = np.linspace(-2,4)
Y2_value = [a_value * Xs +b_value for Xs in X2_value]
ax3.plot(X2_value, Y2_value, linestyle = '--', color = 'red')
# 座標(1,0)の点m を通る直線 (y-0)=a(x-1)
Y3_value = [a_value * Xs -a_value for Xs in X2_value]
ax3.plot(X2_value, Y3_value, linestyle = '--', color = 'blue')
# 上記直線のy切片
intercept = a_value * 0 -a_value # 直線式に x=0 を代入した値
print(f'傾きm= -(切片値):{-round(intercept,2)}')
# t軸、F軸のスケール
ax1.set_xscale('log')
ax1.yaxis.set_ticks([])
# X軸、Y軸のスケール
ax3.set_xscale('linear')
ax3.set_yscale('linear')
# 目盛り
ax1.set_xlim(0.1, 100)
ax3.set_xlim(-2, 4)
ax3.set_ylim(-7, 2)
# 軸名
ax1.set_xlabel('t [ln]')
ax1.set_ylabel('F [lnln]')
ax2.set_xlabel(r'$X=ln(t)$')
ax3.set_ylabel(r'$Y=lnln\left(\frac{1}{1-F}\right)$')
# X軸、Y軸
ax2.axvline(x=0, color='black')
ax3.axhline(y=0, color='black')
# 補助線
ax1.grid()
ax2.grid()
ax3.grid()
# 凡例
h1, l1 = ax1.get_legend_handles_labels()
h3, l3 = ax3.get_legend_handles_labels()
ax1.legend(h1 + h3, l1 + l3, loc='right')
plt.show()
Time [Days] F(t) [%] 0 5.0 16.7 1 7.0 33.3 2 9.0 50.0 3 11.0 66.7 4 14.0 83.3 傾きm= -(切片値):2.22
p163 表7.1 データが直線に並ばない場合(γ 補正)
観測値をプロットした結果、ただちに近似直線を描画できない場合でも、\(\gamma\) 値が0以外である可能性を探索する。適切な\(\gamma\) 値を全データから減算することで、直線判定できる場合、ワイブル分布と認定する。
(作業工程)
- ワイブル確率紙の画面を設定する
- 観測値をプロットし、近似曲線を描画
- 近似曲線と確率紙底辺との交点を、\(\gamma\) 値候補として抽出
- 同\(\gamma\) 候補値ないしは近似する候補値を、全データから減算する(対数表示画面上の移動距離はデータにより異なる)
- 修正後データを再プロットし、近似直線を描画(直線判定→ワイブル分布と認定)
- 形状パラメータ\(m\) を\(y\) 軸切片の負数として取得
import pandas as pd
import numpy as np
import math
from matplotlib import pyplot as plt
import matplotlib as mpl
from scipy.optimize import curve_fit
t_value = [7, 9, 11, 13, 15, 18, 21, 27, 35] # 故障までの経過回数(横下軸)
denominator = len(t_value)+1 #要素数
F_value = [] # 累積故障割合(縦左軸)
for item in range(1,denominator): # 要素数繰り返す
F_value.append(item/denominator)
F_per = [round(Fs*100,1) for Fs in F_value]
DF = pd.DataFrame([t_value, F_per]).T
DF.columns =['Time [回]','F(t) [%]']
display(DF)
X_value = [math.log(t) for t in t_value] # 横上軸
Y_value = [math.log(math.log(1/(1-F))) for F in F_value] # 縦右軸
# グラフ
fig = plt.figure()
ax1 = fig.subplots()
ax2 = ax1.twiny()
ax3 = ax2.twinx()
# 観測値のプロット(X軸Y軸の平面へ)
ax3.scatter(X_value, Y_value, c="red", s =60 ,label="X_Y")
ax3.scatter(1, 0, c="blue", s=60, label="Estimated point of m")
# 近似直線
a_value, b_value = np.polyfit(X_value, Y_value, 1)
X2_value = np.linspace(-2,4)
Y2_value = [a_value * Xs +b_value for Xs in X2_value]
ax3.plot(X2_value, Y2_value, linestyle = '--', color = 'red')
# 座標(1,0)の点m を通る直線 (y-0)=a(x-1)
Y3_value = [a_value * Xs -a_value for Xs in X2_value]
ax3.plot(X2_value, Y3_value, linestyle = '--', color = 'blue')
# 上記直線のy切片
intercept = a_value * 0 -a_value # 直線式に x=0 を代入した値
print(f'傾きm= -(切片値):{-round(intercept,2)}')
# 近時曲線
def func(x, a, b):
return a + b * np.log(x) # モデル関数
a_pred, b_pred = curve_fit(func, X_value, Y_value)[0] # 近似演算
# 近似曲線の描画
X3_value = np.linspace(0.1,4)
y_pred = func(X3_value, a_pred, b_pred)
ax3.plot(X3_value, y_pred, "orange", linestyle = '--', label=fr"$Y={a_pred:.1f} + {b_pred:.1f} \log X$")
# 上記曲線の y=-7 切片
intercept_x = math.exp ((-7-a_pred)/b_pred) # 曲線式に y=-7 を代入したX値
intercept_t = math.exp(intercept_x) # t値へ変換
print(f'修正値候補:{int(intercept_t)}')
# t軸、F軸のスケール
ax1.set_xscale('log')
ax1.yaxis.set_ticks([])
# X軸、Y軸のスケール
ax3.set_xscale('linear')
ax3.set_yscale('linear')
# 目盛り
ax1.set_xlim(0.1, 100)
ax3.set_xlim(-2, 4)
ax3.set_ylim(-7, 2)
# 軸名
ax1.set_xlabel('t [ln]')
ax1.set_ylabel('F [lnln]')
ax2.set_xlabel(r'$X=ln(t)$')
ax3.set_ylabel(r'$Y=lnln\left(\frac{1}{1-F}\right)$')
# X軸、Y軸
ax2.axvline(x=0, color='black')
ax3.axhline(y=0, color='black')
# 補助線
ax1.grid()
ax2.grid()
ax3.grid()
# 凡例
h1, l1 = ax1.get_legend_handles_labels()
h3, l3 = ax3.get_legend_handles_labels()
ax1.legend(h1 + h3, l1 + l3, loc='lower right')
plt.show()
Time [回] F(t) [%] 0 7.0 10.0 1 9.0 20.0 2 11.0 30.0 3 13.0 40.0 4 15.0 50.0 5 18.0 60.0 6 21.0 70.0 7 27.0 80.0 8 35.0 90.0 傾きm= -(切片値):1.87 修正値候補:2
p164 表7.2 修正した t~F(t) と直線判定
修正候補(\(\gamma=2\))では、なお曲線をとどめていたので、\(\gamma=5\) を採用した。
# コードは上記の続き
t_value_fix = [ts - 5 for ts in t_value] # 修正値5 とすると直線になる
denominator = len(t_value_fix)+1 #要素数
F_value = [] # 累積故障割合(縦左軸)
for item in range(1,denominator): # 要素数繰り返す
F_value.append(item/denominator)
F_per = [round(Fs*100,1) for Fs in F_value]
DF = pd.DataFrame([t_value_fix, F_per]).T
DF.columns =['Time [回]','F(t) [%]']
display(DF)
XNvalue = [round(math.log(t),2) for t in t_value_fix] # 横上軸
Y_value = [round(math.log(math.log(1/(1-F))),2) for F in F_value] # 縦右軸
# グラフ
fig = plt.figure()
ax1 = fig.subplots()
ax2 = ax1.twiny()
ax3 = ax2.twinx()
# 観測値のプロット(X軸Y軸の平面へ)
ax3.scatter(X_value, Y_value, c="red", s =60 ,label="X_Y(original)")
ax3.scatter(XNvalue, Y_value, c="green", s =60 ,label="X_Y(revised)")
ax3.scatter(1, 0, c="blue", s=60, label="Estimated point of m")
# 近似曲線
ax3.plot(X3_value, y_pred, "orange", linestyle = '--', label=fr"$Y={a_pred:.1f} + {b_pred:.1f} \log X$")
# 近似直線
a_value, b_value = np.polyfit(XNvalue, Y_value, 1)
X2_value = np.linspace(-2,4)
Y2_value = [a_value * Xs +b_value for Xs in X2_value]
ax3.plot(X2_value, Y2_value, linestyle = '--', color = 'green')
# 座標(1,0)の点m を通る直線 (y-0)=a(x-1)
Y3_value = [a_value * Xs -a_value for Xs in X2_value]
ax3.plot(X2_value, Y3_value, linestyle = '--', color = 'blue')
# 上記直線のy切片
intercept = a_value * 0 -a_value # 直線式に x=0 を代入した値
print(f'傾きm= -(切片値):{-round(intercept,2)}')
# t軸、F軸のスケール
ax1.set_xscale('log')
ax1.yaxis.set_ticks([])
# X軸、Y軸のスケール
ax3.set_xscale('linear')
ax3.set_yscale('linear')
# 目盛り
ax1.set_xlim(0.1, 100)
ax3.set_xlim(-2, 4)
ax3.set_ylim(-7, 2)
# 軸名
ax1.set_xlabel('t [ln]')
ax1.set_ylabel('F [lnln]')
ax2.set_xlabel(r'$X=ln(t)$')
ax3.set_ylabel(r'$Y=lnln\left(\frac{1}{1-F}\right)$')
# X軸、Y軸
ax2.axvline(x=0, color='black')
ax3.axhline(y=0, color='black')
# 補助線
ax1.grid()
ax2.grid()
ax3.grid()
# 凡例
h1, l1 = ax1.get_legend_handles_labels()
h3, l3 = ax3.get_legend_handles_labels()
ax1.legend(h1 + h3, l1 + l3, loc='lower right')
plt.show()
Time [回] F(t) [%] 0 2.0 10.0 1 4.0 20.0 2 6.0 30.0 3 8.0 40.0 4 10.0 50.0 5 13.0 60.0 6 16.0 70.0 7 22.0 80.0 8 30.0 90.0 傾きm= -(切片値):1.16
p173 検査特性曲線(OC曲線)
(作業工程)
- OC曲線のグラフ用データを生成する関数を設定(引数:標本個数、許容不良品率、演算範囲)
- 標本個数は比較のため複数設定(50個の場合、150個の場合)
- ロット不良率、許容不良率は、共通数値を設定
- OC曲線関数で演算し、グラフ化
- 生産者危険と消費者危険を計算し、表示
import math
from matplotlib import pyplot as plt
# 関数 OC曲線
def OC_curve_n (snumber,percent, xrange): # 標本個数、許容不良品率、横軸演算範囲を入力
LOT_P = [] # ロットの真の不良率(グラフ横軸データ)
Series_LPR = [] # ロットが合格する割合(グラフ縦軸データ)
permissable = int(snumber *percent/100) # 許容不良品個数
for lotp in range(0, xrange*10, 1):
prob = lotp/1000 # 0~0.2 の数値
LOT_P.append(lotp/10) # 0~20 の数値をx軸要素として格納
items = range(0, snumber) # 0個~標本個数
Ps = [] # 個別の事象確率
for r in items: # 標本個数の全場合について
Probability = (snumber*prob)**r/math.factorial(r)*(math.exp(-snumber*prob))
Ps.append(Probability)
Lot_Pass_Rate = 0
for pm in range(0,permissable+1): # 許容不良品個数に至るまで
Lot_Pass_Rate += Ps[pm]*100 # ロットが合格する確率を積算
Series_LPR.append(Lot_Pass_Rate)
return [LOT_P,Series_LPR] # グラフ横軸・縦軸データを戻す
# 関数を使用して演算
xrange =8 # ロット不良率8%まで計算
percent = 2 # 許容不良品率[%]
LDR, LPR_050 = OC_curve_n(50, percent, xrange)
LDR, LPR_150 = OC_curve_n(150, percent, xrange)
# 理想の判定基準
p0 = 1 # ロットを全て合格としてよいロットの真の不良品%
p1 = 5 # ロットを全て不合格としたいロットの真の不良品%
# 生産者危険α
alpha_050 = LPR_050[p0*10]
alpha_150 = LPR_150[p0*10]
# 消費者危険β
beta_050 = LPR_050[p1*10]
beta_150 = LPR_150[p1*10]
#グラフを表示
fig = plt.figure(figsize = (6,4), facecolor='lightgrey')
plt.plot(LDR, LPR_050, color='lightblue', label=f'~1 in 50')
plt.plot(LDR, LPR_150, color='pink', label=f'~3 in 150')
# 表示バッファ
buf = 0.04
# 生産者危険αを表示
plt.vlines(p0,0,alpha_050, linestyle='dotted', color='grey',linewidth=2)
plt.vlines(p0-buf,alpha_050,100, color='blue',linewidth=2, label=fr'$\alpha$')
plt.vlines(p0+buf,alpha_150,100, color='red',linewidth=2, label=fr'$\alpha’$')
plt.hlines(100,0,xrange,color='grey',linewidth=1)
print(f'生産者危険α:{round((100-alpha_050),1)}%')
print(f'生産者危険α’:{round((100-alpha_150),1)}%')
# 消費者危険βを表示
plt.vlines(p1+buf,0,beta_050, color='lightgreen',linewidth=2, label=fr'$\beta$')
plt.vlines(p1-buf,0,beta_150, color='orange',linewidth=2, label=fr'$\beta’$')
print(f'消費者危険β:{round(beta_050,1)}%')
print(f'消費者危険β’:{round(beta_150,1)}%')
plt.title(f"OC curve, Allowable Rate = {percent} %")
plt.xlim(0,xrange)
plt.ylim(0,)
plt.xlabel('Defective Product Rate in Lot [%]')
plt.ylabel('Lot Pass Rate [%]')
plt.legend(loc = 'right')
plt.show()
生産者危険α:9.0% 生産者危険α’:6.6% 消費者危険β:28.7% 消費者危険β’:5.9%
p174 表7.3 JIS Z 9002
同表の \(p_0 = 0.901~1.12\)% に記載の抜取個数 \(n\) と合格判定基準数 \(c\) に対応する生産者リスク \(\alpha\) と消費者リスク \(\beta\) を試算した結果。
import pandas as pd
import math
from decimal import Decimal
# 数表データ
p1col = pd.DataFrame([3.55,4.50,5.6,7.1,9,11.2,14]) # p1上限
p1col_under = pd.DataFrame([2.81,3.56,4.51,5.61,7.11,9.01,11.3]) # p1下限
p0901n = pd.DataFrame([300,200,120,80,60,40,30]) # 表7.3 標本数(0.901~1.12行)
p0901c = pd.DataFrame([6,4,3,2,2,1,1]) # 表7.3 許容不良品数(0.901~1.12行)
DF_p0901 = pd.concat([p1col, p1col_under, p0901n, p0901c], axis=1).T
DF_p0901.index = ['p1_upper[%]','p1_lower[%]','sumple[個]','clear[個]']
# 関数(ロット不良品率、標本数、許容不良品数)→ロット合格率、不合格率
def RiskRate(prob_per, snumber, allowed):
prob = prob_per/100 # 演算用
defective = range(0, snumber)
Probs = []
for defect in defective:
Probability = Decimal((snumber*prob)**defect)/Decimal(math.factorial(defect))*Decimal((math.e)**(-snumber*prob))
Probs.append(float(Probability))
Lot_Pass_Rate = 0
for pm in range(0,allowed+1):
Lot_Pass_Rate += Probs[pm]
return round(Lot_Pass_Rate*100,1), round(100-Lot_Pass_Rate*100,1)
# 生産者リスク上限の行を追加
supplier_risk = []
for i in DF_p0901.columns:
supplier_risk.append(RiskRate(1.12,int(DF_p0901[i][2]),int(DF_p0901[i][3]))[1])
DF_p0901.loc["α_upper[%]"] = supplier_risk
# 生産者リスク下限の行を追加
supplier_risk = []
for i in DF_p0901.columns:
supplier_risk.append(RiskRate(0.901,int(DF_p0901[i][2]),int(DF_p0901[i][3]))[1])
DF_p0901.loc["α_lower[%]"] = supplier_risk
# 消費者リスク上限の行を追加
user_risk = []
for j in DF_p0901.columns:
user_risk.append(RiskRate(DF_p0901[j][1],int(DF_p0901[j][2]),int(DF_p0901[j][3]))[0])
DF_p0901.loc["β_upper[%]"] = user_risk
# 消費者リスク下限の行を追加
user_risk = []
for j in DF_p0901.columns:
user_risk.append(RiskRate(DF_p0901[j][0],int(DF_p0901[j][2]),int(DF_p0901[j][3]))[0])
DF_p0901.loc["β_lower[%]"] = user_risk
DF_p0901
p174 表7.3 抜取個数 n と合否判定基準個数 c(理論値)
- \(p_0\):合格水準のロット不良率
- \(p_1\):不合格水準のロット不良率
- \(\alpha\):生産者危険
- \(\beta\):消費者危険
- \(n\):サンプル数
- \(c\):合格判定基準個数
- 設定値を入力:\(p_0, p_1, \alpha, \beta\)
- 不良率の判別比を算定:\(p_1/p_0\)
- 判別式に自然数\(c\)を逐次代入し、判別比≧判別式となる\(c\) を取得
- 得られた\(c\) から構成される自由度に対応する\(\chi\) 二乗値から、自然数 \(n\) 値を計算
import math
from scipy.stats import chi2
# 設定値
p0 = float(input('ロット合格水準の不良率_p0[%]:',))/100
p1 = float(input('ロット不合格水準の不良率_p1[%]:',))/100
alpha = float(input('生産者危険_α[%]:',))/100
beta = float(input('消費者危険_β[%]:',))/100
# 関数 c値に対応する判別式の値
def equation(c_value):
return chi2.isf(beta,2*(c_value+1))/chi2.isf(1-alpha,2*(c_value+1))
# c値 (判別式の値 < 判別比率 となる count)
dratio = p1/p0 # 判別比
count = 0
while True:
answer = equation(count)
if dratio < answer:
count +=1
else:
break
# n値
number = math.ceil(chi2.isf(beta, 2*(count+1))/(2*p1))
# c値,n値の表示
print(f'サンプル数_n:{number}\n合格判定個数_c:{count}')
ロット合格水準の不良率_p0[%]:1 ロット不合格水準の不良率_p1[%]:8 生産者危険_α[%]:5 消費者危険_β[%]:10 サンプル数_n:67 合格判定個数_c:2
p175 母集団N個から取り出した標本n個が良品である場合、残個が良品である確率
import math
import pandas as pd
# 設定数値
N =10 # 母集団の個数
n = 8 # 標本数
r = 0 # 標本中の不良品数
# 関数 超幾何分布(hypergeometric distribution)
def HGD(N,k,n,r):
return math.comb(k,r)*math.comb(N-k,n-r)/math.comb(N,n)
k_values = [] # 母集団の不良品個数のリスト
p_values = [] # 母集団の不良率のリスト
Prob_values = [] # 合格確率のリスト
for k in range(0,N+1): # 全てのkについて
k_values.append(k) # 母集団中の故障品数 k列を作成
p_values.append(k/N) # 母集団中の故障品比率 p列を作成
Prob_values.append(HGD(N,k,n,r)) # 確率 P列を作成
DF = pd.DataFrame([k_values,p_values,Prob_values],
index=['k_value','p_value','Probability']).T
answer = 1/DF['Probability'].sum() # ベイズの定理
print(f'母集団の不良品率が0の確率:{round(answer*100,1)}%')
DF
母集団の不良品率が0の確率:81.8% k_value p_value Probability 0 0.0 0.0 1.000000 1 1.0 0.1 0.200000 2 2.0 0.2 0.022222 3 3.0 0.3 0.000000 4 4.0 0.4 0.000000 5 5.0 0.5 0.000000 6 6.0 0.6 0.000000 7 7.0 0.7 0.000000 8 8.0 0.8 0.000000 9 9.0 0.9 0.000000 10 10.0 1.0 0.000000
p177 表7.4 定時打切試験による合否判定表
- \(t\):試験時間
- \(k_1\):ロット許容故障率
- \(R_1=e^{-k_1t}\):ロットの信頼度
- \(\beta\):消費者危険
- \(n\):サンプル数
- \(c\):合格判定基準個数
import math
from scipy.special import comb
import pandas as pd
conf = 0.9 # 信頼水準
beta = 1- conf # 消費者危険 式右辺
# 関数 式左辺の値
def Lequ(k1t,num,clear):
R1 = math.exp(-k1t) # 信頼度
left =0
for x in range(clear+1):
left += comb(num, x) *((1-R1)**x) *R1**(num-x)
return left
# 関数 式左側 ≦ beta となるnum を求める
def number(k1t, clear):
num = 0
while Lequ(k1t,num,clear)>beta:
num +=1
return num
# DF化
cnum_list = [0,1,2,3,4] # 合格判定個数
kt_list = [1, 0.5, 0.2, 0.1, 0.05, 0.02, 0.01] # 許容故障率×試験時間
DF = pd.DataFrame(index =cnum_list)
for kt in kt_list:
sn_list = []
for cnum in cnum_list:
sn_list.append(number(kt, cnum))
sn_df = pd.DataFrame([sn_list]).T
DF = pd.concat([DF,sn_df],axis=1)
DF.columns = kt_list
DF













