10万元奖金“智源工业检测赛”激战正酣!高分Baseline合辑带你入门智能制造

百年德企博世放出真实独家生产场景脱敏数据,邀你为工业 4.0 制造练就 AI 大脑。

目前,由北京智源人工智能研究院联合博世和 biendata 共同发布的“INSPEC 工业大数据质量预测赛”(2019 年 12 月 — 2020 年 4 月)正在火热进行中,总奖金为 10 万元。

比赛发布了博世某系列产品近年来的质量检测相关数据,要求选手根据已有产品质检环节记录的相关参数,使用机器学习算法对正在测试的产品进行质量预测,提前判断次品,节省整体检测时间。比赛和数据可于下方链接查看,或点击“阅读原文”,欢迎所有感兴趣的报名读者参赛

目前,赛事已接近半程,为帮助选手进一步提升模型预测结果,biendata 邀请的四名活跃选手:pinlan(2019 数字中国混泥土砼活塞故障预警冠军)、bestIteration(JData 亚军、2019 KDD Top 10)、sijinabc、hh_neuq 分享四个分数在 0.6 左右的 baseline ,希望可以为大家在数据探索、特征工程、模型选择、参数调优等方面提供参考和思路。

比赛地址:

https://www.biendata.com/competition/bosch/ 

1

Baseline 概览

(一)选手 pinlan 首先根据题意将赛题归为二分类问题,在样本构造方面,该选手建议样本应和官方提供 validation 相似,并认为样本构造方法可能是上分关键。

在特征工程上,选手 pinlan:1)针对产品实例 Product_ID 构造统计特征:最值,均值;2)对类别特征进行编码;3)构思一些具有背景意义的特征;4)提示工业数据一般暗含很多规则,一些数据探索分析可以帮助发现规则,有助于分数提升。

pinlan 采用 5 fold 划分数据集,并选用 LightGBM 模型。该 Baseline 最终线上成绩为 0.6,具体代码实现欢迎访问以下页面查看或浏览下文。

https://biendata.com/models/category/4063/L_notebook/

(二)选手 bestIteration 首先分析了目标变量分布、缺失值比例、类别变量分布差异等,总结出两种建模思路:1)构造产品实例(ID_F_PROCESS)的特征,预测其最终是否合格;2)构造产品中检测步骤的特征,预测该检测步骤结果是否合格,再进一步得到对应产品实例最终是否合格。

关于特征工程,bestIteration 主要聚焦于对连续值的统计特征(如 RESULT_VALUE)、每个检测步骤中 RESULT_VALUE 的统计特征、对类别变量的 TFIDF 特征(如 ID_F_PARAMETER_S)。该选手选用 LightGBM 模型,并使用 5 折交叉验证。该 Baseline 最终线上成绩为 0.61+,具体代码实现欢迎以下访问页面查看。

https://biendata.com/models/category/4239/L_notebook/

(三)选手 sijinabc 经过对数据的理解,其分类模型将在以下几点假设的基础上建立:1)对于产品检测的过程数据,不同检测步骤之间互不影响,因此认为检测数据不存在时间序列关系;2)对于各检测序列中正常的检测数据,不同产品之间的数值差别可以体现产品的不同质量;3)不同产品的检测序列长度、检测顺序、检测内容不同,模型需有较好的泛化性,注意防止过拟合。

其主要思路为:

1)简化数据表,减小数据维度;

2)建立训练集,其中包括将检测参数序列号(ID_F_PARAMETER_S )顺序排列作为特征名;对应的数值型检测结果(RESULT_VALUE)或参数检测结果(PARAMETER_RESULT_STATE)作为模型特征;产品实例的最终检测结果(PROCESS_RESULT_STATE)作为样本标签;分别取前四个、前十个检测步骤的序列 ID(ID_F_PHASE_S)0~9 对应的检测参数序列及检测结果用于训练模型;识别并删除异常数据。

3)建立二分类模型。该 Baseline 最终线上成绩为 0.6,具体代码实现欢迎访问以下页面查看。

https://biendata.com/models/category/4224/L_notebook/

(四)选手 hh_neuq 首先读取 Excel 格式数据,将小文件合并成三个大文件,并转为 csv 格式文件存储。然后对数据进行筛选,并提取特征,用 LightGBM 建模。该选手认为,可以深入可视化,进而提取特征,并对模型进行调参。

