Rapid prediction of atmospheric pollutant diffusion based on data-driven U-Net model, increasing calculation speed by nearly 6000 times

Background of the project

At present, most common air pollution prediction models are based on physical mechanisms, such as air quality prediction models Calpuff, AERMOD, CMAQ, etc. However, the calculation of these models is relatively complex, the requirements for input data are very high, and the calculation time is relatively long, so they are suitable for forecasting in conventional fixed areas. When encountering a sudden pollution incident, it cannot effectively play its role.

In response to the above problems, this project uses a fixed simulation area with a range of 3km*3km in an urban area, and according to the pollutant diffusion model, quickly calculates the pollutant diffusion animation of any point source of release and any wind direction, and conducts accuracy assessment. Only use the urban local pollutant diffusion cloud image as input, and use the deep learning model to extract the characteristics of pollutant diffusion in the image. It is purely data-driven, does not need to establish a physical model, and the prediction time is short. It is suitable for emergency response decisions in case of sudden pollution diffusion events auxiliary.

project requirements

Topic name

Case study of data-driven deep learning model of pollutant diffusion

Subject requirements

The data set is provided by the external unit. The detailed description of the total data set: 120 animation data (3 wind speeds*5 release source points*8 wind directions). Select the data of any one of the animations, extract the data features based on the data-driven model (the model is not limited), and obtain the pollutant diffusion model, which can predict the pollutant diffusion.

  • project address

https://aistudio.baidu.com/aistudio/projectdetail/5663515

Implementation process

data set

We chose the wind speed of 15m/s, the wind direction is due north, and Pos_0 is used as the animation data of the pollution source release point. The data comes from the CFD simulation results of pollutant diffusion in a fixed area within a range of 3km*3km in an urban area (provided by Nanjing Opatija Company) , a total of 148 pollutant concentration cloud images for 745 seconds, and the time interval between two images is 5 seconds.

Based on the development environment of Flying Paddle 2.4.0, after decompressing the moving picture, we found that among the 181 static pictures obtained after the moving picture decompression, the pictures after the 148th had obvious image shaking. We have adopted the image alignment algorithm based on Harris corner detection, but the image shake has not been completely eliminated. In order to ensure the quality of the input data for the model, we discarded still images after the 148th.

Figure 1 Raw data
insert image description here

Figure 1 Raw data

U-Net network model

The network model is shown in Figure 2, which consists of 3 Encoder/Decoder, 9 convolution Conv, 9 deconvolution Conv-T, about 300,000 training parameters. The reason for choosing U-Net is that the network is widely used in image segmentation and target recognition. Pollutant diffusion pattern learning can be regarded as a dynamic target recognition task, but the shape of the target is relatively abstract; another reason is that The code implementation of U-Net is relatively simple, and the network construction can be completed in a short time.

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-LEHNfl7B-1687247631447)(https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp /99680ddcbcd54560afb36c56f8c13efe~tplv-k3u1fbpfcp-zoom-1.image “wps_doc_3.png”)]

Figure 2 U-Net network diagram

core code

import paddle
import paddle.nn as nn
import paddle.nn.functional as F
from paddle.nn.utils import weight_norm

