工业化生产预测(xgboost)(笔记版)

news2025/3/1 0:09:04

数据任务概述

任务目标:利用异烟酸生产过程中的各参数,预测最终异烟酸的收率
数据集包括生产工程中10个步骤的参数,样本id、A1-A28、B1-B14包括原料、辅料、时间、温度、压强等以及收率

  • 本项目为回归预测任务
    在这里插入图片描述
    生产各个环节的特征以及相关时间
    部分数据:
    在这里插入图片描述
    特征处理关键: 时间数据如何处理?

数据异常检查

导入工具包

import pandas as pd
import numpy as np
import warnings
import xgboost as xgb
from sklearn.model_selection import KFold
from sklearn.metrics import mean_squared_error as mse

warnings.simplefilter('ignore')

读取数据

一个训练集和两个测试集

df_trn = pd.read_csv(
        'data/jinnan_round1_train_20181227.csv', encoding='GB2312')
df_tst_a = pd.read_csv(
        'data/jinnan_round1_testA_20181227.csv', encoding='GB2312')
df_tst_b = pd.read_csv(
        'data/jinnan_round1_testB_20190121.csv', encoding='GB2312')
df_trn.head()

在这里插入图片描述

df_trn.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 1396 entries, 0 to 1395
Data columns (total 44 columns):
样本id    1396 non-null object
A1      1396 non-null int64
A2      42 non-null float64
A3      1354 non-null float64
A4      1396 non-null int64
A5      1396 non-null object
A6      1396 non-null float64
A7      149 non-null object
A8      149 non-null float64
A9      1396 non-null object
A10     1396 non-null int64
A11     1396 non-null object
A12     1396 non-null int64
A13     1396 non-null float64
A14     1396 non-null object
A15     1396 non-null float64
A16     1396 non-null object
A17     1396 non-null float64
A18     1396 non-null float64
A19     1396 non-null int64
A20     1396 non-null object
A21     1393 non-null float64
A22     1396 non-null float64
A23     1393 non-null float64
A24     1395 non-null object
A25     1396 non-null object
A26     1394 non-null object
A27     1396 non-null int64
A28     1396 non-null object
B1      1386 non-null float64
B2      1394 non-null float64
B3      1394 non-null float64
B4      1396 non-null object
B5      1395 non-null object
B6      1396 non-null int64
B7      1396 non-null object
B8      1395 non-null float64
B9      1396 non-null object
B10     1152 non-null object
B11     547 non-null object
B12     1395 non-null float64
B13     1395 non-null float64
B14     1396 non-null int64
收率      1396 non-null float64
dtypes: float64(18), int64(8), object(18)
memory usage: 480.0+ KB

数据量不多,如果觉得数据不够,可做适当的数据增强

数据检查与问题修正

  • 分析是否有离群点、缺失值等
    可以手动查看数据excel表,分析是否存在问题,比如A5 A9存在部分数据不统一的问题
    也可写脚本判断
    在这里插入图片描述
def train_abnormal_revise(data):
    df_trn = data.copy()  #复制一份
    df_trn.loc[(df_trn['A1'] == 200) & (df_trn['A3'] == 405), 'A1'] = 300
    df_trn['A5'] = df_trn['A5'].replace('1900/1/21 0:00', '21:00:00')
    df_trn['A5'] = df_trn['A5'].replace('1900/1/29 0:00', '14:00:00')
    df_trn['A9'] = df_trn['A9'].replace('1900/1/9 7:00', '23:00:00')
    df_trn['A9'] = df_trn['A9'].replace('700', '7:00:00')
    df_trn['A11'] = df_trn['A11'].replace(':30:00', '00:30:00')
    df_trn['A11'] = df_trn['A11'].replace('1900/1/1 2:30', '21:30:00')
    df_trn['A16'] = df_trn['A16'].replace('1900/1/12 0:00', '12:00:00')
    df_trn['A20'] = df_trn['A20'].replace('6:00-6:30分', '6:00-6:30')
    df_trn['A20'] = df_trn['A20'].replace('18:30-15:00', '18:30-19:00')
    df_trn['A22'] = df_trn['A22'].replace(3.5, np.nan)
    df_trn['A25'] = df_trn['A25'].replace('1900/3/10 0:00', 70).astype(int)
    df_trn['A26'] = df_trn['A26'].replace('1900/3/13 0:00', '13:00:00')
    df_trn['B1'] = df_trn['B1'].replace(3.5, np.nan)
    df_trn['B4'] = df_trn['B4'].replace('15:00-1600', '15:00-16:00')
    df_trn['B4'] = df_trn['B4'].replace('18:00-17:00', '16:00-17:00')
    df_trn['B4'] = df_trn['B4'].replace('19:-20:05', '19:05-20:05')
    df_trn['B9'] = df_trn['B9'].replace('23:00-7:30', '23:00-00:30')
    df_trn['B14'] = df_trn['B14'].replace(40, 400)
    return df_trn


