尝试让AI学习固体火箭数据
chenghangtian2023/06/28原创 软件综合 IP:江苏

开发者选择生成对抗网络(GAN)学习固体火箭的内弹道数据,目的是尝试让AI生成固体火箭的内弹道数据以供设计参考使用。

数据由warmonkey于2011年3月开源的仿真程序“burnsim”生成:

罗澍在2011年3月开源了固体火箭内弹道计算的m程序,并将其命名为“burnsim”,该程序能够输出固体火箭内弹道的重要参数的图像.png

“burnsim”程序的原作者声明:(程序)已经经过试车检验,可认为计算较准确。

开发者认为:AI设计像火箭一类的工业产品面临的一大问题便是高品质训练数据短缺,在当下(2023年),文本数据和图像数据的获取“几乎没有成本”,因此相关领域在应用机器学习技术之后得到飞速发展。至于工业产品设计,获取数据就很困难了——以被爱好者“做烂”的固体火箭为例,试问哪一个爱好者能够通过实际点火试车获得大量可靠的内弹道数据?在数据获取成本高的情况下,只能考虑使用可靠的仿真程序生成训练使用的数据。

2023.06.20:人工智能“chatgpt”告诉郭龙承:获取探空火箭的设计数据的难度较大,只能通过开源的渠道获取.png

Warmonkey给出的仿真程序是m程序,包含3个m文件:

2023.06.20:罗澍在2011年开发的“burnsim”计算程序有3个m文件.png

机器学习一般使用py程序,为此,开发者使用“XXXXXXXXXXXXXXXp”网站部署的人工智能,将m程序转化为py程序,如图:

2023.06.20:“code.cpz-cjy.top”网站部署了人工智能,可以将m程序转化为py程序.png

这个网站转换程序之后不需要太多修正就能直接运行(py程序依赖的函数库需要手动补全),将绘制图像的代码去除,并对程序进行适当的修正,运行XXXXXXXXXX:

# BurnSim release 1.3
# 固体火箭发动机内弹道仿真器
import math
import numpy as np
from openpyxl import load_workbook

def burnsim_propellant(pressure, propname, argcname):
    if propname == 'KNSU':
        if argcname == 'vc':
            result = 923  # m/s 特征速度
        elif argcname == 'density':
            result = 1.81  # g/cm^3 密度
        elif argcname == 'burnspeed':
            a, n = 8.263, 0.319  # 燃速系数
            result = a * pressure ** n  # 燃速 r = a * pressure ^ n 燃速指数
        elif argcname == 'k':
            result = 1.044  # 比热比
    elif propname == 'KNDX':
        if argcname == 'vc':  # m/s 特征速度
            result = 897  # 891,916
        elif argcname == 'density':
            result = 1.879 * 0.94  # g/cm^3 密度
        elif argcname == 'burnspeed':
            if pressure < 0.779:  # 0.1MPa以下按此估算
                a, n = 8.875, 0.619  # 燃速系数
            elif pressure < 2.572:
                a, n = 7.553, -0.009  # 燃速系数
            elif pressure < 5.930:
                a, n = 3.841, 0.688  # 燃速系数
            elif pressure < 8.502:
                a, n = 17.20, -0.148  # 燃速系数
            else:  # 11.50MPa以上按此估算
                a, n = 4.775, 0.442  # 燃速系数
            result = a * pressure ** n  # 燃速
        elif argcname == 'k':
            result = 1.043  # 比热比
    elif propname == 'KNSB':
        if argcname == 'vc':  # m/s 特征速度
            result = 914
        elif argcname == 'density':
            result = 1.78  # g/cm^3 密度
        elif argcname == 'burnspeed':
            if pressure < 0.807:  # 0.1MPa以下按此估算
                a, n = 10.708, 0.625  # 燃速系数
            elif pressure < 1.503:
                a, n = 8.763, -0.314  # 燃速系数
            elif pressure < 3.792:
                a, n = 7.852, -0.013  # 燃速系数
            elif pressure < 7.033:
                a, n = 3.907, 0.535  # 燃速系数
            else:  # 10.67MPa以上按此估算
                a, n = 9.653, 0.064  # 燃速系数
            result = a * pressure ** n  # 燃速
        elif argcname == 'k':
            result = 1.042  # 比热比
    # 此处添加新燃料
    return result