该 Baseline 最终线上成绩为 0.57,具体代码实现欢迎访问以下页面查看。

https://biendata.com/models/category/4298/L_notebook/

2

Baseline 详情

pinlan 版 

本 baseline 线上成绩为 0.6。

1. 赛题引入与问题分析

本次比赛的任务为产品质量预测,所使用数据为“INSPEC 工业检测大数据“,其中包含博世某产品家族的工厂生产环节的检测参数,要求选手根据训练集中产品的相关数据(如子家族名称、检测流程、检测结果)建立和优化模型,并参照目标产品中已完工序的检测结果,预测最终产品检测的结果为合格或不合格。

赛题线上验证集已经由官方提取完毕,训练数据需要自行提取。官方提供了以产品类型-子家族(TYPE_NUMBER-PRODUCTGROUP_NAME)命名的 excel 表格,每个表格下包含产品实例表,检测步骤表和步骤参数表三个表。

整体思路

1. 根据官方发布的题目,明确题目含义:参照目标产品中已完工序的检测结果,预测 "最终产品" 检测的结果为合格或不合格。

  • 根据题意,作者将题目定义为二分类问题;

  • 先建立 valid_4 模型,再建立 valid_11 模型,建模流程相同。

2. 训练样本构造,样本应和官方提供 validation 相似,这里样本构造方法可能是上分关键,这里提供本人样本构建方法(get_data 函数),以及部分思考。

  • 样本越多,效果越好;

  • 官方验证集未包含全部子家族以及产品类型,在提取训练集时是否删去官方验证集未包含的子家族;

  • 对于 validation_predict_4 而言,提取训练数据应包含产品实例前三步检测数据,这里进行了数据筛选,剔除了前三部已经检测出问题的产品。

3. 特征工程:

  • 针对产品实例 Product_ID 构造统计特征:最值,均值;

  • 对类别特征进行编码;

  • 构思一些具有背景意义的特征;

  • 工业数据一般暗含很多规则,一些 EDA 可以帮助发现规则,有助于分数提升。

4. 采用 5 fold 划分数据集。

5. lightgbm 模型,模型可自选:

  • 正负样本极不平衡;

  • 主要在于不平衡样本的处理,如使用采样,is_unbalance 参数;

  • 模型方面小数据集分类问题 Catboost 可能更具有优势。

6. 评价指标 F1。

  • F1 需要设置阈值,阈值对结果影响很大,概率、排序或者搜索算法等都可以;

  • F1 不单考虑某一类样本的准确性,需要正负样本预测准确性都高。

7. 划重点:

  • 训练样本构造以及筛选方式,十分重要;

  • 特征工程。

2. 数据提取与探索性分析
import numpy as np
import pandas as pd
import gc
import os
import math
import lightgbm as lgb
from sklearn.metrics import f1_score,accuracy_score,roc_auc_score
from sklearn.model_selection import StratifiedKFold,KFold,train_test_split
import matplotlib.pyplot as plt
%matplotlib inline
import seaborn as sns
color = sns.color_palette()
sns.set_style("whitegrid")
import warnings
warnings.filterwarnings('ignore')
path='./INSPEC_train/'
test_path='./INSPEC_validation/'
filename=os.listdir('./INSPEC_train/')
data_cols = ['Product_ID', 'TYPE_NUMBER', 'PRODUCTGROUP_NAME', 'ID_F_PHASE','PHASE_RESULT_STATE', 'PHASE_NAME', 'ID_F_PHASE_S',
             'RESULT_STRING','RESULT_VALUE', 'PARAMETER_RESULT_STATE', 'LOWER_LIMIT', 'UPPER_LIMIT','AXIS', 'SIDE', 'ID_F_PARAMETER_S']

2.1 数据提取

2.1.1 数据组成

a) 产品实例表:产品实例的 ID,产品实例的最终检测结果(1 为合格、2 为不合格),产品类型名,产品类型所在子家族。

b) 检测步骤表:产品实例的 ID,检测步骤的 ID,检测步骤的结果,检测步骤的名称,检测步骤的序列 ID。

