CNN or RNN(LSTM)
一、背景
這次項目是導師的一個課題,大概需求是在工廠内,有許多生産裝置,其裝置的産出率與利潤直接挂鈎。是以,保證裝置穩定的高産率是節約成本、提高利潤的重要工作。而通常管理裝置、依照目前狀态,實時調整電壓、電流等各相關指數通常是由專業技術人員負責,培養一個專業調控人員的成本是很高的,是以就需要一個模型能夠代替人工對裝置進行實時相控以保證高産率。
在本次項目裡,目的也是如此。在本項目中,一個值x是人工無法實時測量的,隻能在每次停爐檢查的時候才能人工測量,但在工作時期,x這個值對爐中功率的影響尤其重要,操作人員通常是通過人工經驗評估的方法對其進行評估,并依照經驗對其他量進行調整。由此雖然效果也還行,但也隻是差強人意。
若可以通過其他的可以實時擷取的相關量,間接求出每一個時刻下的此值x,那對于工廠來說,就可以更加科學的進行調控,杜絕了人員犯錯的風險。
資料大概如下所示:

資料中可以看出,特征裡有電壓擋位、電流、功率、及相關參數。
并且,對于我們需要預測出的量x,其并沒有一一對應,幾天才更新一次。并不能把這個x當作标記值y來直接模組化。
每一組資料,大概有60W條左右,預測量的變化僅一次,y的嚴重缺失導緻不能正常的去模組化訓練。是以,通過老師的幫助與提示,将目标放在了另一個可以自定義的參數x2上,借以預測出下一班次的壓放次數x2,來間接預測出實時長度。
x2約八小時重置為0一次,如上圖中,位于中間的部分,将每一段的所有資料作為特征變量,下一段的最高值作為預測值y。
對其進行模組化,利用時序性的特點,将每一段中間約3萬條資料作為時間跨度,去預測下一階段的值。
二、資料預處理
#擷取data1每一段的起點
dots_zero_start = []
for i in range(len(data1)):
if(data1.loc[i, 'Server0.Group1.DS5DJAYF'] == 0):
if(data1.loc[i + 1, 'Server0.Group1.DS5DJAYF'] != 0):
dots_zero_start.append(i)
else:
continue
#根據圖删掉最後一個
del(dots_zero_start[13])
for num in range(len(dots_zero_start)):
time = data1.loc[dots_zero_start[num], 'time']
print(time + '\n')
print('起點一共有: ', len(dots_zero_start), '個')
#擷取每一段的尾點
dots_zero_end = []
for i in range(0, (len(data1) - 1)):
if(data1.loc[i, 'Server0.Group1.DS5DJAYF'] != 0):
if(data1.loc[i + 1, 'Server0.Group1.DS5DJAYF'] == 0):
dots_zero_end.append(i)
else:
continue
#根據圖删掉第一個
del(dots_zero_end[0])
for num in range(len(dots_zero_end)):
time = data1.loc[dots_zero_end[num], 'time']
print(time + '\n')
print('起點一共有: ', len(dots_zero_end), '個')
#計算每一段有多少個資料
minus = []
for i in range(len(dots_zero_end)):
m = dots_zero_end[i] - dots_zero_start[i]
minus.append(m)
minus
#取出每一段的所有資料行
x_sets = []
for set_index in range(len(dots_zero_end)):
set_indexs = data1.loc[(dots_zero_start[set_index]) : (dots_zero_end[set_index])]
x_sets.append(set_indexs)
x = x_sets[:-1]
y = [8, 9, 10, 10, 8, 10, 11, 12, 10, 13, 13 ,13]
#擷取data2每一段的尾點
dots_zero_end2 = []
for i in range(0, (len(data2) - 1)):
if(data2.loc[i, 'Server0.Group1.DS5DJAYF'] != 0):
if(data2.loc[i + 1, 'Server0.Group1.DS5DJAYF'] == 0):
dots_zero_end2.append(i)
else:
continue
#根據圖删掉第一個
del(dots_zero_end2[0])
del(dots_zero_end2[4])
del(dots_zero_end2[8])
dots_zero_end2 = dots_zero_end2[:10]
for num in range(len(dots_zero_end2)):
time = data2.loc[dots_zero_end2[num], 'time']
print(time)
print('起點一共有: ', len(dots_zero_end2), '個')
#計算每一段有多少個資料
minus2 = []
for i in range(len(dots_zero_end2)):
m = dots_zero_end2[i] - dots_zero_start2[i]
minus2.append(m)
minus2
#取出每一段的所有資料行
x_sets2 = []
for set_index in range(len(dots_zero_end2)):
set_indexs = data2.loc[(dots_zero_start2[set_index]) : (dots_zero_end2[set_index])]
x_sets2.append(set_indexs)
x2 = x_sets2[:-1]
y2 = [10, 11, 10, 11, 11, 10, 9, 10, 10]
#擷取data3每一段的起點
dots_zero_start3 = []
for i in range(len(data3)):
if(data3.loc[i, 'Server0.Group1.DS5DJAYF'] == 0):
if(data3.loc[i + 1, 'Server0.Group1.DS5DJAYF'] != 0):
dots_zero_start3.append(i)
else:
continue
del(dots_zero_start3[9])
dots_zero_start3 = dots_zero_start3[:16]
#根據圖删掉最後一個
for num in range(len(dots_zero_start3)):
time = data3.loc[dots_zero_start3[num], 'time']
print(time + '\n')
print('起點一共有: ', len(dots_zero_start3), '個')
#擷取data3每一段的尾點
dots_zero_end3 = []
for i in range(0, (len(data3) - 1)):
if(data3.loc[i, 'Server0.Group1.DS5DJAYF'] != 0):
if(data3.loc[i + 1, 'Server0.Group1.DS5DJAYF'] == 0):
dots_zero_end3.append(i)
else:
continue
#根據圖删掉第一個
del(dots_zero_end3[0])
del(dots_zero_end3[9])
dots_zero_end3 = dots_zero_end3[:-5]
for num in range(len(dots_zero_end3)):
time = data3.loc[dots_zero_end3[num], 'time']
print(time)
print('起點一共有: ', len(dots_zero_end3), '個')
#計算每一段有多少個資料
minus3 = []
for i in range(len(dots_zero_end3)):
m = dots_zero_end3[i] - dots_zero_start3[i]
minus3.append(m)
minus3
#取出每一段的所有資料行
x_sets3 = []
for set_index in range(len(dots_zero_end3)):
set_indexs = data3.loc[(dots_zero_start3[set_index]) : (dots_zero_end3[set_index])]
x_sets3.append(set_indexs)
x3 = x_sets3[:-1]
y3 = [10, 12, 12, 12, 12, 10, 11, 10, 9, 7, 7, 8, 9, 9, 6]
x[0].head(1)
去除三個資料組中所有段之後,發現data3的變量順序和其他不同,是以稍微修改一下
#修改x3次序,和x1、x2相同排序方式
for i in range(len(x3)):
DS5_DJC_A = x3[i]['Server0.Group1.DS5_DJC_A']
DS5_DJB_A = x3[i]['Server0.Group1.DS5_DJB_A']
DS5_DJA_A = x3[i]['Server0.Group1.DS5_DJA_A']
DS5DJAYF = x3[i]['Server0.Group1.DS5DJAYF']
DS5DJBYF = x3[i]['Server0.Group1.DS5DJBYF']
DS5DJCYF = x3[i]['Server0.Group1.DS5DJCYF']
DS5_P0 = x3[i]['Server0.Group1.DS5_P0']
DS5_COS = x3[i]['Server0.Group1.DS5_COS']
DS5_PP = x3[i]['Server0.Group1.DS5_PP']
DS5BYQC_D = x3[i]['Server0.Group1.DS5BYQC_D']
DS5BYQB_D = x3[i]['Server0.Group1.DS5BYQB_D']
DS5BYQA_D = x3[i]['Server0.Group1.DS5BYQA_D']
DS1BY11 = x3[i]['Server0.Group1.DS1BY11']
DS1BY10 = x3[i]['Server0.Group1.DS1BY10']
DS1BY09 = x3[i]['Server0.Group1.DS1BY09']
DS1DJ3_P = x3[i]['Server0.Group1.DS1DJ3_P']
DS1DJ2_P = x3[i]['Server0.Group1.DS1DJ2_P']
DS1DJ1_P = x3[i]['Server0.Group1.DS1DJ1_P']
a = pd.DataFrame()
a = pd.concat([a,DS5_DJC_A], axis = 1)
a = pd.concat([a,DS5_DJB_A], axis = 1)
a = pd.concat([a,DS5_DJA_A], axis = 1)
a = pd.concat([a,DS5DJAYF], axis = 1)
a = pd.concat([a,DS5DJBYF], axis = 1)
a = pd.concat([a,DS5DJCYF], axis = 1)
a = pd.concat([a,DS5_P0], axis = 1)
a = pd.concat([a,DS5_COS], axis = 1)
a = pd.concat([a, DS5_PP], axis = 1)
a = pd.concat([a, DS5BYQC_D], axis = 1)
a = pd.concat([a, DS5BYQB_D], axis = 1)
a = pd.concat([a, DS5BYQA_D], axis = 1)
a = pd.concat([a, DS1BY11], axis = 1)
a = pd.concat([a, DS1BY10], axis = 1)
a = pd.concat([a, DS1BY09], axis = 1)
a = pd.concat([a, DS1DJ3_P], axis = 1)
a = pd.concat([a, DS1DJ2_P], axis = 1)
a = pd.concat([a, DS1DJ1_P], axis = 1)
x3[i] = a
這裡有點智障了,腦子昏昏的,不想去編函數處理,看變量數量也不對,幹脆就直接暴力的轉順序。。。
for i in range(len(x)):
x[i] = x[i].drop(columns = ['time', 'Server0.Group4.NET50', 'Server0.Group4.NET51', 'Server0.Group4.NET52', 'Server0.Group4.NET53', 'Server0.Group4.NET54', 'Server0.Group4.NET55'])
for i in range(len(x2)):
x2[i] = x2[i].drop(columns = ['time', 'Server0.Group4.NET50', 'Server0.Group4.NET51', 'Server0.Group4.NET52', 'Server0.Group4.NET53', 'Server0.Group4.NET54', 'Server0.Group4.NET55'])
for i in range(len(x3)):
x3[i] = x3[i].drop(columns = ['time', 'Server0.Group4.NET50', 'Server0.Group4.NET51', 'Server0.Group4.NET52', 'Server0.Group4.NET53', 'Server0.Group4.NET54', 'Server0.Group4.NET55'])
這裡把無關變量删去,那些都是不能實時變化的值
然後現在存在一個問題就是,每一段之間的資料量并不一樣,是以如果想利用lstm或者cnn進行模組化,需要對其做個處理。
大概有倆種思路:
一種是,将每一段的中位數、方差、平均數取出來,成一個3*18的矩陣作為輸入。最終為n * 3 * 18的三維資料。
另一種是,幹脆将所有資料擴充為30000 * 18的矩陣,對不滿30000的,将中位數進行填充項,填滿。
個人最後是采取了後者,因為想着每一段資料基本都是2萬7千條左右,如果僅僅合并為3條,對特征的壓縮抽象太嚴重了,不能很好的利用已有的大批量資料。
代碼如下:
#填補data1所有資料
for index in range(len(x)):
mean = (pd.DataFrame(x[index].mean())).T
print('現在處理的是',index ,'段' + '/n')
if len(x[index]) < 30000:
for i in range(30000 - len(x[index])):
x[index] = x[index].append(mean)
print('增加',i,'個')
#填補data2所有資料
for index in range(len(x2)):
mean = (pd.DataFrame(x2[index].mean())).T
print('現在處理的是',index ,'段' + '/n')
if len(x2[index]) < 30000:
for i in range(30000 - len(x2[index])):
x2[index] = x2[index].append(mean)
print('增加',i,'個')
#填補data3所有資料
for index in range(len(x3)):
mean = (pd.DataFrame(x3[index].mean())).T
print('現在處理的是',index ,'段' + '/n')
if len(x3[index]) < 30000:
for i in range(30000 - len(x3[index])):
x3[index] = x3[index].append(mean)
print('增加',i,'個')
X = x[0]
for i in range(1, len(x)):
X = pd.concat([X, x[i]], ignore_index=True)
for i in range(len(x2)):
X = pd.concat([X, x2[i]], ignore_index=True)
for i in range(len(x3)):
X = pd.concat([X, x3[i]], ignore_index=True)
填充完以後,将三個data中的所有資料,拼接在一起,作為X,便于後續操作。
mms = MinMaxScaler()
X1 = mms.fit_transform(X1)
因為資料的各變量量綱不同,是以需要做歸一化處理,對其最大最小規範化。
X_all = X1.reshape(36, 30000,17 )
因為三個data中,最終整理出來了36段含有y的資料段,是以,reshape一下
for i in range(len(y2)):
y.append(y2[i])
for i in range(len(y3)):
y.append(y3[i])
y
将y也拼湊一下
二、模組化
這裡分成了倆個部分,第一個是使用了CNN進行模組化,經過基本調參後得到:
model_cnn = Sequential()
model_cnn.add(Conv1D(input_shape = (30000,17),filters=50,kernel_size=3, padding='valid', activation='sigmoid',strides=1))
model_cnn.add(GlobalMaxPool1D())
model_cnn.add(Dense(1))
model_cnn.compile(loss='mean_squared_error', optimizer = 'adam', metrics=['mse'])
model_cnn.summary()
# 訓練模型并預測
random_state = np.random.RandomState(0)
# 随機化資料,并劃分訓練資料和測試資料
X_train, X_test, y_train, y_test = train_test_split(X_all, y, test_size=0.3,random_state=0)
model_cnn.fit(X_train, y_train, epochs=1000,batch_size = 1, validation_data=(X_test, y_test))
約在480次時開始穩定,最終訓練集mse為0.5713,測試集mse為1.3890
然後是LSTM,這裡吐槽一下,lstm的速度是真的慢的不行,一個epoch的時間就要470s,晚上睡覺的時候設為200次,第二天中午看,才跑了一半,但看了記錄,發現到了49次的時候就開始穩定了
model_lstm = Sequential()
model_lstm.add(LSTM(len(X_train), input_shape = (30000, 7)))
model_lstm.add(Dense(1))
model_lstm.compile(loss = 'mse', optimizer = 'adam',metrics=['mse'])
最終結果,訓練集mse為2.3719,測試集的mse為3.9893,效果不如卷積的好
以上就是目前的研究現狀,暫時還沒有對資料特征進行建構、相關性檢查删減,後期會繼續嘗試新的資料建構方式。
(資料不便外放,見諒!)