iT邦幫忙

2023 iThome 鐵人賽

DAY 21
0
AI & Data

從Keras框架與數學概念了解機器學習系列 第 21

[從Keras框架與數學概念了解機器學習] - 21. 實例應用-集團銷售資料分析

  • 分享至 

  • xImage
  •  

https://ithelp.ithome.com.tw/upload/images/20230921/20144614i7RhtsGFp7.jpg

經過前20節的文章,了解模型訓練與預測相關運作後,接著實例應用並比較幾種損失函數與optimizer的搭配比較。這邊拿某集團企業的銷售資料訂單來做訓練範例。

資料內容為某年度的業務銷售訂單,每張單客戶可以一次付清或分期給付,每張銷售單號會有對應的申請日期。

訓練目的要讓機器幫忙辨認未來的案件報酬是否相符於此年度的前70%~80%之間的銷售案 ,排除80%以上的極端訂單與70%以下的普通或較差訂單。

因為訂單有很多因素構成,所以利用深度學習來幫忙找出訂單,將找出的訂單單號蒐集後,日後可以由系統調出這些單號來分析。而未來進件的單也可拿來判斷是否為符合報酬區間的案件。如果不是,那就可以調整訂單內容,使其可以趨近報酬範圍,讓業績可以趕上。

隨後也會產生其它的損失函數與optimizer搭配的結果。

步驟如下:

1.首先匯入資料到dataframe:

這邊是由資料庫匯出某年度資料至csv檔,但其實可以直接以python建立DB server連線,下SQL語法來擷取資料。
此用匯出資料來做範例示意。

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd

df = pd.read_csv('20230502052056.csv',
header=0,
names=["單號","date","期數","進貨價","手續費","印花稅",
"營所稅","貨物稅","保險費","特別稅",
"維護費","物品管理費","每期費用",
"銷項稅",
"商品估值","淨收入"]
) 

idf = df.copy()
feature_names = list(idf.columns[:-1])
idf.dropna(inplace=True)

示意範例資料大約有80萬筆以上。
https://ithelp.ithome.com.tw/upload/images/20230921/20144614Q8Cwve5WAv.jpg

2.對資料作前處理,過濾處理不太合理的單子內容,並加上成本欄位;這部分依照資料內容來做處理,可與資料規劃師或系統分析師規劃討論,因各公司業務邏輯來做相關處理,此只是範例說明有做data pre-process。

def generate_cost(row):
    cost = 0;
    if row['期數'] == 1 :
        if row['進貨價'] == 0:
        cost = row['淨收入']
    elif ( abs( abs(row['進貨價']) - abs(row['淨收入']) ) / abs(row['淨收入']) ) <= 0.05 :
        cost = abs( row['淨收入'] )
    else:
        cost = row['進貨價']
        
    return cost
    
    
new_col = 'cost'
columns=idf.columns.tolist()
columns.insert(2, new_col)
idf[new_col] = idf.apply(generate_cost, axis=1)
idf.loc[:, columns]
idf.set_index(["date", "單號"], inplace = True)
idf.dropna()
gpdf= idf.groupby(["date", "單號"]).sum() #將某單案件直接依照index合併起來

def generate_reward(row):
    reward = 0.0
    if abs(row['cost'])>0:
        reward = ( row['淨收入'] ) / abs(row['cost'])
    else:
        reward = 1.0
    return reward
    
new_col = 'reward'
columns=gpdf.columns.tolist()
columns.insert(2, new_col)
gpdf[new_col] = gpdf.apply(generate_reward, axis=1)
gpdf.loc[:, columns]

feature_names = ["進貨價","手續費","印花稅",
"營所稅","貨物稅","保險費","特別稅",
"維護費","物品管理費","每期費用",
"銷項稅",
"商品估值","淨收入"] 

units = len(feature_names)

3.將資料做標準化

from sklearn.preprocessing import StandardScaler

Standard_Scaler = StandardScaler()
data_scaled = Standard_Scaler.fit_transform(gpdf[feature_names]) 
data_scaled = pd.DataFrame(data_scaled, index=gpdf.index, columns=feature_names)
print('data_scaled:',data_scaled)
data_scaled['reward'] = gpdf['reward']
data_scaled.describe()

4.建構模型

from keras import layers
import keras
from keras import optimizers

model = keras.Sequential()
model.add(layers.Dense(units, activation='relu', input_shape=(len(feature_names),))) 
model.add(layers.Dense(1, activation='sigmoid'))