c) 步骤参数表:检测步骤 ID,字符串类型检测结果(表示产品等级),数值型检测结果,该参数检测结果,数值型检测可供参考的上下限,产品的轴、产品的面,检测步骤的序列 ID,检测参数的序列号。

2.1.2 对单个产品类型表格提取数据(get_data 函数)

a) 以每个产品类型 excel 为基础,包括产品实例表、检测步骤表和步骤参数表三个表。

b) 将三个数据表合并,对于验证集 4 提取检测步骤 ID_F_PHASE_S<3 的数据。

c) 将训练数据与验证数据比较,删除多余字段,使训练集与验证集具有相同形式。

2.1.3 将单个表提取数据合并为训练数据,其中 Product_ID 为样本编号,label 为标签 (get_train4)。

def get_data(path, data_cols, file_dir, num):
    process = pd.read_excel(path+file_dir, sheet_name='Process_Table')
    phase = pd.read_excel(path+file_dir, sheet_name='Phase_Table')
    parameters = pd.read_excel(path+file_dir, sheet_name='Parameters_Table')
    del parameters['ID_F_PHASE_S'];gc.collect()
    df = process.merge(phase, on = 'ID_F_PROCESS', how = 'left')
    df = df.merge(parameters, on = 'ID_F_PHASE', how = 'left')
    df.rename(columns={'ID_F_PROCESS':'Product_ID','PROCESS_RESULT_STATE':'label'}, inplace=True)
    df = df[data_cols+['label']]
    bad_id = df[(df['ID_F_PHASE_S'] < num)&(df['PHASE_RESULT_STATE'] == 2)]['Product_ID'].unique()
    df = df[~df['Product_ID'].isin(bad_id)]
    df = df[df['ID_F_PHASE_S'] < num].reset_index(drop=True)
    del process, phase, parameters;gc.collect()
    return df

def get_train4(path, data_cols, filename):try:
        train_4 = pd.read_csv('train_4.csv')
    except:
        train_4 = pd.DataFrame()
        for dir_file in tqdm(filename):
            temp_df = get_data(path, data_cols, dir_file, 3)
            train_4 = train_4.append(temp_df)
        train_4 = train_4.reset_index(drop=True)
        train_4.to_csv('train_4.csv', index=False)
    return train_4

2.2 探索性分析

主要特征: 

1)检测方面:产品的轴、产品的面;

2)检测结果:RESULT_STRING,RESULT_VALUE,LOWER_LIMIT,UPPER_LIMI;

3)其他描述性类别特征。

train_4 = get_train4(path, data_cols, filename)
train_4.head()
train_4.describe()
plt.rcParams['font.sans-serif']=['SimHei']
train_4.drop_duplicates(subset=['Product_ID'])['label'].value_counts().plot.pie(autopct='%1.1f%%',title = '正负样本比例')
<matplotlib.axes._subplots.AxesSubplot at 0x2375cb20f98>

train_4.nunique().plot.bar(title='类别个数')
<matplotlib.axes._subplots.AxesSubplot at 0x2375cbbfb70>

(train_4.isnull().sum()/len(train_4)).plot.bar(title='缺失值比例')
<matplotlib.axes._subplots.AxesSubplot at 0x2375cc6b9b0>

标签在检测参数的序列号 ID_F_PARAMETER_S 上面变化大,可以看出说明检测步骤越多,产品越紧密,制作难度越大。

train_4.groupby('label')['ID_F_PARAMETER_S'].agg(['min', 'max', 'median','mean', 'std']) 

train_4.groupby(['label'])['RESULT_VALUE'].describe()

正常来说,产品尺寸好坏要通过尺寸与公差上下极限关系来判断,因此可以考虑 RESULT_VALUE 和 LOWER_LIMIT 以及 UPPER_LIMIT 关系,构造特征:做差。可以看出距离上下限差值越大,产品越容易在制作时损坏。 

temp = train_4[['Product_ID','RESULT_VALUE', 'LOWER_LIMIT', 'UPPER_LIMIT','label']].dropna()
temp.head(10)

temp['差值'] = temp['RESULT_VALUE'] - temp['LOWER_LIMIT'] / (temp['UPPER_LIMIT'] - temp['LOWER_LIMIT'])
temp.groupby('label')['差值'].describe()

3

代码分析