# 创建基础卷积层
def create_layer(in_channels, out_channels, kernel_size, wn=True, bn=True,
                 activation=nn.ReLU, convolution=nn.Conv2D):
    assert kernel_size % 2 == 1
    layer = [ ]
    conv = convolution(in_channels, out_channels, kernel_size, padding=kernel_size // 2)
    if wn:
        conv = weight_norm(conv)
    layer.append(conv)
    if activation is not None:
        layer.append(activation())
    if bn:
        layer.append(nn.BatchNorm2D(out_channels))
    return nn.Sequential(*layer)

# 创建Encoder中的单个块
def create_encoder_block(in_channels, out_channels, kernel_size, wn=True, bn=True,
                         activation=nn.ReLU, layers=2):
    encoder = [ ]
    for i in range(layers):
        _in = out_channels
        _out = out_channels
        if i == 0:
            _in = in_channels
        encoder.append(create_layer(_in, _out, kernel_size, wn, bn, activation, nn.Conv2D))
    return nn.Sequential(*encoder)

# 创建Decoder中的单个块
def create_decoder_block(in_channels, out_channels, kernel_size, wn=True, bn=True,
                         activation=nn.ReLU, layers=2, final_layer=False):
    decoder = [ ]
    for i in range(layers):
        _in = in_channels
        _out = in_channels
        _bn = bn
        _activation = activation
        if i == 0:
            _in = in_channels * 2
        if i == layers - 1:
            _out = out_channels
            if final_layer:
                _bn = False
                _activation = None
        decoder.append(create_layer(_in, _out, kernel_size, wn, _bn, _activation, nn.Conv2DTranspose))
    return nn.Sequential(*decoder)

# 创建Encoder
def create_encoder(in_channels, filters, kernel_size, wn=True, bn=True, activation=nn.ReLU, layers=2):
    encoder = [ ]
    for i in range(len(filters)):
        if i == 0:
            encoder_layer = create_encoder_block(in_channels, filters[i], kernel_size, wn, bn, activation, layers)
        else:
            encoder_layer = create_encoder_block(filters[i - 1], filters[i], kernel_size, wn, bn, activation, layers)
        encoder = encoder + [encoder_layer]
    return nn.Sequential(*encoder)

# 创建Decoder
def create_decoder(out_channels, filters, kernel_size, wn=True, bn=True, activation=nn.ReLU, layers=2):
    decoder = []
    for i in range(len(filters)):
        if i == 0:
            decoder_layer = create_decoder_block(filters[i], out_channels, kernel_size, wn, bn, activation, layers,
                                                 final_layer=True)
        else:
            decoder_layer = create_decoder_block(filters[i], filters[i - 1], kernel_size, wn, bn, activation, layers,
                                                 final_layer=False)
        decoder = [decoder_layer] + decoder
    return nn.Sequential(*decoder)

# 创建网络
class UNetEx(nn.Layer):
    def __init__(self, in_channels, out_channels, kernel_size=3, filters=[16, 32, 64], layers=3,
                 weight_norm=True, batch_norm=True, activation=nn.ReLU, final_activation=None):
        super().__init__()
        assert len(filters) > 0
        self.final_activation = final_activation
        self.encoder = create_encoder(in_channels, filters, kernel_size, weight_norm, batch_norm, activation, layers)
        decoders = [ ]
        # for i in range(out_channels):
        decoders.append(create_decoder(out_channels, filters, kernel_size, weight_norm, batch_norm, activation, layers))
        self.decoders = nn.Sequential(*decoders)

    def encode(self, x):
        tensors = [ ]
        indices = [ ]
        sizes = [ ]
        for encoder in self.encoder:
            x = encoder(x)
            sizes.append(x.shape)
            tensors.append(x)
            x, ind = F.max_pool2d(x, 2, 2, return_mask=True)
            indices.append(ind)
        return x, tensors, indices, sizes

    def decode(self, _x, _tensors, _indices, _sizes):
        y = [ ]
        for _decoder in self.decoders:
            x = _x
            tensors = _tensors[:]
            indices = _indices[:]
            sizes = _sizes[:]
            for decoder in _decoder:
                tensor = tensors.pop()
                size = sizes.pop()
                ind = indices.pop()
                # 反池化操作,为上采样
                x = F.max_unpool2d(x, ind, 2, 2, output_size=size)
                x = paddle.concat([tensor, x], axis=1)
                x = decoder(x)
            y.append(x)
        return paddle.concat(y, axis=1)

    def forward(self, x):
        x, tensors, indices, sizes = self.encode(x)
        x = self.decode(x, tensors, indices, sizes)
        if self.final_activation is not None:
            x = self.final_activation(x)
        return x

train

The input data during training is the pollutant cloud image at the previous moment, and the output is the predicted pollutant cloud image at the next moment. The current training batch-size is 1, that is, only predicting the pollutant diffusion at the next moment. During training, the model is saved every 10 epochs to prevent loss of model parameters when training is interrupted unexpectedly.

# 训练方法
def train(model, train_dataset, criterion, optimizer, device, num_epochs):
    loss_history = [ ]
    epoch_loss = 0
# 遍历批次
    for epoch in range(num_epochs):
        optimizer.clear_grad()
        for batch_id in range(len(train_dataset)-1):
            inputs = train_dataset[batch_id]
            outputs_true = train_dataset[batch_id+1]

            inputs = T.ToTensor()(inputs)
            inputs = paddle.unsqueeze(inputs, 0)
            outputs_true = T.ToTensor()(outputs_true)
            outputs_true = paddle.unsqueeze(outputs_true, 0)

# 训练
            outputs = model(inputs)
# 计算损失值
            loss = criterion(outputs, outputs_true)
            if batch_id % 10 ==0:
                print('epoch:',epoch,'batch_id:',batch_id,'loss:',loss.numpy())
            loss.backward()

            epoch_loss += loss.item()
        optimizer.step()
        epoch_loss /= len(train_dataset)


        loss_history.append(epoch_loss)
        print("Epoch [{}/{}], Loss: {:.8f}".format(epoch + 1, num_epochs, loss.numpy()[0]))

    # 保存模型
        if epoch % 10 == 0:
            save_model(model, '/home/aistudio/pollution_model.pdparams')

    print("Training complete.")
return loss_history

predict

When predicting, input the pollutant diffusion cloud map of the test data at a certain moment, and predict the pollutant diffusion situation at the next moment. The supervise flag in the test function presets the interface for subsequent continuous prediction of data at multiple times. Currently supervise is set to true, when the model is ready to continuously predict data at multiple times, supervise is set to false during testing.

def test():
    # 初始化结果列表
    results = [ ]

    # 测试集合起始点
    inputs = test_dataset[0]
    inputs = T.ToTensor()(inputs)
    inputs = paddle.unsqueeze(inputs, 0)

    # 是否supervise
    flag_supervise = True

    device = paddle.set_device('gpu' if paddle.is_compiled_with_cuda() else 'cpu')
    # 加载模型
    model = UNetEx(3,3,3)
    load_model(model,'/home/aistudio/pollution_model.pdparams',device)

    for num in range(1,10):

        # 进行预测
        outputs = model(inputs)

        outputs_np = outputs.numpy()
        outputs_np = np.squeeze(outputs_np, axis=0)  # 去除第一个维度(batch_size)
        outputs_np = np.transpose(outputs_np, (1, 2, 0))  # 将通道维度调整为最后一个维度
        outputs_np = (255 * np.clip(outputs_np, 0, 1)).astype('uint8')
        #outputs_np = outputs_np.transpose([1, 2, 0])
        #outputs_np_uint8 = (outputs_np * 255).astype(np.uint8)
        # 将预测结果添加到结果列表中
        results.append(outputs_np)

        if flag_supervise == False:
            # 将预测结果作为下一帧的输入
            inputs = outputs
        else:
            # 使用真实数据预测
            inputs = test_dataset[num+1]
            inputs = T.ToTensor()(inputs)
            inputs = paddle.unsqueeze(inputs, 0)

    return results

results = test()

project outcome

insert image description here
Fig.3 Calculation function loss valueFig.4
insert image description here
Comparison of CFD simulation parameters

insert image description here

Figure 5 Comparison of residual values

As shown in Figure 5, the concentration error is mainly concentrated near the pollution source (as shown in the red box), and the main values ​​are distributed between -0.02 and 0.02. Different colors represent the errors of different concentration intervals. Blue indicates that the relative error of low concentration is small, and green and red indicate that the average error of medium and high concentration errors is relatively high. The green area represents the medium concentration area, and the larger error affects a larger area.

insert image description here

Figure 6 Numerical comparison

Future direction

Aspects of predictive ability

  • Based on the pollutant concentration cloud map at the previous moment, predict the pollutant concentration cloud map at the next ten, twenty, and forty moments;

  • Try to predict multiple instants with multiple instants.

network

  • Try to introduce more advanced network architecture, such as transformer;

  • For the number of network layers and the number of neurons in each layer of the network, try to conduct sensitivity analysis and error analysis;

  • Try to introduce more types of activation functions such as tanh, silu, etc.;

  • Try to adjust the hyperparameters such as learning rate and batch size.

Physical principles

  • Try to introduce physical prior knowledge and impose loss soft constraints on buildings and boundary positions;

  • Attempt to modify the model using the fluid NS equations.

model aspect

  • Try to introduce more parameters as input: such as the location of pollution sources, the initial concentration of pollution sources, etc. to improve the adaptability of the model;

  • Increase the magnitude of model parameters and explore the ability of large models to deal with complex polymorphic problems;

  • Try to integrate with traditional fluid solution methods.

Project significance and experience

This project tries to use the U-Net network to learn the model parameters of pollutant diffusion through the cloud image of pollutant diffusion, and quickly predict the diffusion of pollutants. It is an exploration of the expansion of data-driven computing scenarios. Judging from the project results, the calculation speed of the model is significantly improved compared with the CFD simulation, but the effect of the model prediction still needs to be improved. In the future, we will continue to optimize the model prediction effect by exploring the above directions. During the implementation of the project, we spent a lot of time processing images with jittery backgrounds, until later we found that the quality of some data sets was much better than the other, and we chose to discard the data with poor quality, thus speeding up the progress of the project .

The data processing process has the following experience.

First , the data of the project should be explored globally at the first time to understand the overall picture of the data and evaluate the quality of the data;

Second , instead of spending a lot of time processing poor-quality data, it is better to use better-quality data first, and give priority to things that are more critical to the progress of the model;

Third , improving the quality of the input data has a more positive effect on the training results of the model than changing the structure of the model. The reason why the effects of some open source models cannot be reproduced is that the training data is not public. Even if everyone uses the same structure of the network, but the training data is different, the effect of the model is very different. From this perspective, the model parameters are the compressed information left by the training data on the network, and the flaws in the training data are difficult to solve by optimizing the network.

The Flying Paddle AI for Science co-creation plan provided strong technical support for this project, creating an active and forward-looking AI for Science open source community. Through the Flying Paddle AI for Science co-creation plan, I learned how to use science on the Flying Paddle platform Computational AI methods solve the problem of CFD simulation prediction and greatly increase the speed of data-driven calculations. It is believed that in the future, more and more projects will establish a closed loop of industry-university-research through the AI ​​for Science co-creation plan to promote scientific research innovation and industrial empowerment.

relevant address

  • Paddle AI for Science co-creation plan

https://www.paddlepaddle.org.cn/science

  • Flying Paddle PPSIG-Science Group

https://www.paddlepaddle.org.cn/specialgroupdetail?id=9

  • PaddleScience tool kit

https://github.com/PaddlePaddle/PaddleScience

Guess you like

Origin blog.csdn.net/PaddlePaddle/article/details/131309087