def test_a_abnormal_revise(data):
    df_tst = data.copy()
    df_tst['A5'] = df_tst['A5'].replace('1900/1/22 0:00', '22:00:00')
    df_tst['A7'] = df_tst['A7'].replace('0:50:00', '21:50:00')
    df_tst['B14'] = df_tst['B14'].replace(785, 385)
    return df_tst


def train_abnormal_adjust(data):
    df_trn = data.copy()
    df_trn.loc[df_trn['样本id'] == 'sample_1894', 'A5'] = '14:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1234', 'A9'] = '0:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1020', 'A9'] = '18:30:00'

    df_trn.loc[df_trn['样本id'] == 'sample_1380', 'A11'] = '15:30:00'
    df_trn.loc[df_trn['样本id'] == 'sample_844', 'A11'] = '10:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1348', 'A11'] = '17:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_25', 'A11'] = '00:30:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1105', 'A11'] = '4:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_313', 'A11'] = '15:30:00'

    df_trn.loc[df_trn['样本id'] == 'sample_291', 'A14'] = '19:30:00'

    df_trn.loc[df_trn['样本id'] == 'sample_1398', 'A16'] = '11:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1177', 'A20'] = '19:00-20:00'

    df_trn.loc[df_trn['样本id'] == 'sample_71', 'A20'] = '16:20-16:50'
    df_trn.loc[df_trn['样本id'] == 'sample_14', 'A20'] = '18:00-18:30'
    df_trn.loc[df_trn['样本id'] == 'sample_69', 'A20'] = '6:10-6:50'
    df_trn.loc[df_trn['样本id'] == 'sample_1500', 'A20'] = '23:00-23:30'

    df_trn.loc[df_trn['样本id'] == 'sample_1524', 'A24'] = '15:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1524', 'A26'] = '15:30:00'

    df_trn.loc[df_trn['样本id'] == 'sample_1046', 'A28'] = '18:00-18:30'

    df_trn.loc[df_trn['样本id'] == 'sample_1230', 'B5'] = '17:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_97', 'B7'] = '1:00:00'
    df_trn.loc[df_trn['样本id'] == 'sample_752', 'B9'] = '11:00-14:00'

    df_trn.loc[df_trn['样本id'] == 'sample_609', 'B11'] = '11:00-12:00'
    df_trn.loc[df_trn['样本id'] == 'sample_643', 'B11'] = '12:00-13:00'
    df_trn.loc[df_trn['样本id'] == 'sample_1164', 'B11'] = '5:00-6:00'
    return df_trn


def test_a_abnormal_adjust(data):
    df_tst = data.copy()
    df_tst.loc[df_tst['样本id'] == 'sample_919', 'A9'] = '19:50:00'
    return df_tst


def test_b_abnormal_adjust(data):
    df_tst = data.copy()
    df_tst.loc[df_tst['样本id'] == 'sample_566', 'A5'] = '18:00:00'
    df_tst.loc[df_tst['样本id'] == 'sample_40', 'A20'] = '5:00-5:30'
    df_tst.loc[df_tst['样本id'] == 'sample_531', 'B5'] = '1:00'
    return df_tst
df_trn = train_abnormal_revise(df_trn).pipe(train_abnormal_adjust)
df_tst_a = test_a_abnormal_revise(df_tst_a).pipe(test_a_abnormal_adjust)
df_tst_b = test_b_abnormal_adjust(df_tst_b)

标签与数据集整合