import numpy as np
import pandas as pd
import gc
import os
import math
import lightgbm as lgb
from sklearn.metrics import f1_score,accuracy_score,roc_auc_score
from sklearn.model_selection import StratifiedKFold,KFold,train_test_split
path='./INSPEC_train/'
test_path='./INSPEC_validation/'
filename=os.listdir('./INSPEC_train/')
data_cols = ['Product_ID', 'TYPE_NUMBER', 'PRODUCTGROUP_NAME', 'ID_F_PHASE','PHASE_RESULT_STATE', 'PHASE_NAME', 'ID_F_PHASE_S',
           'RESULT_STRING','RESULT_VALUE', 'PARAMETER_RESULT_STATE', 'LOWER_LIMIT', 'UPPER_LIMIT','AXIS', 'SIDE', 'ID_F_PARAMETER_S']

valid4 建模

#提取训练数据def get_data(path, data_cols, file_dir, num):
    process = pd.read_excel(path+file_dir, sheet_name='Process_Table')
    phase = pd.read_excel(path+file_dir, sheet_name='Phase_Table')
    parameters = pd.read_excel(path+file_dir, sheet_name='Parameters_Table')
    del parameters['ID_F_PHASE_S'];gc.collect()
    df = process.merge(phase, on = 'ID_F_PROCESS', how = 'left')
    df = df.merge(parameters, on = 'ID_F_PHASE', how = 'left')
    df.rename(columns={'ID_F_PROCESS':'Product_ID','PROCESS_RESULT_STATE':'label'}, inplace=True)
    df = df[data_cols+['label']]
    bad_id = df[(df['ID_F_PHASE_S'] < num)&(df['PHASE_RESULT_STATE'] == 2)]['Product_ID'].unique()
    df = df[~df['Product_ID'].isin(bad_id)]
    df = df[df['ID_F_PHASE_S'] < num].reset_index(drop=True)
    del process, phase, parameters;gc.collect()
    return df
#合并数据def get_train4(path, data_cols, filename):try:
        train_4 = pd.read_csv('train_4.csv')
    except:
        train_4 = pd.DataFrame()
        for dir_file in tqdm(filename):
            temp_df = get_data(path, data_cols, dir_file, 3)
            train_4 = train_4.append(temp_df)
        train_4 = train_4.reset_index(drop=True)
        train_4.to_csv('train_4.csv', index=False)
    return train_4
#构造统计特征def make_feature(data,aggs,name,data_id):
    agg_df = data.groupby(data_id).agg(aggs)
    agg_df.columns = agg_df.columns = ['_'.join(col).strip()+name for col in agg_df.columns.values]
    agg_df.reset_index(drop=False, inplace=True)
    return agg_df
#产品实例统计特征def get_4_fe(data,cate_cols):
    dd_cols = ['PHASE_RESULT_STATE', 'RESULT_STRING','PARAMETER_RESULT_STATE']
    data.drop(columns=dd_cols, inplace=True)
    data['ID_F_PHASE_S'] = data['ID_F_PHASE_S'].astype('int8')
    df = data[['Product_ID', 'label'] + cate_cols].drop_duplicates()

    aggs = {}
    for i in ['RESULT_VALUE']:
        aggs[i] = ['min', 'max', 'mean', 'std', 'median']
    for i in ['PHASE_NAME', 'AXIS']:
        aggs[i] = ['nunique']
    aggs['ID_F_PARAMETER_S'] = ['max', 'std', 'mean', 'median', 'count']
    temp = make_feature(data, aggs, "_product", 'Product_ID')
    df = df.merge(temp, on = 'Product_ID', how='left')
    return df
#根据数值检测结果上下限构造统计def get_limit_4(data,df):
    temp = data[['Product_ID','RESULT_VALUE', 'LOWER_LIMIT', 'UPPER_LIMIT']].dropna()
    temp['差值'] = temp['RESULT_VALUE'] - temp['LOWER_LIMIT'] / (temp['UPPER_LIMIT'] - temp['LOWER_LIMIT'])
    aggs = {}
    aggs['差值'] = ['min', 'max', 'mean']
    temp_df = make_feature(temp, aggs, "_limit", 'Product_ID')
    df = df.merge(temp_df, on = 'Product_ID', how='left')
    return df