def burnsim(prop,d_nozzle_begin,D_outer,d_hole,L):
    solution_name='dataset'   #设计方案名称
#    d_nozzle_begin=20  #喷喉初始直径,单位毫米
    nozzle_burn_speed=0   #喷管烧蚀速率
#    args = parser.parse_args()


#    d_hole = [8]  # mm 药柱内孔径
#    D_outer = 45  # mm 药柱外径
    N = 5  # 药柱能够燃烧的横断面数
#    L = [300]  # mm 药柱可燃部分长度
#    prop = 'KNDX'  # 推进剂名称
    ap = 0.1  # MPa 大气压
    n = 0.85  # 喷管效率
    g = 9.8  # m/s^2 重力加速度

    # 初始值 单位
    pi = math.pi  # 圆周率
    d_nozzle = [d_nozzle_begin]  # mm
    r = [burnsim_propellant(ap, prop, 'burnspeed')]  # mm/s
    V_gram = [(D_outer ** 2 - d_hole[0] ** 2) * pi / 4 * L[0] / 1000]  # cm^3
    c = burnsim_propellant(0, prop, 'vc')  # m/s
    de = burnsim_propellant(0, prop, 'density')  # g/cm^3
    k = burnsim_propellant(0, prop, 'k')  # 比热比
    I = 0  # N*s
    t = 0  # s
    dt = 0.001  # s 分析时间片长度,数值小精度高,数值大需要内存少,修改后注意要更改图像的X坐标名称
    
    i = 1  # 循环计数
    while V_gram[i - 1] > 0:
        # 计算公式 得数含义 单位
        Ae = d_nozzle[i - 1] ** 2 * pi / 4  # 当前喷管直径 mm^2
        S_burn = (D_outer ** 2 - d_hole[i - 1] ** 2) * pi / 4 * N + d_hole[i - 1] * pi * L[i - 1]  # 当前燃烧面积 mm^2
        Kn = S_burn / Ae  # 喷燃比
        P = Kn * r[i - 1] * c * de / 1e6  # 压力 MPa
        r.append(burnsim_propellant(P, prop, 'burnspeed'))  # 当前燃速 mm/s
        k_thrust = n * abs((2 * k ** 2 / (k - 1) * (2 / (k + 1)) ** ((k + 1) / (k - 1))) ** 0.5 * (1 - (ap / P) ** ((k - 1) / k)))  # 当前推力系数
        F = k_thrust * Ae * P  # 推力
        I += F * dt  # 总冲
        d_hole.append(d_hole[i - 1] + 2 * r[i] * dt)  # 下一时刻的药柱内孔径 mm
        L.append(L[i - 1] - N * dt * r[i])  # 下一时刻的药柱长度 mm
        V_gram.append((D_outer ** 2 - d_hole[i] ** 2) * pi / 4 * L[i] / 1000)  # 下一时刻的药柱体积 cm^3
        d_nozzle.append(d_nozzle[i - 1] + 2 * nozzle_burn_speed * dt)  # 下一时刻的喷管内径 mm
    
        i += 1
        t += dt

    Isp = I / 9.8 / V_gram[0] / de * 1000  # 比冲 单位为秒
    F_avg = I / t  # 平均推力
    M_propellant = V_gram[0] * de  # 药柱质量 单位为g
    data=[Ae,S_burn,Kn,P,k_thrust,F,I,Isp,F_avg,M_propellant]
    print(data)
    return data