df_trn, df_tst = df_trn.copy(), df_tst_a.copy()
df_target = df_trn['收率']
del df_trn['收率']
df_trn_tst = df_trn.append(df_tst, ignore_index=False).reset_index(
    drop=True)

由于训练集和测试集要进行相同的数据预处理,所以先合并在一起,再分开。

for _df in [df_trn, df_tst, df_trn_tst]:
    _df['A3'] = _df['A3'].fillna(405)  # 众数填充

时间特征提取

# 所有时间相关列
cols_timer = ['A5', 'A7', 'A9', 'A11', 'A14', 'A16', 'A24', 'A26', 'B5', 'B7']
# 同时对训练和测试集进行相同处理
for _df in [df_trn_tst, df_trn, df_tst]:
    # 添加列名标记
    _df.rename(columns={_col: _col + '_t' for _col in cols_timer},
               inplace=True)
    # 遍历所有持续时间相关列例如21:00-21:30
    for _col in ['A20', 'A28', 'B4', 'B9', 'B10', 'B11']:
        # 取到当前列的索引
        _idx_col = _df.columns.tolist().index(_col)
        # 添加新的一列,表示起始时间,split表示分别取开始和结束时间,用索引来指定
        _df.insert(_idx_col + 1, _col + '_at',
                   _df[_col].str.split('-').str[0])
        # 添加新的一列,表示终止时间
        _df.insert(_idx_col + 2, _col + '_bt',
                   _df[_col].str.split('-').str[1])
        # 删除持续时间
        del _df[_col]
        cols_timer = cols_timer + [_col + '_at', _col + '_bt']

如将A20转成多个特征,分解成起始时间 结束时间 时间段

将时间点转换为数值,如转换为分钟单位

在这里插入图片描述
将时间全部转换成分钟形式:

def time_to_min(x):
    if x is np.nan:
        return np.nan
    else:
        x = x.replace(';', ':').replace(';', ':')
        x = x.replace('::', ':').replace('"', ':')
        h, m = x.split(':')[:2]
        h = 0 if not h else h
        m = 0 if not m else m
        return int(h)*60 + int(m)

对所有列执行上面的操作

for _df in [df_trn_tst, df_trn, df_tst]:
    for _col in cols_timer:
        _df[_col] = _df[_col].map(time_to_min)

各道工序特征构建

创建一个id特征来准备添加特征

raw = df_trn_tst.copy()
df = pd.DataFrame(raw['样本id'])
df.head()

温度相关特征

# 加热过程
df['P1_S1_A6_0C'] = raw['A6']  # 容器初始温度
df['P1_S2_A8_1C'] = raw['A8']  # 首次测温温度
df['P1_S3_A10_2C'] = raw['A10']  # 准备水解温度
df['P1_C1_C0_D'] = raw['A8'] - raw['A6']  # 测温温差
df['P1_C2_C0_D'] = raw['A10'] - raw['A6']  # 初次沸腾温差

# 水解过程
df['P2_S1_A12_3C'] = raw['A12']  # 水解开始温度
df['P2_S2_A15_4C'] = raw['A15']  # 水解过程测温温度
df['P2_S3_A17_5C'] = raw['A17']  # 水解结束温度
df['P2_C3_C0_D'] = raw['A12'] - raw['A6']  # 水解开始与初始温度温差
df['P2_C3_C2_D'] = raw['A12'] - raw['A10']  # 水解开始前恒温温差
df['P2_C4_C3_D'] = raw['A15'] - raw['A12']  # 水解过程中途温差
df['P2_C5_C4_D'] = raw['A17'] - raw['A15']  # 水解结束中途温差
df['P2_C5_C3_KD'] = raw['A17'] - raw['A12']  # 水解起止温差

# 脱色过程
df['P3_S2_A25_7C'] = raw['A25']  # 脱色保温开始温度
df['P3_S3_A27_8C'] = raw['A27']  # 脱色保温结束温度
df['P3_C7_C5_D'] = raw['A25'] - raw['A17']  # 降温温差
df['P3_C8_C7_KD'] = raw['A27'] - raw['A25']  # 保温温差