#目标编码def get_target_mean_4(df, cate_cols):for i in cate_cols:
        df[f'{i}_label_mean'] = df.groupby(i)['label'].transform('mean')
    return df
#建模数据def get_training_data(df, name):
    train_4 = df[~df['label'].isnull()].reset_index(drop=True)
    test_4 = df[df['label'].isnull()].reset_index(drop=True)

    col = [i for i in train_4.columns if i notin ['Product_ID', 'label']]
    X_train = train_4[col]
    y_train = (train_4['label']-1).astype(int)
    X_test = test_4[col]
    sub = test_4[['Product_ID']].copy()
    print('{} train shape {} and test shape {}'.format(name, X_train.shape, X_test.shape))
    return X_train, y_train, X_test, sub

1. 提取数据

train_4 = get_train4(path, data_cols, filename)
test_4 = pd.read_csv(test_path + 'validation_predict_4.csv')
train_4 = train_4[train_4['PRODUCTGROUP_NAME'].isin(test_4['PRODUCTGROUP_NAME'].unique())]
data_4 = train_4.append(test_4).reset_index(drop=True)
data_4.loc[data_4['AXIS'] == -9.223372036854776e+18, 'AXIS'] = np.nan
print('val_4 train sample {} and test sample {}'.format(train_4['Product_ID'].nunique(), test_4['Product_ID'].nunique()))

val_4 train sample 16441 and test sample 3721 

2. 特征工程

cate_cols = ['TYPE_NUMBER', 'PRODUCTGROUP_NAME']
df4 = get_4_fe(data_4,cate_cols)
df4 = get_limit_4(data_4,df4)
df4 = get_target_mean_4(df4,cate_cols)
df4['TYPE_NUMBER'] = df4['TYPE_NUMBER'].astype('category')
df4['PRODUCTGROUP_NAME'] = df4['PRODUCTGROUP_NAME'].astype('category')
#构建标签
X_train, y_train, X_test, sub1 = get_training_data(df4, 'val_4')

val_4 train shape (16441, 19) and test shape (3721, 19) 

3. 模型训练

lgb 自定义评测 f1 评测:

def lgb_f1_score(y_hat, data):
    y_true = data.get_label()
    y_hat = np.round(y_hat)
    return'f1', f1_score(y_true, y_hat), True

五折划分数据,lgb 参数设置:

K = 5
seed = 2020
skf = StratifiedKFold(n_splits=K, shuffle=True, random_state=seed)
lgb_params = {
                        'boosting_type': 'gbdt',
                        'objective': 'binary',
                        'metric': 'None',
                        'num_leaves': 63,
                        'subsample': 0.8,
                        'colsample_bytree': 0.8,
                        'learning_rate': 0.05,
                        'lambda_l2':2,
                        'nthread': -1,
                        'silent': True
             }
f1_scores = []
oof = np.zeros(len(X_train))
predictions = np.zeros(len(X_test))
feature_importance_df = pd.DataFrame()

for i, (train_index, val_index) in enumerate(skf.split(X_train,y_train)):
    print("fold{}".format(i))
    X_tr, X_val = X_train.iloc[train_index], X_train.iloc[val_index]
    y_tr, y_val = y_train.iloc[train_index], y_train.iloc[val_index]

    lgb_train = lgb.Dataset(X_tr,y_tr)
    lgb_val = lgb.Dataset(X_val,y_val)
    num_round = 3000
    clf = lgb.train(lgb_params, lgb_train, num_round, valid_sets = [lgb_train, lgb_val], feval=lgb_f1_score,
                    categorical_feature=['TYPE_NUMBER', 'PRODUCTGROUP_NAME'],
                    verbose_eval=100, early_stopping_rounds = 100)
    oof[val_index] = clf.predict(X_val, num_iteration=clf.best_iteration)
    pred = clf.predict(X_val, num_iteration=clf.best_iteration)
    sc = f1_score(y_val, np.round(pred))
    f1_scores.append(sc)
    print(f'fold{i} f1 score = ',sc)
    print('best iteration = ',clf.best_iteration)
    fold_importance_df = pd.DataFrame()
    fold_importance_df["Feature"] = clf.feature_name()
    fold_importance_df["importance"] = clf.feature_importance()
    fold_importance_df["fold"] = i + 1
    feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)
    predictions += clf.predict(X_test, num_iteration=clf.best_iteration) / skf.n_splits