if __name__ == '__main__':
    prop = 'KNSU'
    d0 = np.linspace(2, 30, 8)
    d1 = np.linspace(35, 50, 8)
    d2 = np.linspace(10, 30, 8)
    d3 = np.linspace(100, 800, 8)
    
    b = []
    
    wb = load_workbook('dataset-KNSU.xlsx')
    sheet = wb.active
    
    # 向excel中写入表头
    sheet['a1'] = '喷管出口面积'
    sheet['b1'] = '燃烧面积'
    sheet['c1'] = '喷燃比'
    sheet['d1'] = '燃烧室压强'
    sheet['e1'] = '推力系数'
    sheet['f1'] = '推力'
    sheet['g1'] = '总冲'
    sheet['h1'] = '比冲'
    sheet['i1'] = '平均推力'
    sheet['j1'] = '药柱质量'
    
    for d00 in d0:
        d_nozzle_begin = d00
        
        for d11 in d1:
            D_outer = d11
            
            for d22 in d2:
                d_hole = [d22]
                
                for d33 in d3:
                    L = [d33]
                    result = burnsim(prop, d_nozzle_begin, D_outer, d_hole, L)
                    b.append(result)
                    
    for bb in b:
        sheet.append(bb)
        
    wb.save('dataset-KNSU.xlsx')
    print("成功写入数据!!!")

自我批评:向excel文件写入生成的数据时只知道嵌套for循环,这样操作增加了程序运行占用的内存空间,不合适。

运行XXXXXXXXXX之后生成一个excel文件“dataset-KNSU.xlsx”;

attachment icon dataset-KNSU.xlsx 505.80KB XLSX 4次下载

将文件内的数组输入给神经网络展开训练,以下为开发者运行的神经网络程序XXXXXX:

import argparse
import numpy as np
import torchvision.transforms as transforms
from torchvision.utils import save_image
from torch.utils.data import DataLoader,TensorDataset
from torchvision import datasets
from torch.autograd import Variable
import pandas as pd
import torch.nn as nn
import torch.nn.functional as F
import torch
from matplotlib import pyplot as plt

parser = argparse.ArgumentParser()
parser.add_argument("--n_epochs", type=int, default=20, help="number of epochs of training")
parser.add_argument("--batch_size", type=int, default=64, help="size of the batches")
parser.add_argument("--lr", type=float, default=0.02, help="adam: learning rate")
parser.add_argument("--b1", type=float, default=0.5, help="adam: decay of first order momentum of gradient")
parser.add_argument("--b2", type=float, default=0.999, help="adam: decay of first order momentum of gradient")
parser.add_argument("--n_cpu", type=int, default=0, help="number of cpu threads to use during batch generation")
parser.add_argument("--latent_dim", type=int, default=10, help="dimensionality of the latent space")
parser.add_argument("--channels", type=int, default=10, help="number of image channels")
parser.add_argument("--sample_interval", type=int, default=40, help="interval betwen image samples")
opt = parser.parse_args(args=[])
print(opt)

#img_shape = (opt.channels,1,1)

cuda =False
class Generator(nn.Module):
    def __init__(self):
        super(Generator, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(opt.latent_dim, 128),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(128, 256),
            nn.BatchNorm1d(256, 0.8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(256, 512),
            nn.BatchNorm1d(512, 0.8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 1024),
            nn.BatchNorm1d(1024, 0.8),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(1024, 1),
            nn.Tanh()
        )

    def forward(self, z):
        img = self.model(z)
        img = img.view(img.size(0), 1)
        return img


class Discriminator(nn.Module):
    def __init__(self):
        super(Discriminator, self).__init__()

        self.model = nn.Sequential(
            nn.Linear(1, 512),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(512, 256),
            nn.LeakyReLU(0.2, inplace=True),
            nn.Linear(256, 10),
            nn.Sigmoid(),
        )

    def forward(self, img):
        img_flat = img.view(img.size(0), -1)
        validity = self.model(img_flat)

        return validity


# Loss function
adversarial_loss = torch.nn.BCELoss()

# Initialize generator and discriminator
generator = Generator()
discriminator = Discriminator()

if cuda:
    generator.cuda()
    discriminator.cuda()
    adversarial_loss.cuda()


# Optimizers
optimizer_G = torch.optim.Adam(generator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))
optimizer_D = torch.optim.Adam(discriminator.parameters(), lr=opt.lr, betas=(opt.b1, opt.b2))

Tensor = torch.cuda.FloatTensor if cuda else torch.FloatTensor