5.設定模型 compiler 參數,損失函數 為 binary_crossentropy,optimizer為 Adam

adam = optimizers.Adam(lr=0.001) 
model.compile(loss='binary_crossentropy', optimizer=adam, metrics = ["accuracy"] )

6.訓練模型,並指定要辨認的資料為報酬率位於 70%~80% 之間的資料

data_scaled_train = data_scaled

Best_ValLoss_Model = keras.callbacks.ModelCheckpoint(filepath="ModelBestLoss",monitor="val_loss") 

historyTrain = model.fit(data_scaled_train[feature_names],
( (data_scaled_train['reward'] >= data_scaled_train['reward'].quantile(0.7)) & (data_scaled_train['reward'] <= data_scaled_train['reward'].quantile(0.8)) )
,
batch_size = 1000, epochs = 1000 , validation_split = 0.1 ,
callbacks = [Best_ValLoss_Model ]
)

7. 將預測結果圖示化

PredictResult = model.predict(data_scaled_train[feature_names])
PredictResult = pd.Series(PredictResult.swapaxes(0, 1)[0], index=data_scaled_train.index)

dfResult = data_scaled_train.copy()
dfResult['PredictResult'] = PredictResult #預測未來哪些業績是幫助提升
dfResult['PredictCategory'] = dfResult['PredictResult'] >= dfResult['PredictResult'].mean()
dfResult = dfResult.reset_index()
PredictResultMean = dfResult['PredictResult'].mean()

#預測結果觀察
import seaborn as sns
plt.figure(figsize = (20,6))
sns.scatterplot(x='date' , y='reward' , hue = 'PredictCategory' ,  s = 5 , data = dfResult)
plt.show()

此例的 損失函數設定為 binary_crossentropy,optimizer設定adam,其學習率以預設的0.001 來操作,模型訓練時 batch size 為 1000, epoch 設定為 1000。

產生以下結果:

A. 損失值的變化,紅色為訓練資料,藍色為測試資料。
https://ithelp.ithome.com.tw/upload/images/20230921/20144614J8eCFFrHaZ.png

B. 橫軸為日期訂單編號,縱軸為報酬率,黃色為80萬筆資料中報酬率前 70%~80% 的資料
https://ithelp.ithome.com.tw/upload/images/20230921/20144614CGGPrFdfNv.png

C. 觀察訓練準確率達0.99以上
https://ithelp.ithome.com.tw/upload/images/20230921/20144614teL0TvDEGm.png

D. 紅色為預測報酬為前 70%~80% 的資料平均報酬 ,對上藍色非預測出的資料平均報酬,平均計算為每日計算。
https://ithelp.ithome.com.tw/upload/images/20230921/20144614J7VdzzprsS.png


比較

將步驟5的損失函數與optimizer替換與比較。
https://ithelp.ithome.com.tw/upload/images/20230921/20144614s2BIV09R0d.png

由以下比較結果,可以看出 Binary Focal Crossentropy 搭配 Adam 收斂速度較快,但隨 epoch的增加其實準確率不相上下。

Loss Value 變化 (紅色為訓練資料,藍色為測試資料)
https://ithelp.ithome.com.tw/upload/images/20230921/20144614ol4wKkRUVM.png

預測結果分佈,黃色為80萬筆資料中報酬率前 70%~80% 的資料
https://ithelp.ithome.com.tw/upload/images/20230921/20144614TpOSBgxrpl.png

訓練準確率觀察幾乎都在0.99以上,交叉觀察損失值:
https://ithelp.ithome.com.tw/upload/images/20230921/20144614sX4zMWPoFY.png

透過實例應用與觀察損失函數與optimizer替換時的效果,而其它待交互替換測試的因子如 epoch、batch size、學習率、正規化資料方式、資料訓練分割,與模型建構方式,甚至資料再度經由threshold設定過濾等等,每個步驟階段其實是有很多事情要做,這邊大致是示意應用過程供初步參考。而大致上透過keras運作的內容也於此稍做個小結,之後會是進入到數學概念的章節呼應。


上一篇
[從Keras框架與數學概念了解機器學習] - 20. 使用 callbacks.ModelCheckpoint 求最佳模型
下一篇
[從Keras框架與數學概念了解機器學習] - 22. Model Container框架介面
系列文
從Keras框架與數學概念了解機器學習30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言