print('val_4 训练f1均值: {},波动: {}.'.format(np.mean(f1_scores), np.std(f1_scores)))
print('val_4 macro F1 score: ',f1_score(y_train, np.round(oof),average='macro'))

4. 特征重要性

plt.figure(figsize=(12,8))
sns.barplot(y='Feature', x='importance',data=feature_importance_df)
plt.title('val_4特征重要性')

Text (0.5,1,'val_4特征重要性')

5. 生成 val4 结果

sub1['label'] = predictions
sub1['label'] = sub1['label'].rank()
sub1['label'] = (sub1['label']>=sub1.shape[0] * 0.93).astype(int)
sub1['label'] = (sub1['label'] + 1).astype(int)
sub1.rename(columns={'Product_ID':'id'}, inplace=True)
print('val_4正负样本比例:\n', sub1['label'].value_counts())

val_4 正负样本比例:


1 3460 

2 261 

Name: label, dtype: int64 

这里结合数据和结果发现规则:结果中发现一个产品实例只有三条检测记录的正常样本居多,直接全部赋值 1,大概有百分位提升,但更换数据集后效果未知。

rule = test_4['Product_ID'].value_counts()
rule = rule[rule==3].index.values
sub1.loc[sub1['id'].isin(rule), 'label'] = 1
print('val_4正负样本比例:\n', sub1['label'].value_counts())

val_4 正负样本比例:

1 3609 

2 112 

Name: label, dtype: int64 

valid11 建模

#合并数据def get_train11(path, data_cols, filename):try:
        train_11 = pd.read_csv('train_11.csv')
    except:
        train_11 = pd.DataFrame()
        for dir_file in tqdm(filename):
            temp_df = get_data(path, data_cols, dir_file, 10)
            train_11 = train_11.append(temp_df)
        train_11 = train_11.reset_index(drop=True)
        train_11.to_csv('train_11.csv', index=False)
    return train_11
#产品实例统计特征def get_11_fe(data_11, cate_cols):
    dd_cols = ['PHASE_RESULT_STATE', 'PARAMETER_RESULT_STATE']
    data_11.drop(columns=dd_cols, inplace=True)
    data_11['ID_F_PHASE_S'] = data_11['ID_F_PHASE_S'].astype('int8')
    df = data_11[['Product_ID', 'label'] + cate_cols].drop_duplicates()

    aggs = {}
    for i in ['RESULT_VALUE']:
        aggs[i] = ['min', 'max', 'mean', 'std', 'median']
    for i in ['PHASE_NAME', 'AXIS', 'SIDE', 'RESULT_STRING']:
        aggs[i] = ['nunique']
    aggs['ID_F_PARAMETER_S'] = ['max', 'std', 'mean', 'count']
    temp = make_feature(data_11, aggs, "_product", 'Product_ID')
    df = df.merge(temp, on = 'Product_ID', how='left')
    return df
#根据数值检测检测上下限构造统计def get_limit_11(data,df):
    temp = data[['Product_ID','RESULT_VALUE', 'LOWER_LIMIT', 'UPPER_LIMIT']].dropna()
    temp['差值'] = temp['RESULT_VALUE'] - temp['LOWER_LIMIT'] / (temp['UPPER_LIMIT'] - temp['LOWER_LIMIT'])
    aggs = {}
    aggs['差值'] = ['min', 'max', 'mean']
    temp_df = make_feature(temp, aggs, "_limit", 'Product_ID')
    df = df.merge(temp_df, on = 'Product_ID', how='left')
    return df
#类别特征def get_cate_11(data, df, cate_cols):
    df['TYPE_NUMBER'] = df['TYPE_NUMBER'].astype('category')
    df['PRODUCTGROUP_NAME'] = df['PRODUCTGROUP_NAME'].astype('category')

    temp = pd.pivot_table(data=data, index='Product_ID',values='RESULT_VALUE',columns='SIDE',aggfunc='min').reset_index()
    df = df.merge(temp, on = 'Product_ID', how='left')

    temp = pd.pivot_table(data=data, index='Product_ID',values='RESULT_VALUE',columns='AXIS',aggfunc='min').reset_index()
    df = df.merge(temp, on = 'Product_ID', how='left')

    temp = pd.pivot_table(data=data, index='Product_ID',values='RESULT_VALUE',columns='RESULT_STRING',aggfunc='count').reset_index()
    df = df.merge(temp, on = 'Product_ID', how='left')

    for i in cate_cols:
        df[f'{i}_label_mean'] = df.groupby(i)['label'].transform('mean')

    return df