# ----------
#  Training
# ----------
dat_loader = pd.read_excel('dataset-KNSU.xlsx', 'Sheet1', skiprows=1, header=None)
dat=dat_loader.values
get_data =torch.from_numpy(dat)
imgs = torch.tensor(get_data)
#print(imgs.shape,type(imgs))
def plot_curve(data):
    fig = plt.figure()
    plt.plot(range(len(data)), data, color='blue')
    plt.legend(['value'], loc='upper right')
    plt.xlabel('step')
    plt.ylabel('value')
    plt.show()
for epoch in range(opt.n_epochs):
    for im in imgs:
        valid = Variable(Tensor(im.size(0), 10).fill_(1.0), requires_grad=False)
        fake = Variable(Tensor(im.size(0), 10).fill_(0.0), requires_grad=False)
        real_imgs = Variable(im.type(Tensor))
        real_imgs=torch.unsqueeze(real_imgs,dim=1)
   #     print(real_imgs.shape)
        optimizer_G.zero_grad()
        z = Variable(Tensor(np.random.normal(0, 1, (im.shape[0], opt.latent_dim))))
#        print(z.shape)
        gen_imgs = generator(z)
#        print(discriminator(gen_imgs).shape)
        g_loss = adversarial_loss(discriminator(gen_imgs), valid)
        g_loss.backward()
       
        optimizer_G.step()
        optimizer_D.zero_grad()
#        nn.utils.clip_grad_norm(generator.parameters, max_norm=1, norm_type=2)
#        nn.utils.clip_grad_norm(discriminator.parameters, max_norm=1, norm_type=2)
        print(discriminator(real_imgs))
        
        real_imgs_normalized = (real_imgs - real_imgs.min()) / (real_imgs.max() - real_imgs.min())
#        print(real_imgs_normalized)
        real_loss = adversarial_loss(discriminator(real_imgs_normalized), valid)

        fake_loss = adversarial_loss(discriminator(gen_imgs.detach()), fake)
        d_loss = (real_loss + fake_loss) / 2
        d_loss.backward()
        optimizer_D.step()
        print(
                "[Epoch %d/%d] [D loss: %f] [G loss: %f]"
                 % (epoch, opt.n_epochs, d_loss.item(), g_loss.item())
              )

运行上面的程序(运行的硬件环境是英特尔i7-7700CPU,8GB内存,不使用CUDA),得到梯度爆炸的结果:

2023.06.27:生成对抗网络刚开始训练固体火箭内弹道数据时出现梯度爆炸的问题.png

图中在epoch0还没有训练完成的时候,输出的discriminator(real_imgs)出现“NAN”,模型无法收敛,项目暂时停滞。

来自:计算机科学 / 软件综合动手实践:实验报导
10
3
已屏蔽 原因:{{ notice.reason }}已屏蔽
{{notice.noticeContent}}
~~空空如也
chenghangtian作者
1年6个月前 IP:江苏
922202

我个人认为这个项目探索的意义不大——项目的目的是让AI生成的固体火箭内弹道数据,用计算程序完全能够解决问题,没有必要再为此专门设计开发神经网络。我思考这个项目的初衷也是希望探索人工智能和火箭设计结合的方面,但个人思路受限,不能想出很好的实践思路。

引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
qwe
1年6个月前 IP:辽宁
922203

思路没问题,现在的期刊文章经常这么干。提点小意见:

  1. 数据可以保存成csv等文本格式,excel格式效率低下且没必要,过大还有可能出错。

  2. 深度学习建议整个gpu,现在百元级甚至十元级gpu多得是,没必要拿cpu硬干

  3. 直观感觉这个模型不是很复杂,lz的网络好像过于大了,可能是不收敛的原因之一


引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
chenghangtian作者
1年6个月前 IP:江苏
922204
引用qwe发表于2楼的内容
思路没问题,现在的期刊文章经常这么干。提点小意见:数据可以保存成csv等文本格式,excel格式效率...

感谢你的建议。本来我是使用GPU(单张1070)训练的,可无奈程序报错“CUDA error”,我这才把CUDA关闭,只在CPU上运行找原因的。