# 结晶过程
df['P4_S2_B6_11C'] = raw['B6']  # 结晶开始温度
df['P4_S3_B8_12C'] = raw['B8']  # 结晶结束温度
df['P4_C11_C8_D'] = raw['B6'] - raw['A27']  # 脱色结束到结晶温差
df['P4_C12_C11_KD'] = raw['B8'] - raw['B6']  # 结晶温差

温度相关统计特征

_funcs = ['mean', 'std', 'sum']
# 遍历每一种统计指标
for _func in _funcs:
    # 对每一个样本计算各项指标
    df[f'P2_C2-C5_{_func}'] = raw[['A10', 'A12', 'A15', 'A17']].\
        agg(_func, axis=1)  # 沸腾过程温度
    df[f'P2_D3-D5_{_func}'] = \
        df[[f'P2_C{i}_C{i-1}_D' for i in range(3, 6)]].\
            abs().agg(_func, axis=1)  # 沸腾过程绝对温差
    df[f'P2_C1-C12_KD_ABS_{_func}'] = \
        df[[_f for _f in df.columns if _f.endswith('KD')]].\
            abs().agg(_func, axis=1)  # 关键过程绝对温差
    df[f'P2_C1-C12_D_{_func}'] = \
        df[[_f for _f in df.columns if _f.endswith('D')]].\
            abs().agg(_func, axis=1)  # 所有过程绝对温差
    df[f'P2_LARGE_KD_{_func}'] = \
        df[['P2_C3_C0_D', 'P3_C7_C5_D', 'P4_C12_C11_KD']].\
            abs().agg(_func, axis=1)  # 大温差绝对温差

设置索引,便于各种特征类别合并

df_temperature = df.set_index('样本id')

时间相关特征

水耗相关特征

合并所有特征

df_feature = pd.concat([df_materials, df_duration, df_temperature, df_interact], axis=1).reset_index()
df_trn = df_feature.iloc[:len(df_trn)].reset_index(drop=True)
df_trn['收率'] = df_target
df_tst = df_feature.iloc[len(df_trn):].reset_index(drop=True)
df_tst['收率'] = np.nan

准备训练数据

筛选常规数据

根据分布,将一些离群点的数据筛掉
在这里插入图片描述

训练xgboost模型

def xgb_cv(train, test, params, fit_params, feature_names, nfold, seed):
    # 创建结果df
    train_pred = pd.DataFrame({
        'id': train['样本id'],
        'true': train['收率'],
        'pred': np.zeros(len(train))})
    # 测试提交结果
    test_pred = pd.DataFrame({'id': test['样本id'], 'pred': np.zeros(len(test))})
    # 交叉验证
    kfolder = KFold(n_splits=nfold, shuffle=True, random_state=seed)
    # 构造测试DMatrix
    xgb_tst = xgb.DMatrix(data=test[feature_names])
    print('\n')
    # 遍历cv中每一折数据,通过索引来指定
    for fold_id, (trn_idx, val_idx) in enumerate(kfolder.split(train['收率'])):
        # 构造当前训练的DMatrix
        xgb_trn = xgb.DMatrix(
            train.iloc[trn_idx][feature_names],
            train.iloc[trn_idx]['收率'])
        # 构造当前验证的DMatrix
        xgb_val = xgb.DMatrix(
            train.iloc[val_idx][feature_names],
            train.iloc[val_idx]['收率'])
        # 训练回归模型
        xgb_reg = xgb.train(params=params, dtrain=xgb_trn, **fit_params,
                  evals=[(xgb_trn, 'train'), (xgb_val, 'valid')])
        # 得到验证结果
        val_pred = xgb_reg.predict(
            xgb.DMatrix(train.iloc[val_idx][feature_names]),
            ntree_limit=xgb_reg.best_ntree_limit)
        train_pred.loc[val_idx, 'pred'] = val_pred
        # print(f'Fold_{fold_id}', mse(train.iloc[val_idx]['收率'], val_pred))
        test_pred['pred'] += xgb_reg.predict(
            xgb_tst, ntree_limit=xgb_reg.best_ntree_limit) / nfold
    print('\nCV LOSS:', mse(train_pred['true'], train_pred['pred']), '\n')
    return test_pred

设置训练参数

fit_params = {'num_boost_round': 10800, # 
              'verbose_eval': 300,  # 打印参数
              'early_stopping_rounds': 360} # 提前停止策略