1. 提取数据

train_11 = get_train11(path, data_cols, filename)
test_11 = pd.read_csv(test_path + 'validation_predict_11.csv')
train_11 = train_11[train_11['PRODUCTGROUP_NAME'].isin(test_11['PRODUCTGROUP_NAME'].unique())]
data_11 = train_11.append(test_11).reset_index(drop=True)
data_11.loc[data_11['AXIS'] == -9.223372036854776e+18, 'AXIS'] = np.nan
print('val_11 train sample {} and test sample {}'.format(train_11['Product_ID'].nunique(), test_11['Product_ID'].nunique()))

val_11 train sample 13051 and test sample 3784

2. 特征工程

cate_cols = ['TYPE_NUMBER', 'PRODUCTGROUP_NAME']
df11 = get_11_fe(data_11, cate_cols)
df11 = get_limit_11(data_11, df11)
df11 = get_cate_11(data_11, df11, cate_cols)

# 构建标签
X_train, y_train, X_test, sub2 = get_training_data(df11, 'val_11')

val_11 train shape (13051, 36) and test shape (3784, 36) 

3. 模型训练 

五折划分数据,lgb 参数设置:

K = 5
seed = 2020
skf = StratifiedKFold(n_splits=K, shuffle=True, random_state=seed)
lgb_params = {
                        'boosting_type': 'gbdt',
                        'objective': 'binary',
                        'metric': 'None',
                        'num_leaves': 32,
#                         'is_unbalance': True,'subsample': 0.9,
                        'colsample_bytree': 0.9,
                        'learning_rate': 0.05,
                        'lambda_l2':1,
#                         'min_data_in_leaf':10,'nthread': -1,
                        'silent': True
             }
f1_score2 = []
oof = np.zeros(len(X_train))
predictions2 = np.zeros(len(X_test))
feature_importance_df = pd.DataFrame()

for i, (train_index, val_index) in enumerate(skf.split(X_train,y_train)):
    print("fold_{}".format(i))
    X_tr, X_val = X_train.iloc[train_index], X_train.iloc[val_index]
    y_tr, y_val = y_train.iloc[train_index], y_train.iloc[val_index]

    lgb_train = lgb.Dataset(X_tr,y_tr)
    lgb_val = lgb.Dataset(X_val,y_val)
    num_round = 3000
    clf = lgb.train(lgb_params, lgb_train, num_round, valid_sets = [lgb_train, lgb_val], feval=lgb_f1_score,
                    categorical_feature=['TYPE_NUMBER', 'PRODUCTGROUP_NAME'],
                    verbose_eval=100, early_stopping_rounds = 100)
    oof[val_index] = clf.predict(X_val, num_iteration=clf.best_iteration)
    pred = clf.predict(X_val, num_iteration=clf.best_iteration)
    sc = f1_score(y_val, np.round(pred))
    f1_score2.append(sc)
    print(f'fold{i} f1 score = ',sc)
    print('best iteration = ',clf.best_iteration)
    fold_importance_df = pd.DataFrame()
    fold_importance_df["Feature"] = clf.feature_name()
    fold_importance_df["importance"] = clf.feature_importance()
    fold_importance_df["fold"] = i + 1
    feature_importance_df = pd.concat([feature_importance_df, fold_importance_df], axis=0)
    predictions2 += clf.predict(X_test, num_iteration=clf.best_iteration) / skf.n_splits

print('val_11训练f1均值:{},波动:{}.'.format(np.mean(f1_score2), np.std(f1_score2)))
print('val_11 macro F1 score: ',f1_score(y_train, np.round(oof),average='macro'))

4. 特征重要性

plt.figure(figsize=(12,8))
sns.barplot(y='Feature', x='importance',data=feature_importance_df)
plt.title('val_11特征重要性')

Text (0.5,1,'val_11特征重要性')

5. 生成 val_11 结果