2023.06.28:使用单张1070显卡训练生成对抗网络,但程序报错.png

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
chenghangtian作者
1年6个月前 IP:江苏
922205

适当缩小神经网络的规模,结果仍然不收敛:

2023.06.28:缩小神经网络的规模之后,程序仍然出现梯度爆炸的现象.png

原因分析:开发者是直接修改生成对抗网络的开源程序(开源程序训练的数据是MNIST数据集,包含正确的数据预处理操作),在数据预处理方面做得不好——训练数据有4096个数组,每个数组有10个元素,分别表示“喷管出口面积”、“燃烧面积”等固体火箭的内弹道参数;4096个数组的前半部分作为训练集,后半部分作为测试集,AI训练的任务就是根据已有的数据生成新的固体火箭内弹道参数。但是开发者没有针对具体的任务预处理数据,以至于出现梯度爆炸现象。

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
warmonkey
1年6个月前 IP:广东
922217

内弹道特性与内孔形状有关系。蛮干不可取,请先分析因果关系。

引用
评论(1)
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
谁叫小明
1年6个月前 IP:广东
922222

本质应该还是让机器自己学习拟合出由十个变量到输出曲线的某个变换关系式,这就不可避免的就是自身的学习误差导致数据不准确。思路是挺新奇的,但是这类工程问题交给确定公式和代码会稳妥一些


引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
chenghangtian作者
1年6个月前 IP:江苏
922224
引用谁叫小明发表于6楼的内容
本质应该还是让机器自己学习拟合出由十个变量到输出曲线的某个变换关系式,这就不可避免的就是自身的学习误...

我也是尝试思考人工智能和火箭技术结合的方面,但火箭技术领域貌似没有太多的问题能交给AI解决

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
chenghangtian作者
1年6个月前 IP:江苏
922225

使用机器学习的方法设计火箭参数在行业内已有先例:

XXXXXXXXXXXXXXXXXXXXXXXXXX/component/content/article/tb/stories/blog/36755

2020.04.23:“TECH BRIEFS”网站刊登:常见的机器学习算法并不能直接用于设计火箭参数,为此开发团队侧重于“嵌入”物理控制方程——利用方程识别结构,并把结构反映在开发的人工智能模型中,这样做模型既保证了预测准确性和灵活性,又不过度依赖训练数据.png

图中的开发团队指出,常见的机器学习算法并不能直接用于设计火箭参数,为此开发团队侧重于“嵌入”物理控制方程——利用方程识别结构,并把结构反映在开发的人工智能模型中,这样做模型既保证了预测准确性和灵活性,又不过度依赖训练数据

引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
MGS
1年5个月前 IP:重庆
922486

支持创新尝试,ai还有很多路子走

引用
评论
1
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论
chenghangtian作者
1年5个月前 IP:江苏
922519
引用MGS发表于9楼的内容
支持创新尝试,ai还有很多路子走

可以做些基础的工作,比如说根据火箭技术的知识微调大语言模型,微调后的模型作为人类工程师的助手

引用
评论
加载评论中,请稍候...
200字以内,仅用于支线交流,主线讨论请采用回复功能。
折叠评论

想参与大家的讨论?现在就 登录 或者 注册

所属专业
所属分类
上级专业
同级专业
chenghangtian
开除学籍
文章
5
回复
51
学术分
0
2022/08/14注册,5个月5天前活动

Artificial Intelligence

主体类型:个人
所属领域:无
认证方式:身份证号
IP归属地:江苏
插入公式
评论控制
加载中...
文号:{{pid}}
投诉或举报
加载中...
{{tip}}
请选择违规类型:
{{reason.type}}

空空如也

加载中...
详情
详情
推送到专栏从专栏移除
设为匿名取消匿名
查看作者
回复
只看作者
加入收藏取消收藏
收藏
取消收藏
折叠回复
置顶取消置顶
评学术分
鼓励
设为精选取消精选
管理提醒
编辑
通过审核
评论控制
退修或删除
历史版本
违规记录
投诉或举报
加入黑名单移除黑名单
查看IP
{{format('YYYY/MM/DD HH:mm:ss', toc)}}