params_xgb = {'eta': 0.01, 'max_depth': 7, 'subsample': 0.8,
              'booster': 'gbtree', 'colsample_bytree': 0.8,
              'objective': 'reg:linear', 'silent': True, 'nthread': 4}

一般情况下,树的数量越多,学习率稍微大点。

TIPS

  • 先尽可能的将特征列出来,最后再做筛选
  • 特征本身 和 特征相关的统计特征
  • 使用xgboost 或者 lightgbm 等会自动填充缺失值,可不提前填充。 (最好提前填充,方便做对比实验)
  • 使用xgboost时,数据转换成Dmatrix, 速度会提升,特别是针对大数据

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/998829.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

第34章 IOCTL驱动传参实验

用户如果要对外设进行操作&#xff0c;对应的设备驱动不仅要具备读写的能力&#xff0c;还需要对硬件进行控制。以点亮LED灯驱动实验为例&#xff0c;应用程序通过向内核空间写入1和0从而控制LED灯的亮灭&#xff0c;但是读写操作主要是数据流对数据进行操作&#xff0c;而一些…

C++解析XML文件(TinyXML)

简介 TinyXML是一个开源的解析XML的解析库&#xff0c;能够用于C&#xff0c;能够在Windows或Linux中编译。这个解析库的模型通过解析XML文件&#xff0c;然后在内存中生成DOM模型&#xff0c;从而让我们很方便的遍历这棵XML树。 TinyXML库下载 本文所用库文件来自 TinyXML …

阿里云WAF应用防火墙核心概念与购买使用

文章目录 1.WAF应用防火墙基本概念1.1.什么是WAF防火墙1.2.WAF的主要功能1.3.WAF应用防火墙的应用场景1.4.网站接入WAF应用防火墙架构图 2.开通WAF防火墙产品 1.WAF应用防火墙基本概念 官方文档&#xff1a;https://help.aliyun.com/document_detail/28517.html 1.1.什么是WA…

【ccf-csp题解】第四次csp认证-第四题-网络延时-树的直径

题目描述 思路分析 本题所求的实际上是树的直径&#xff0c;即树中的任意两个结点之间的最大距离 采用的方法是dfs 从根节点开始遍历&#xff0c;对于每一个被dfs的结点m&#xff0c;返回此结点m到所有叶子结点的距离最大的那个即d1&#xff0c;同时在dfs过程当中记录结点m到…

修改conda 虚拟环境下的PS1提示符格式

问题&#xff1a; 终端命令提示符太长了&#xff0c;严重影响工作效率 解读办法&#xff1a; conda env config vars set PS1(nyang)[\u\h \W]$效果&#xff1a; so beautiful !!!

【Redis】4、rsync远程同步

与inodify结合使用&#xff0c;实现实时同步 rsync简介 rsync&#xff08;Remote Sync&#xff0c;远程同步&#xff09;是一个开源的快速备份工具&#xff0c;可以在不同主机之间镜像同步整个目录树&#xff0c;&#xff1b;支持增量备份&#xff0c;并保持链接和权限&#…

四叶草clover配置工具:Clover Configurator for Mac

Clover Configurator是一款Mac上的工具&#xff0c;用于配置和优化Clover引导加载器。Clover引导加载器是一种用于启动macOS的开源引导加载器。它允许用户在启动时选择操作系统和配置启动选项。 Clover Configurator提供了一个可视化的界面&#xff0c;让用户可以轻松地编辑和…

极光笔记 | 推送服务数据中心选择:合规性与传输效率的双重考量

随着全球化进程的深入&#xff0c;跨境数据传输与存储问题已经变得愈发重要。推送服务的数据中心节点选择不仅关乎数据访问速度和用户体验&#xff0c;同时也直接牵扯到数据合规性和安全保障。EngageLab Push深知这一点&#xff0c;为了满足更多国际客户和全球用户触达需求&…

uniapp打包安卓apk的隐私政策配置

