公卫人

 找回密码
 立即注册

QQ登录

只需一步,快速开始

楼主: baisenes

[经验] 想成为魔法少女吗?来和VBA签订契约吧,浅谈公卫自动化报表。

  [复制链接]
yangshujian520 发表于 2023-5-5 17:42:55 | 显示全部楼层
tsinfneg 发表于 2023-1-27 16:23) G6 e+ e2 L* v/ K6 w
两本入门的书,也足够用了。基本了三到四天就能完全掌握。第一本是本地疫情防控部门数据专班培训用的。第二 ...
) D: G& H  y* Q. Z4 V  C
哪本好入门,鄙人小白
回复

使用道具 举报

rml1981 发表于 2023-5-6 09:16:47 | 显示全部楼层
tsinfneg 发表于 2023-1-27 09:41
' e2 t: f: l4 D$ |6 ~% H* K- L1 Y用python不好吗,一是下一步办公软件都要国产化,python是开源的编程语言,国产操作系统完全支持;二是可以 ...
  C9 A0 o6 {$ [9 y# p. @
N牛人,Python用的这么牛,机器学习这块如何,大神加下好友
回复

使用道具 举报

tsinfneg 发表于 2023-5-17 17:53:13 | 显示全部楼层
rml1981 发表于 2023-5-6 09:16
! F; f! Q' o, E# U& b/ rN牛人,Python用的这么牛,机器学习这块如何,大神加下好友
% P8 r% G! u4 u5 k% E8 n6 K+ z2 `
机器学习我试过keras,目前在用pytorch,建议在监测预警工作中试试LSTM(长短期记忆模型),可以较好的对时间序列建模,并进行预测。
回复

使用道具 举报

tsinfneg 发表于 2023-5-17 18:01:12 | 显示全部楼层
本帖最后由 tsinfneg 于 2023-5-17 18:02 编辑
. i  f# i: G0 h9 j2 W; S  D, k/ a% H" e/ _6 c
以下是我为目前工作写的程序中,pytorch神经网络LSTM模型部分的主要代码。
3 f) r# b, F8 l6 d3 a'''torch 机器学习'''* K* [0 R+ ~* T* y" B
# 定义预测
' F( l+ F" I: c4 z' pclass Predict():
/ u: B0 ^* {, Q( J6 i& N     # data 数据列表,n_steps数据分割步长
( V9 w6 h0 `" |3 K5 f     def __init__(self,data,n_steps):7 m* Q( W8 T* p; ]! N* E! B  @
         self.data = data
, f, G7 G; o" K' _( q. S         self.n_steps = n_steps6 v% G& ?! W* Q" h
     
( c$ A& l. B' i6 A0 U  k     # 序列分割,
, g  @8 ?5 R: H0 ]" G9 w     def split_df(self):/ g& K# U- R& I( C
        X, y = list(), list()% j1 X- {+ l  x+ m1 ?, ?$ x
        for i in range(len(self.data)):! |0 f5 x) H* D* A; V3 w
            # 确定最后一个分段
, n0 E$ R' X1 {4 s9 w            end_ix = i + self.n_steps
0 Y+ F% W# |6 A( L4 s# c            # 确定分段结束" J) I. T; F( T9 I
            if end_ix > len(self.data)-1:
* K1 P& K/ s8 z; u                break
1 f; \/ r( g9 t4 i, l3 H/ B- B             # 开始分段,x为分段中各个元素,y为每个分段后的第一个元素* S- h/ F. k0 Y9 N& f0 x# B
            seq_x = self.data[i:end_ix]4 T9 |" N4 G" X/ I% u
            seq_y = self.data[end_ix]& N4 w% n0 ^4 y
            X.append(seq_x)) H* U: v# S& p
            y.append(seq_y)
$ O& |# c3 a) A; q. B        return array(X), array(y)
1 l4 p: n' F$ Q' v& B3 L9 u     & x: o/ x; e6 V
4 ]+ D$ \( e4 W- K; q8 u& {

0 m0 `" R6 R- s- l2 T
7 {; C9 C! y7 s9 {; @# 定义模型) n0 @% n+ O+ W$ ^' h
class LSTM(nn.Module):1 Q; D( u- }2 V
    """/ K& c; t* [+ u  X
     input_dim: 数据的特征数
# D  U$ i: r9 H$ A     hidden_dim:隐藏层神经元个数; e. L+ |' [1 U
     num_layers:LSTM的层数9 ~, A8 s* m0 D; [7 l5 V
     output_dim:预测的特征数    0 R0 ^- U# d) `9 }- [' q; X
    """( f! o; z- o6 W! d  @6 W
    def __init__(self, input_dim,hidden_dim, num_layers, output_dim):6 j! t1 H  m, q2 _& q- p/ ^
        super(LSTM, self).__init__()
, x' u8 r, y2 i7 s        self.input_dim = input_dim
4 }$ W$ L; B% J; t  {        self.hidden_dim = hidden_dim
& v- H% p' \" ~: }        self.num_layers = num_layers
# ?4 ]" C4 u4 {9 ]. A$ a        
; O8 {8 u2 H3 m' w        # 实例化模型,batch_frist = True表明输入格式为(batch, seq_dim, feature_dim)
) _. y5 g: Y9 ]# H% G- n7 y# P* E        self.lstm = nn.LSTM(input_dim, hidden_dim, num_layers, batch_first = True)
2 Z/ r/ `' Z% F4 _' J- O        # 在LSTM后再增加一个全链接层,由于是回归,所以不能在线性层后增加激活函数,作用是加入长短期结果对新结果影响度的权重。& ?9 e6 D* x$ z6 q* r  H
        self.fc = nn.Linear(hidden_dim, output_dim)
  z' U5 x5 t. T+ E2 `, h) ]0 i& a* ~! Q/ ~: ^

5 E% @3 M( }+ K* H8 t    def forward(self, x):
, z9 y% Q" l$ H6 Z        # 初始化的隐藏元和记忆元,通常它们的维度是一样的,设定初始的隐藏层为0,x(0)就是batch_size2 m$ p) n, B( E7 q0 H3 G
        h0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).requires_grad_()& B3 d& k  |2 m
        # $ Q( ~9 X0 s/ @* @5 h
        c0 = torch.zeros(self.num_layers, x.size(0), self.hidden_dim).requires_grad_()
, z: P6 v$ b. L% u$ l/ Y        # hn,cn是所有层最后一个隐藏元和记忆元的输出  ]" v  A8 u. y2 V! x
        out, (hn, cn) = self.lstm(x, (h0.detach(), c0.detach()))$ z# Q$ D  S; }
        # 用全链接层处理
8 g6 c1 W! `& W5 X        out = self.fc(out)2 d! ~7 `" o7 l
        return out
3 }" ^8 b; l( }7 r7 ]# g    / Q4 E% s1 I. T9 @& K6 W
    # 定义对未知的预测方法,x为预测天数。
+ A0 r- l- h: S9 J- f. D    def predict(self,samples,x,model):# Z* F8 I6 O2 M: ~- z" L6 \* x
        # 生成一个空序列用于存放结果
# C9 M" m5 B( X' Y  _1 ?        results = []/ L! q- b3 h/ h: C; {; x
        for i in range(x):# X2 ~4 j9 J3 C

# l; x8 k; C9 p7 _; ~6 J3 W    #       # 使用最后一组数据预测一个新数据
. k1 X1 |# a! W% _! f  N$ R0 ?            result = model(samples[-1].reshape(-1,1,self.input_dim))
- p% G. ?( L7 _1 }" q            # 转换结果格式,方便数据拼接
. s4 T  d! @: P# Y, X            result = result.detach().numpy()[:,-1,0]
# R7 D5 M' j( Y2 v, e! d+ y4 O2 y) d            # 将结果定稿空序列
) F4 f! `( y6 h" B- g: X+ X            results.append(result)8 [) y$ ?% P4 T) o
            # 更改最后一组数据格式,用于拼接4 H  ~% [7 W, L4 S) h- x" ?
            a = samples[-1].detach().numpy()
7 Z2 \6 @. V6 a7 I5 @            a = a.reshape(self.input_dim)
6 r6 z  V1 H  y, v! X9 E            # 取最后一组数据后4个元素,加上新预测的结果,组成新的计算数据6 t& w2 x1 w5 t7 Q8 p
            sample = np.append(a[1:],result)
6 B) U+ @4 O; u6 \; [            # 整理数据格式  T: R, s# M* X6 u+ A1 t
            sample = sample.reshape((1,1,self.input_dim))
" o6 \# L$ S) x- n# u            samples1 = np.concatenate((samples,sample),axis=0)) Y/ c. a" B: `% T! q" e
            samples = torch.from_numpy(samples1)9 w. q5 V. C, ^, v* \: y
            4 L$ h' M- A# D- l% a- b+ k1 L2 V
            # X1 = np.concatenate((samples,sample),axis=0)
6 D) E0 g+ m, Z. J5 W7 T            # D0 _$ \% i% t6 Q5 H, H1 \
        return samples
" g- C/ V" Q% V- L; c    $ |5 D# F4 G: m! j4 w- y# P6 [
# 机器学习数据准备
! ]4 [3 P  y% h# Jdef data_std(df,input_dim):
& t7 m: L; ?2 T1 v. C/ ?5 m5 _    # 数据准备, w2 P9 B' q) O, `
    df1 = df[["检测日期","比例(%)"]]
% n; R( p+ q6 G    #df = df.set_index("检测日期")* v; t* }) v4 m7 \9 w' ], V
    df1["比例(%)"] = df1["比例(%)"].astype(np.float32)
) b( x0 t! f/ m    data = df1["比例(%)"].tolist()
5 d, n0 V, C: U/ e0 I& U    # 按步长划分数据
& `3 b5 T! ?, s2 U: Z    lstm = pytorchlstm.Predict(data,input_dim)
& m/ K; }* a8 }9 R- ?" q, D    X, y = lstm.split_df()
( D/ h2 I% \7 a, E$ f3 D    X = X.astype(np.float32)
, K+ N; X8 d: p9 O% o    y = y.astype(np.float32)' n5 _' H0 X, J
1 h% R' v* H" n4 M
    # 按pytorch要求变换数据格式
- \% D2 T! O2 r' c    X = X.reshape(-1,1,input_dim)
* u. d' M4 b) g3 t9 c    y = y.reshape(-1,1,1)5 B; Q5 U$ C8 _0 x$ h
    X = torch.from_numpy(X)
* l8 }4 [$ o9 j2 p9 s2 F  Y, s6 ?    y = torch.from_numpy(y)
0 S# v% V! n" W8 b0 M+ w6 i6 ]    return X,y3 G, @" R7 \/ V" ^. e

5 @8 @  v9 e: O- O3 F0 E: X% A2 [* j  p5 H$ u
# 模型训练$ U8 C& m$ T7 M' g0 S7 ^
def model_train(X,y,input_dim,hidden_dim, num_layers, output_dim,num_epochs):. v) b3 e; P( D2 Z- l
   
; Q  W2 B2 k- j+ W$ v# I3 T3 {    # 建立损失函数和优化器
' H7 Y* U7 s4 z/ e2 o! S    model = pytorchlstm.LSTM(input_dim,hidden_dim, num_layers, output_dim)
0 H( P/ o6 }) N5 I; ]( f    # 设定loss_fn采用的是均方差" I! o5 o, U# s# X7 E
    loss_fn = nn.MSELoss(reduction='mean')2 T' b  c% H% N8 Z8 z3 w% O0 V
    # 模型的学习率定为0.019 {# Q  g# i; g& a  t
    optimiser = torch.optim.Adam(model.parameters(), lr=0.01)1 f; ^! Y+ A" G0 H% k' V' `  \

' b1 R" x9 v( h0 Y! M/ Y( m$ S
    # 开始训练
% ?  S7 t: T$ t9 N8 |    # 设定一个空列表,用于传入每次循环的偏差
& Q( M  u8 P( D3 D. h* U/ H4 y    hist = np.zeros(num_epochs)) A  |+ u" g$ y) A% d
    for t in range(num_epochs):
) G1 K* d3 d% i2 C5 m& n( T. k. l' M6 c, n            # Initialise hidden state- e# \# i- K( m4 n) u
            # Don't do this if you want your LSTM to be stateful
0 d2 v( Y3 {) ^5 l8 _            # model.hidden = model.init_hidden()- V7 X2 w( C* `/ q* b- e. L4 I5 e
            
7 B- C, ]7 z( A) F" ~1 N            # Forward pass% L) ^. c& g- ~3 Y" p3 A

) R, o' s& V8 A+ L        # 将梯度归零
6 k9 {/ a$ _/ d* M        optimiser.zero_grad()
3 t. i0 f( w- `( L( R7 P  N+ j# e1 F3 p+ u
        # 前向传播计算5 {5 ]* C% h7 M) L
        y_pred = model(X)2 ]2 @4 r' L( J/ L8 m
        # 计算损失偏差,在前面已经设定loss_fn采用的是均方差9 Y: i8 ^9 ~# `8 l( ~* s9 i
        loss = loss_fn(y_pred, y)
& j3 @9 F4 w% i9 F        # 每训练一百次,打印一次均方差
# j" ~& p# ?/ a5 M  T1 |9 k' U        if t % 100 == 0 and t !=0:                  9 O  a6 \4 s$ |3 W! {' y( x
            print("Epoch ", t, "MSE: ", loss.item())" D* N+ J* X' P+ m
        # 将本次循环的均方差的值传入空列表) B; U2 q3 ~. E8 Z& w. q
        hist[t] = loss.item()
2 F0 S$ H/ d4 o5 ?, \5 j# A
" ^- G( |, X) J, y, [        5 {7 g$ t9 P! h6 q& h0 M7 \
        # 将偏差回传,用于调整各层各节点参数3 L0 _  i) |6 l& O
        loss.backward(), k3 U" _- A  x6 c$ ~1 b, m- d9 Y9 P. y
            ' P3 c1 x( d9 }. `! S, C* ^; P
        # 更新权重参数。, L- G; B" t$ n, Q  F
        optimiser.step()
7 X6 g7 p6 m+ J. m. w" L8 P% T5 `# q3 m) X
    # 最终的偏差值
, X! g5 ?9 R0 k% n, _; x, a    loss = loss_fn(y_pred, y).item()7 O. y, C$ S/ r& y; k3 j4 z1 ]
    # plt.plot(range(num_epochs),hist)) l3 e; i4 l/ d+ v; N3 A: {
    # plt.show()) f" ^8 ~" \( S/ `6 Q
    print(loss)
! l+ o- z' {% K/ m) x: i/ P9 o! Z3 w: t2 _* F6 `3 K
    # 保存模型
5 C0 o) I- I$ q6 ?& _; ]    torch.save(model, "model/torch_model0504.pth")  J$ \5 N' }8 }6 i. q& |

+ x  @8 e0 c8 l& e3 e( \, ?8 A# 数据预测
. p% a+ ]  |+ F% m" Y( D6 F* l! R1 idef pred(input_dim,X,y,pre):- M: d/ ]$ V1 M  I( U- ?! c2 ^
    ## 读取模型
: m, q6 G- Q& X' U    model = torch.load('model/torch_model0504.pth')* d3 c6 I% K9 Y8 S
    # 预测. a8 q& x& l  Y6 G# g
    samples = X
. t% z; b8 e$ K" w    # 生成一个空序列用于存放结果
( x3 f$ B# i- t    results = []
# T+ K9 O: K% m+ r5 _    for i in range(pre):! ~3 @7 S4 j. p( R  i
: C0 b  O" W) k% p5 [' @$ [
        # 使用最后一组数据预测一个新数据4 x5 \% b# h8 H8 ?1 C
        result = model(samples[-1].reshape(-1,1,input_dim))
. R- f7 }; s) m        # 转换结果格式,方便数据拼接8 c, E0 ~/ g. P: D( A5 ~
        result = result.detach().numpy()[:,-1,0]. U1 J2 \$ Q6 r1 u) ]7 D: ]
        # 将结果定稿空序列
1 i7 C% t2 {  t; t5 d5 d: j5 [; O        results.append(result)
* v' {# {1 R& f* R# t        # 更改最后一组数据格式,用于拼接  C! ?* e1 [- d
        a = samples[-1].detach().numpy()5 b/ e! V; |1 I8 b. Q1 {2 d
        a = a.reshape(input_dim)8 e9 m6 Z, r! o5 [& i  j8 c2 g
        # 取最后一组数据后4个元素,加上新预测的结果,组成新的计算数据% `3 J- U; g2 I4 z+ X( G
        sample = np.append(a[1:],result)
3 r2 ?. a! s, L- s        # 整理数据格式便于循环输入模型8 a. Z4 N* ~9 u" U* W3 _
        sample = sample.reshape((1,1,input_dim))  f' b) p" s( ?) e9 L, B. o
        samples1 = np.concatenate((samples,sample),axis=0)
, ^& l4 s; f3 D+ R) ^- f        samples = torch.from_numpy(samples1): t. P3 [1 T. l2 a7 ^' t
$ @% Y/ D  S: e2 t- L4 E2 S+ y
& {4 N4 X& I2 Z6 z+ N' F/ p* i
    # 对已有数据进行计算
" W( n$ Y" L+ }2 F    y_pred = model(samples.reshape(-1,1,input_dim))
0 J) g7 k# u4 \7 n) B
2 }, s- W% I' `% P    # 将结果由torch格式转换为numpy格式
2 P9 W; _6 _2 d/ j2 l  a/ y    pred_value = y_pred.detach().numpy()[:,-1,0]2 f+ [# \$ Q1 }
    # 将训练用的y由torch格式转换为numpy格式。方便plt绘图,分析模型质量
3 j) G' R/ i' H6 Z) X    true_value = y.detach().numpy()[:,-1,0] % W' C% l, c+ \* J& k

+ I$ B' j$ J3 T9 U- ?+ G4 Z9 U    # pred_value1 = np.append(pred_value, results)
3 a; f' C: \3 X& S) j
. a$ H" v$ c& L    pred_value1 = pred_value% H6 C0 ]. p7 G, R& o! C; I/ }5 O
    return pred_value1

点评

牛人  发表于 2023-6-1 18:11
回复

使用道具 举报

tsinfneg 发表于 2023-5-17 18:07:52 | 显示全部楼层
本帖最后由 tsinfneg 于 2023-5-17 18:10 编辑
7 }6 |" X8 S' a8 |5 I7 `5 t' q& v# z) z! j/ @7 F) S3 S4 {6 R
入门神书,这一本读完可以应付日常绝大多数工作。但神经网络建模还得再往深的学,因为需要用到面向对象编程。这本书只讲了面向过程编程。
0516.jpg
回复

使用道具 举报

Gohankx 发表于 2023-5-30 10:42:04 | 显示全部楼层
给大佬递茶,我也是苦于繁琐的报表,最近正在探寻自动化
回复

使用道具 举报

EpidemicZzz 发表于 2023-8-29 16:52:06 | 显示全部楼层
这才是精品帖,提高工作效率
回复

使用道具 举报

flymds· 发表于 2023-12-26 17:07:58 | 显示全部楼层
baisenes 发表于 2023-1-27 11:24
5 ~2 ^' R, }3 i0 x疫情管理初期,我曾经尝试过上黑魔法,无奈其他人根本不会用。最后变成我不但要维护一份数据库,还要维护 ...
7 K! t8 z9 e, D8 k$ P8 X' A  \
我也是疫情初学vba,简单的自动化。楼主更是大牛,学习!
回复

使用道具 举报

929769610 发表于 2024-1-9 10:18:07 | 显示全部楼层
无事逛论坛,每天都有新收获
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|会员|至尊|接种|公卫人 ( 沪ICP备06060850号-3 )

GMT+8, 2024-6-24 21:35 , Processed in 0.066044 second(s), 9 queries , Gzip On, MemCached On.

Powered by Discuz! X3.4

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表