sub2['label'] = predictions2
sub2['label'] = sub2['label'].rank()
sub2['label'] = (sub2['label']>=sub2.shape[0] * 0.97).astype(int)
sub2['label'] = (sub2['label'] + 1).astype(int)
sub2.rename(columns={'Product_ID':'id'}, inplace=True)
print('正负样本比例:\n', sub2['label'].value_counts())

正负样本比例:

1 3703 

2 81 

Name: label, dtype: int64

生成提交文件

sub = sub1.append(sub2)
print('正负样本比例:\n', sub['label'].value_counts())
sub.to_csv(f'sub_val4_{np.round(np.mean(f1_scores),3)}_val11_{np.round(np.mean(f1_score2),3)}.csv', index=False)

正负样本比例: 

1 7312 

2 193 

Name: label, dtype: int64

sub.head()

由于文章篇幅限制,其他选手 Baseline 请扫码查看。

▲ bestIteration版

▲ sijinabc版

▲ hh_neuq版

4

参赛方式

点击阅读原文链接或扫描下图中的二维码直达赛事页面,注册网站-下载数据,即可参赛。

biendata 是知名的国际性大数据竞赛平台,面向全球在校学生、科研人员、企业以及自由职业者开放,期待对人工智能感兴趣的小伙伴能在平台上众多比赛中大展身手,在思维与技术的交流碰撞中激发创新和突破。 

友情提示,因涉及到数据下载,强烈建议大家登录 PC 页面报名参加。

5

INSPEC 工业检测大数据

智源联合博世发布了 INSPEC 工业检测大数据,该数据集包括某系列产品近年来的质量检测相关数据,其中主要为每个产品质量检测环节各个步骤记录的相关参数,每个步骤都标注检测判定结果,整体数据量在 3w 条左右。相比于类似数据集,本比赛数据具有显著优势和特点。 

首先,该数据集来自世界顶尖制造企业真实的工厂生产数据,已经过脱敏处理,尽量还原现实环境中产品检测的工序和流程。其次,INSPEC 工业检测大数据详细记录了检测环节生成的具体产品参数,涵盖产品子家族 ID、实例 ID、检测环节 ID、检测环节结果、检测规格和数值等。丰富的数据维度一方面增强了比赛的难度,另一方面有助于选手打造更加鲁棒的模型。

6

智源算法大赛

2019 年 9 月,智源人工智能算法大赛正式启动。本次比赛由北京智源人工智能研究院主办,清华大学、北京大学、中科院计算所、旷视、知乎、博世、爱数智慧、国家天文台、晶泰等协办,总奖金超过 100 万元,旨在以全球领先的科研数据集与算法竞赛为平台,选拔培育人工智能创新人才。 

研究院副院长刘江也表示:“我们希望不拘一格来支持人工智能真正的标志性突破,即使是本科生,如果真的是好苗子,我们也一定支持。”而人工智能大赛就是发现有潜力的年轻学者的重要途径。 

本次智源人工智能算法大赛有两个重要的目的,一是通过发布数据集和数据竞赛的方式,推动基础研究的进展。特别是可以让计算机领域的学者参与到其它学科的基础科学研究中。二是可以通过比赛筛选、锻炼相关领域的人才。智源算法大赛已发布全部的 10 个数据集,目前仍有 5 个比赛(奖金 50 万)尚未结束。

7

正在角逐的比赛

智源小分子化合物性质预测挑战赛 

https://www.biendata.com/competition/molecule/ 

智源杯天文数据算法挑战赛 

https://www.biendata.com/competition/astrodata2019/

智源-INSPEC 工业大数据质量预测赛 

https://www.biendata.com/competition/bosch/

智源-MagicSpeechNet 家庭场景中文语音数据集挑战赛

https://www.biendata.com/competition/magicdata/ 

智源-高能对撞粒子分类挑战赛 

https://www.biendata.com/competition/jet/

????

现在,在「知乎」也能找到我们了

进入知乎首页搜索「PaperWeekly」

点击「关注」订阅我们的专栏吧

关于PaperWeekly

PaperWeekly 是一个推荐、解读、讨论、报道人工智能前沿论文成果的学术平台。如果你研究或从事 AI 领域,欢迎在公众号后台点击「交流群」,小助手将把你带入 PaperWeekly 的交流群里。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值