uniapp打包安卓端app的隐私政策配置 1、隐私政策配置位置 2、uniapp项目配置文件代码 androidPrivacy.json {"version" : "1","prompt" : "template","title" : "用户服务协议和隐私政协议","message&quo…

JAVASE事件监听

代码&#xff1a; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Scanner;import javax.swing.JButton; import javax.…

管理类联考——数学——汇总篇——知识点突破——应用题——最值问题

⛲️ 一、考点讲解 最值问题是应用题中最难的题目&#xff0c;也是考生普遍丢分的题目。最值问题一般要结合函数来分析&#xff0c;一般结合二次函数和平均值定理求解。最值问题的求解步骤是&#xff1a;先设未知变量&#xff0c;然后根据题目建立函数表达式&#xff0c;最后利…

HT for Web (Hightopo) 使用心得(1)- 基本概念

Hightopo 公司 3D 可视化产品有对应的官方手册。但是这些手册内容比较多。对于想学习的新同学来说可能相对比较繁琐。这里本人根据个人使用经验做了一些总结。希望对读者有所帮助。 本文会提到一些前端开发的概念&#xff0c;如 H5, JavaScript&#xff0c;JSON 等。没有开发经…

【linux input子系统-01】核心层、事件处理层、设备驱动层

简介 input子系统的三层&#xff1a; 核心层&#xff1a;为事件处理层、设备驱动层提供接口&#xff0c;并在input_handler和input_dev之间建立关联&#xff1b;事件处理层&#xff1a;内核对象对应input_handler&#xff0c;用于接收-解析-处理设备驱动层上报的输入事件&…

借助VScode将 Docker 容器用作开发环境

参考 借助 Visual Studio Code 将 Docker 容器用作开发环境 - Training | Microsoft Learn 存在的问题 Remote-SSH XHR failed无法访问远程服务器 【VScode】Remote-SSH XHR failed无法访问远程服务器_SuperSources的博客-CSDN博客 可能是网络问题&#xff0c;打开vpn 就可以正…

探索GreatADM:如何快速定义监控

引文 在数据库运维过程中&#xff0c;所使用的运维管理平台是否存在这样的问题&#xff1a; 1、默认监控粒度不够,业务需要更细颗粒度的监控数据。2、平台默认的监控命令不适合,需要调整阈值量身定制监控策略。3、不同类型的实例或组件需要有不同的监控重点,但管理平台监控固…

【云原生】kubectl常用命令大全

目录 一、资源管理方法 kubectl 的命令大全 二、 kubectl常用命令大全 2.2 项目的生命周期&#xff1a;创建-->发布-->更新-->回滚-->删除 1、创建 kubectl create命令 2、发布 kubectl expose命令 3、更新 kubectl set 4、回滚 kubectl rollou…

什么是实时监控系统?

监控报警器在工业生产和电子行业中广泛应用。其中包括数据收发器、多功能监控报警器、人体接地监控器、手腕带监控报警器等等。 通过网络把“静电监测设备”、“接地监控报警器”、“数据转换器”、“计算机”等设备连接起来&#xff0c;连接成一个完整的静电实时监控系统。缺一…

u盘制成系统盘之后如何让恢复普通盘

U盘装完pe后怎么还原成普通U盘 1.插入U盘&#xff0c;按WindowsR 输入diskpart 2.输入“list disk”回车&#xff0c;查看U盘代号&#xff0c;例如下图里我的U盘代号是磁盘1&#xff08;你的不一定是1&#xff0c;一定要分清楚&#xff09; 3.输入“select disk 2”选中U盘磁…

2 亿 + 数据打开方式:人工智能数字疗法

你今天真好看 APP:您好&#xff0c;我们目前是一个大学生创新项目团队&#xff0c;内容为针对青少年痤疮问题的「人工智能数字疗法」。目前正在进行 AI 诊断模型的训练&#xff0c;看到您产品的信息并且开放了数据库&#xff0c;我们想知道&#xff1a;如何才能使用贵公司的数据…

PDF文件太大怎么办?三招教会你PDF文件压缩

PDF文件太大怎么办&#xff1f;这是许多人在处理PDF文件时遇到的问题。为了帮助大家解决这个问题&#xff0c;下面总结了三个可以解决PDF文件过大问题的方法&#xff0c;需要的朋友抓紧来看看吧~ 方法一&#xff1a;使用嗨格式压缩大师 嗨格式压缩大师是一款功能强大的PDF压缩…