泰迪杯 A 题

  • 思路
  • 数据读取
  • 分析数据
    • 数据类型和缺失值
    • 缺失值处理(FLAG 除外)
    • 画图与统计描述
      • 计算各列的统计信息
      • 转换数据集(省内存走起)
      • 画图
        • KDE 图
        • 频率柱状图
  • 数据预处理
    • 对 int、类别(category) 类型的数据,查看其取值个数:
    • 报告截止日期 vs 截止日期?——单位是天吗?
  • 第一问(以‘制造业’为例)
    • 给数据加上行业标签
    • 离群数据处理
    • 标准化处理
    • 筛选指标
      • 根据偏相关系数进行筛选
      • 配合 FLAG 筛选
        • 原始数据?
        • 不变?显著大于?
        • 机器学习模型?
        • 特征权重?
        • 结果
  • 第一问最终结果
    • 过程
    • 结果
  • 第二问
    • 时序性?
    • 机器学习方法解决
      • 筛选最佳参数
      • 筛选最佳算法
      • 效果评价 + 挑出第6年数据造假的企业(股票编号)
    • 深度学习方法
      • 筛选网络拓扑
      • 结果输出
  • 第三问
    • 可以筛选出指标、且数据充足的行业,造假判断结果:
    • 数据不足,无法筛选指标的行业,造假预测结果:
      • 标准化+聚类
        • Kmeans 聚类 + 折臂图
      • 筛选影响指标
      • 机器学习方法
      • 意外
  • 代码与提问
  • 附件
    • IQR 诊断法
    • 偏相关系数
    • 类别不均衡问题
      • 单边选择
      • ADASYN
    • 交叉验证
    • 网格寻优
    • KMeans 聚类

本人专挑数据挖掘、机器学习和 NLP 类型的题目做,有兴趣也可以逛逛我的数据挖掘竞赛专栏

本人不会回访,不互关,不互吹,以及谢绝诸如此类事

赛题官网:https://www.tipdm.org/

思路

https://blog.csdn.net/weixin_42141390/article/details/116423465

返回目录

数据读取

原本这里采用 dask 库读取 csv 文件。因为 dask 库的好处是:1、分块;2、并行化计算

然而:我先尝试了用 pandas 读取数据,读入整个 CSV 占用内存 76 MB。算是比较小的了。鉴于其可直接放入内存之中,因此就不需要分块了,因为反而会因为与硬盘交互,消耗 CPU 资源。

经过测试,用 dask 读取数据,虽然可以分块,但需要启动并行化客户端,所以占用内存共 490 MB,而用 pandas 读取,仅占用了 230 MB,因此,选择 pandas 库。

%%time
df = dd.read_csv(r'../泰迪杯/泰迪杯 A 题/附件/附件2.csv')
df    # 可视化头五行数据


(补:本人读取完数据后,CPU 已经占用 78% 了… 惭愧)

返回目录

分析数据

数据类型和缺失值

print(df.dtypes)    # 查看各行的类型

各列的类型如下所示:

为何要没事找事,打印出数据类型呢?为了节省内存呀…,这里先按下不表。

再看数据各列的缺失值数量如何:

print(df.isna().sum())    #缺失值计算


经过详细分析,可以看到附件二还是挺良心的。那些类型为 int 的数据,没有缺失值,但一些类型为 float 的数据,就有较多的缺失值了。如下图所示,下面给出的这些列,类型都是 int 或者 category,他们都没有缺失值:

再看, FLAG(有无造假标签)居然也有缺失值。结合题目,那些 FLAG 带有缺失值的, 应该是需要我们在第二题、第三题中求解的 。所以,在数据预处理完毕后,我们还需要对表格,根据有无 FLAG 进行拆分。

先来看一下有多少数据没有 FLAG 吧:

可以看到,有 4153 条数据是没有 FLAG 的。

返回目录

缺失值处理(FLAG 除外)

由于那些数据类型为字符串(object)的列不包括缺失值,因此,用 0 代替缺失值,不会造成过大影响。且用 0 代替,能与现有的数据情况相匹配,本人曾将数据转为 excel 表格,并从中发现,有些数据虽然没有缺失值,但却用 0 去代替了,如下图所示:

所以,这里也用 0 去替代缺失值。

返回目录

画图与统计描述

计算各列的统计信息


我们从中得出如下信息:

  1. 由于股票代码最大编号>65536,所以在接下来的内存转换中,要用 uint64。
  2. 各列的量纲、以及方差都各不相同,需要我们进行标准化

返回目录

转换数据集(省内存走起)

根据各列的类型,我们可以在数据存储上再拉紧裤腰带,我们修改数据集的类型,将那些整数(单位为天、年、次)或者是类别型换成 int8、category 等等:

返回目录

画图

KDE 图

挑选 TFA_TURNOVER 列画出数据的 KDE 图(密度分布图):

频率柱状图


从这张图中可以看出:造假的企业和没有造假的企业,在数量上极度不均衡!

返回目录

数据预处理

对 int、类别(category) 类型的数据,查看其取值个数:

如下:

列 ACT_PUBTIME 即 实际披露时间 的取值个数共6个.
取值为:[3, 4, 2, 5, 6, 7]
列 PUBLISH_DATE 即 发布时间 的取值个数共6个.
取值为:[3, 4, 2, 5, 6, 7]
列 END_DATE_REP 即 报告截止日期 的取值个数共7个.
取值为:[2, 4, 3, 1, 5, 6, 7]
列 END_DATE 即 截止日期 的取值个数共6个.
取值为:[1, 2, 3, 4, 5, 6]
列 REPORT_TYPE 即 报告类型 的取值个数共1个.
取值为:[‘A’]
列 FISCAL_PERIOD 即 会计区间 的取值个数共1个.
取值为:[12]
列 MERGED_FLAG 即 合并标志:1-合并,2-母公司 的取值个数共1个.
取值为:[1]
列 ACCOUTING_STANDARDS 即 会计准则 的取值个数共1个.
取值为:[‘CHAS_2007’]
列 CURRENCY_CD 即 货币代码 的取值个数共1个.
取值为:[‘CNY’]

从这里大家可以看出什么呢?

  1. 造假标准肯定和那些取值仅一个的无关,也即可以直接排除:{ 报告类型、会计区间 、合并标志、会计准则、货币代码 }
  2. 第二题中的“第六年”,到底指的是:ACT_PUBTIME,还是 PUBLISH_DATE? 个人觉得应取发布时间。这点大家可以在论文中声明一下。
  3. 删除完 { 报告类型、会计区间 、合并标志、会计准则、货币代码 } 后,那些类型为 category 的列就没有了。所以,在后面的操作中,不需要进行 one-hot 编码。

大家也可以按照同样的方法,去判断权益乘数,但其取值有 6000+ 多个呢,所以就别将他转为类别变量了。

然后,大家请思考:那些没被删除的日期数据,他们可以转换为 category 类型吗? 这个问题还是先挂着,下一节分晓。

这里,我们来看到,发布时间有 2-7 年。那么,是不是每一个企业,都有 2-7 年的数据呢?

这个问题还是比较重要的,最完美的情况是,每一家企业都有 2-7 年的数据。这种情况下,在接下来的分析中,就不得不考虑数据是否有时序性了。换句话说,今年造假,是否和去年的数据有关(即使去年没造假)。

基于这个理由,我们首先来看看,每一个企业是否真的都有2-7年的数据:

df.groupby(by='TICKER_SYMBOL').count()

很让人瑟瑟发抖的是:大部分的企业都有 6 组数据,7−2+1=67-2+1 = 67−2+1=6。所以,记住这个结论,之后我们解第二问、第三问,都应该要至少提到时序性的问题。

返回目录

报告截止日期 vs 截止日期?——单位是天吗?

报告截止日期与截止日期,咋看之下好像是一样的,但仔细观察可以发现:报告截止日期总是大于截止日期,我们验证一下:

np.any(df.END_DATE_REP > df.END_DATE)

结果为 True !

换句话说:我们是否可以理解为,截止日期是规定的审计结束日期,而报告截止日期是审计结束之后,审计单位整理报告上报的日期

如果是这样,那么(报告截止日期-截止日期),即企业拖拉症状,应该与截止日期无关才对,即两者作为随机变量应是相互独立的。于是,我们就可以用列联表的方式,用统计检验的方法,来考察两者的分布是否独立。

若独立,我们就可以将报告截止日期、截止日期,用(报告截止日期-截止日期)(即企业拖拉情况)来替换。因为一个企业拖拉的程度,更能够体现出这个企业造假的态度。

这样子的变换看上去似乎没有太大意义,但要知道,我们的数据只有 2W,而行业大约 20 个,每一个企业还有 300+ 的列数。平均下来,每一列仅有 3 个数据(不严谨的说法),因此数据的密度是非常低的。能够降低列数,不单单可以提高效率,也可以提高准确率!

闲话少说,我们取原假设为:截止日期、(报告截止日期-截止日期)(下面用Δ\DeltaΔ代替)两个变量相互对立,首先构建用于独立检验的列联表:

df_for_table = df.loc[:,['END_DATE_REP','END_DATE']]
df_for_table['Delta'] = df_for_table.iloc[:,0] - df_for_table.iloc[:,1]
df_for_table = df_for_table.groupby(by=['END_DATE','Delta']).count()
df_for_table

从结果表中,我们可以看出,END_DATE 取 5 和 6 的时候(此时单位我们还不知,可能是天、月、年),Δ\DeltaΔ 最大值分别是 2 和 1。即,END_DATE_REP 的最大取值为 7。仔细回忆,我们的发布时间、实际披露时间的最大值也是为 7 。

于是,不难得出,END_DATE 和 END_DATE_REP 的单位是年!

为了分析方便,我们将 END_DATE 为 5 和 6 的删除,并构建列联表:

obs = np.zeros((4,4))
for i in range(4):tmp = df_for_table[4*i:4*(i+1)].values.reshape(-1)obs[i,:] = tmp
obs

构建好列联表后,进行假设检验,结果如下:
检验统计量的值为 3521.1458225666274
p-值为 0.0

根据假设检验的结果,由于 p值为 0,所以很遗憾,我们需要拒绝原假设,并有100%的把握,可以说拖延时间Δ\DeltaΔ 和截止时间是相关的。

不过,为了提高模型的辨识度(数据密度实在太低了),我们可以用 Δ\DeltaΔ 去替换 END_DATE_REP。

同上述分析,我们也需要考虑 PUBLISH_DATE 和 ACT_PUBTIME 之间的关系。来判断两者之间,是不是实际发布时间,大于等于发布时间?

np.any(df.ACT_PUBTIME >= df.PUBLISH_DATE)

结果是 True。于是,我们是否也可以列一个发布拖延时间:(实际发布时间-发布时间)。

如果判断出发布拖延时间,与发布时间,作为随机变量是相互独立的。那么,不仅可以为我们省下一列,而且,如果我们不用考虑数据的时序性,至少在做简单分析的时候可以这样。之所以可以不考虑时序性,是因为延迟时间,一定程度上代表了时序性的作用!

话不多说,先搭建一个列联表,结果如下:

然而,从这个表可以看出,原来所有企业的实际发布时间,和发布时间都是相同的。不过也好,借此机会可以删除 ACT_PUBTIME 列。

同时我们也看到,PUBLISH_DATE 的取值为 2~7,应当是一个索引数据。用 SQL 语言的话说,它和 TICKET_SYMBOL 构成表格的主键。所以,不能将其转为 category 类型,更不用说对他进行 one-hot 编码了

在接下来的问题中,它和股票代码应是用来识别数据,不参与运算的。同时,它们两个实际上对是否造假所起到的作用和信息量,都包含在其他列里面了。所以,在之后的分析中,这两列不参与分析。

但还是需要考虑,如果忽略了 PUBLISH_DATA(发布时间),那么就等于丢弃了数据的时序性,这样好吗?

对于第一问,我们不考虑时序性。因为我们的指标,是对整个行业来筛选的。若考虑时序性,那么结果只能局限于企业而非行业。

对于第二问和第三问,我们无法考虑时序性,因为我们需要解决类别不均衡问题,后文会谈到。

返回目录

第一问(以‘制造业’为例)

确定数据是否造假的决定指标,本质上是一个数据降维的问题。首先,为了便于数据的处理,首先要对数据进行标准化。

但在标准化前,首先应该考虑:数据标准化需不需要根据行业,采用不同的标准化基础?还是将整个表格直接标准化?答案当然是前者。毕竟,不同行业间,我们很有理由认为量纲各不同。

给数据加上行业标签

首先读取附件1:

同时可以从附件1 中看出,给出的行业一共有 19 个。

要如何给数据附上标签呢?这就要用到 SQL 里的 join 操作了。但要怎么 join 呢?是左连接、右连接,还是内连接?

由于有些企业没有在附件一中有具体的分类,因此,可能有人再考虑用左连接的自然连接。但你要知道,问题二、问题三都是求其他行业的,所以如果你狠心一点,直接用 inner join(内连接),将那些没有归入行业的企业划掉!!

(本人用内连接)附上标签以后,就要着手标准化数据了。

准化的方式一般有两种:

  1. 用最大值、最小值
  2. 用均值、方差

由于上述标准化都对离群值敏感,所以首先要排除离群数据:

离群数据处理

离群值数据,当然要以行业为单位考虑。毕竟,有些行业某个列的总体数值偏高,总不能把他们都删了吧。

据分析,这些报表造假也好,详细记录的也好,应该都不会偏离正常值太多。但如果详细记录却出现离群值的,一般是因为数据录入出现错误。此外,造假与否本身也会产生离群值,所以,在离群值识别的时候,我们要制定一个很宽松的标准。
然后,我们将离群数据删除!

这里采用的离群值识别算法是:IQR 方法。若一整行中,若果全部行通过 IQR 诊断为离群值,则删去。

标准化处理

这里采用均值、方差标准化(标准化后均值=0,方差=1)处理。之所以采用这种方法,是因为最大、最小标准化难以体现数据的差异性。

在标准化时,要根据行业分组进行,原因在于,每一个行业可能的量纲不同。

我们把数据拆分成两部分:

  1. df_flag : 指那些带有 FLAG 标签的数据
  2. df_noflag:指那些 FLAG 为 NAN 的数据

然后,将 df_flag、df_noflag 按照行业,拆分成 19 个子集(行业共19个嘛)。再对每一个子集进行标准化。

注意,标准化时候,是将 df_flag、df_noflag 一起标准化(同一行业):
xij′=xij−xiˉstd(xi)x_{ij}^\prime = \frac{x_{ij}-\bar{x_i}}{std(x_i)} xij′​=std(xi​)xij​−xi​ˉ​​

返回目录

筛选指标

筛选指标其实,就是叫我们进行数据降维,为了方便阐述,以后都会把输入变量称为特征1

根据偏相关系数进行筛选

第一问叫我们找决定指标,而我们知道,一些指标(特征)自身相互决定。因此,或多或少带有一定的冗余,所以在进行进一步地筛选之前,我们需要先删除多余的指标。

偏相关系数度量了两个变量,在刨除其他变量后的线性相关特性2。所以,这里计算了指标两两的相关性,构成一个偏相关系数矩阵:

(上述矩阵将自身与自身的相关系数设为 0)然后,再根据相关系数矩阵,遍历所有特征,若两个特征相关性大于 0.8 ,则删除其中一个。

一顿操作下来,数据变成这样(以制造业为例):

209 列还是加上了 (发布时间、股票代码、所属行业和 FLAG 的),所以最后特征只剩下 205 列,不过这个数字还是比较大的。

返回目录

配合 FLAG 筛选

根据相关性的筛选是一种“窝里斗”的筛选。现在我们要结合 FLAG 来筛选了。

我们要找的是,决定企业是否造假的决定性指标。所以,如果我们搭建一个机器学习模型,而这个机器学习模型根据现有特征,和 FLAG 构成的数据进行训练,然后得出模型的精确度为 sss。然后再删除一些特征,再重复上一个过程。若模型的精确度不变,则删去特征,直到精确度明显降低为止:

Created with Raphaël 2.2.0开始原始数据使用某个机器学习算法用数据训练,得到机器学习模型得出模型精确度 s1根据机器学习模型对特征权重的分配删除一些权重小特征用相同的机器学习算法用删后的数据,训练模型得出精确度 s2s1>s2?结束yesno

返回目录

原始数据?

在进行机器学习模型训练的时候,由于数据的类别不均衡,所以需要我们通过采样的方法,减少主类别的数量;增加次类别的数量,从而达到主类别、次类别的平衡。

举个例子,假如 1% 的企业造假,99%的企业不造假。那么,一个只会回答 不造假 的模型,就能达到 99% 的精确度…

为了解决这个问题,这里采用单边选择法,先进行欠采样,再用 ADASYN 法进行过采样。最后得出 造假:不造假 = 1:1.

一顿操作下来,数据变成这样(以制造业为例):

数据量大约翻了一倍

返回目录

不变?显著大于?

若模型的精确度在删除特征前后不变,则保留?那么不变是什么意思呢?我们知道,模型的训练算法的收敛是具有偶然性的。所以每一次训练的结果都不相同,精确度也自然不同,那么怎么才能叫不变呢?

首先,在训练模型,获得精确度的时候,当然不能做一次。这个过程,要重复做 10 次,怎么做呢?交叉验证,最后得到 10 个精确度。删除特征后,再重复一次,再得到 10 个精确度。

然后,将这两组精确度,进行单边 T 检验。原假设为:两组数据的均值不变;备选假设为:删除前精确度的均值 > 删除后。

返回目录

机器学习模型?

用什么机器学习模型呢?应该考虑如下几点:

  1. 简单,快速
  2. 能进行非线性分类
  3. 能评估每一个特征的权重(对结果的重要性)

综上,我觉得可以用决策树、SVC。但是 SVC 在非线性分类方面做得不是很好,且训练比较复杂,所以本文用的决策树

返回目录

特征权重?

若采用决策树的话,特征权重就可以用每个特征的 Gini 系数来代替了。

若用 SVC 的话,可以考虑使用 SVC 模型的每个特征的系数。

返回目录

结果

以“制造业”为例(强调了3次了),使用上述算法,最后的筛选结果是:

迭代终止,终止原因是:特征只剩一个啦!
筛选过后的数据: [[-1.59929924 1.30480919]
[-1.59929924 -0.05784333]
[-1.0068208 -0.34304967]

[ 0.77061452 -0.34358523]
[ 0.77061452 -0.27621283]
[ 0.77061452 -0.366081 ]]
筛选过后的数据矩阵的大小: (20940, 2)
决定指标: Index([‘END_DATE’, ‘BASIC_EPS’], dtype=‘object’)
筛选前,模型的精确度: 0.847898758357211
最后一次筛选,模型的精确度:(本次筛选不采纳) 0.8322349570200573
相差: 0.015663801337153616
历史精确度: [0.847898758357211, 0.8554441260744985, 0.8534383954154728, 0.8585482330468004, 0.8681470869149951, 0.8322349570200573]

所以,最终筛选的指标是:[‘END_DATE’, ‘BASIC_EPS’]

筛选过程中,平均精确度如下:

返回目录

第一问最终结果

不是所有行业的数据都像制造业那样,都有 1W+ 的数据。有一些行业的数据,只有个位数。对于这些数据,我们在考虑解决类别不均衡的问题时,要特别注意。比如不能再用欠采样了,过采样时,用于产生新数据的 K 近邻个数肯定不能大于样本量。

过程

解决的过程如“制造业”一样:

返回目录

结果

对于那些数据量比较少的,我们往结果前加一个感叹号

制造业 行业财务数据造假的决定指标有: END_DATE, OTH_NCA, BASIC_EPS, ASSETS_IMPAIR_LOSS
批发和零售业 行业财务数据造假的决定指标有: C_FR_CAP_CONTR, BASIC_EPS, NOPERATE_EXP
信息传输、软件和信息技术服务业 行业财务数据造假的决定指标有: C_FR_OTH_FINAN_A, N_C_PAID_ACQUIS, BASIC_EPS
!建筑业 行业财务数据造假的决定指标有: GOODWILL, REFUND_OF_TAX, N_C_PAID_ACQUIS, C_FR_MINO_S_SUBS, OTH_GAIN
房地产业 行业财务数据造假的决定指标有: AVAIL_FOR_SALE_FA, BASIC_EPS, NCL_WC, N_TAN_A_TL
!交通运输、仓储和邮政业 行业财务数据造假的决定指标有: N_CF_FA_PROPT, R_TR
!采矿业 行业财务数据造假的决定指标有: Delta_Date, R_D
金融业 行业财务数据造假的决定指标有: LT_AMOR_EXP, AP, C_FR_OTH_INVEST_A, C_FR_OTH_OPERATE_A
农、林、牧、渔业 行业财务数据造假的决定指标有: OTH_RECEIV, MINORITY_INT
教育 行业数据太少, 难以筛选
!电力、热力、燃气及水生产和供应业 行业财务数据造假的决定指标有: INVEST_REAL_ESTATE, OTH_COMPRE_INCOME, ASSETS_DISP_GAIN
文化、体育和娱乐业 行业数据太少, 难以筛选
卫生和社会工作 行业数据太少, 难以筛选
水利、环境和公共设施管理业 行业数据太少, 难以筛选
!科学研究和技术服务业 行业财务数据造假的决定指标有: N_CF_FR_INVEST_A, N_CF_IA_PROPT, N_CF_OPA_PS_YOY, INV_INC_TR
租赁和商务服务业 行业数据太少, 难以筛选
综合 行业数据太少, 难以筛选
住宿和餐饮业 行业数据太少, 难以筛选
居民服务、修理和其他服务业 行业数据太少, 难以筛选

返回目录

第二问

求“第六年”财务造假的企业,也就是要求我们,根据第7年发布的报表,来判断企业是否造假。

注意,这里用的一定要是 发布时间为 7(第7年)的报表。因为报表是一般是年底的呀,而企业是否造假,指的是在出报表之前的那段时间。

其实这一点,数据也告诉我们了。我查了一下,那些 FLAG 为 NAN(带预测),但发布时间为 6 的数据,结果一条都没有。有的只是发布时间为 7 的。

返回目录

时序性?

在筛选数据和特征的时候,特别是筛选特征时,我们需要解决类别不均衡问题。另外,在训练机器学习的时候,当然也需要解决这个问题。

而,在解决类别不均衡问题时,欠采样、过采样早已破坏了数据的时序性。所以,在完后的分析中,便不再考虑数据的时序性了。

返回目录

机器学习方法解决

根据“天下没有免费午餐”定律,在选择一个特定的机器学习算法时,需要从大量的算法中筛选最佳的算法。

我们从下面这些算法中筛选最优算法:

算法 逻辑回归 k近邻算法 朴素贝叶斯分类器 支持向量机分类 决策树 随机森林 AdaBoost
符号 lg kNN NB SVC dtc rf ada

返回目录

筛选最佳参数

不过要从上述算法中,筛选最佳算法,首先要筛选算法的最合适参数。筛选的方法是网格寻优法

算法 参数网格
lg
kNN {‘n_neighbors’:[3,5,7,9,11,13,15,17,19,21,23,25,27]}
NB
SVC grid = { ‘C’:[0.1,0.25,0.5,0.75,1,1.25,1.5,1.75,2,2.25,2.5,2.75,3,3.25,3.5],‘kernel’:[‘linear’,‘rbf’,‘poly’] }
dtc grid = {‘max_depth’:[4,9,14,19,24,29,34,39,44,49,54,59,64,69,74,79], ‘ccp_alpha’: [0,0.00025,0.0005,0.001,0.00125,0.0015,0.002,0.005,0.01,0.05,0.1]}
rf 基模型个数:5,15,25,35,45,50,65,75,85,95
ada 基模型个数:5, 15,25,35,45,50,65,75,85,95,105,115,125,135,145,155

最佳结果如下:

返回目录

筛选最佳算法

得到最佳参数之后,就可以筛选最佳的算法了。这里我们将所有的最佳参数,用交叉验证,对每一个算法,算出 10 组精确度和均值,结果如下:

可见:knn 和 dtc 的效果最好。虽然看起来 knn 最好,但记住,我们解决类别不均衡时,用的过采样 ADASYN 产生新数据。所以,用 knn 的效果好,不一定用在其他数据好。所以,这里选择 dtc。

返回目录

效果评价 + 挑出第6年数据造假的企业(股票编号)

将数据按 7:3 拆分成训练集、测试集。用训练集训练 dtc,用测试集评价模型,评价指标还用精确度。之后,用模型求解造假的股票,结果如下所示:

(制造业为例)

返回目录

深度学习方法

这里将构建一个简单的多层感知器,来搭建深度学习模型。

筛选网络拓扑

当然,如何搭建多层感知器呢?神经网络的拓扑结构如何?

根据“没有午餐”定律,我们需要根据模型效果参数。同上,这里再次使用 5 折交叉验证+网格寻优,来筛选最合适的网络拓扑和参数。

参数表格如下:

参数 取值 含义
units_list [[8,16,8],[5,10,5],[3,8,3]] 隐藏层的层数和对应的神经元个数
‘optimizer’ rmsprop, adam 寻优算法
activation ‘relu’, ‘sigmoid’ 激活函数
init init_uniform, init_normal 节点参数初始化方法
epochs 150, 100, 50 训练迭代次数
batch_size 200, 100, 50 batch 大小
rate 0, 0.1, 0.2 dropout 正则化率

经过筛选,可得最佳的参数是:

参数 取值 含义
units_list [8,16,8] 隐藏层的层数和对应的神经元个数
‘optimizer’ adam 寻优算法
activation relu 激活函数
init init_uniform, 节点参数初始化方法
epochs 200 训练迭代次数
batch_size 100 batch 大小
rate 0.1 dropout 正则化率

返回目录

结果输出

训练过程中,绘制训练集、测试集的损失(交叉熵),以及精确度,随着训练迭代次数的变化,如图所示:

结果如下所示: 多层感知器的最高精确度(测试集)为 0.97522,检验出来的造假企业如下:

返回目录

第三问

第三问咋看一下和第二问没有区别,其实对于有些行业,确实没有区别。但对于其他行业,特别是那些数据量较小,我们在第一问中无法筛选出来决定性指标的那些,就成为难题了。

对于那些我们在第一问,求出决定性指标的,且前面没有带 感叹号 的,我们用第二问的方法就可以解决,机器学习和深度学习皆可。

但对于缺乏数据的,也即没办法找出决定指标,或者带感叹号的,由于数据量非常少,因此,我们需要把他们集结到一起,构成大表。

直接构成一张大表,肯定是不行的,因为没有考虑各行业的区别。因此,一个解决的好办法是:聚类!

先对数据进行聚类,然后用所属聚类簇代替行业,用第一问的方法筛选决定指标,用第二问的方法求解问题,于是乎,问题解决!

可以筛选出指标、且数据充足的行业,造假判断结果:

用第二问的方法,可得:



返回目录

数据不足,无法筛选指标的行业,造假预测结果:

带感叹号的,或者是数据不足以筛选的行业,他们分别是:【建筑业、交通运输、仓储和邮政业、采矿业、教育、电力、热力、燃气及水生产和供应业、文化、体育和娱乐业、卫生和社会工作、水利、环境和公共设施管理业、科学研究和技术服务业、租赁和商务服务业、综合、住宿和餐饮业、居民服务、修理和其他服务业】

将上述行业经过预处理的数据读入 Python 中,共有 2530 行(实在不多!!)

返回目录

标准化+聚类

为了避免聚类效果受到量纲的影响,首先将 2530 个数据进行均值、方差标准化,使得其均值为 0,方差为 1。

返回目录

Kmeans 聚类 + 折臂图

Kmeans 聚类需要事先选择聚类簇数,为此,这里采用折臂图的方法,根据聚类效果筛选聚类簇数,画出折臂图如下:

根据上述折臂图,可见聚类簇选 2 比较合适。(也可以选择 4)

返回目录

筛选影响指标

把属于同一聚类簇的数据,视为一个行业,用 第一问 的方法,找出该聚类簇的所属指标(下图为属于聚类簇 0 的数据的决定指标):

返回目录

机器学习方法

使用第二问的机器学习方法,求出所属聚类簇的最佳模型和最佳参数,并得出第六年造假企业:

返回目录

意外

我发现,聚类簇 1 不包含造假数据,所以无法训练机器学习模型。故而筛选指标,求出第六年造假的企业就无从谈起。但是,聚类簇 1 中, FLAG == NAN 也就是待求解的数据,仅有 3 个!而且,聚类 1 中 FLAG 已知的数据都是 0, 所以,很大概率可以认定这些数据并非造假。

返回目录

代码与提问

若需要代码,请点赞、关注、私信、说明题目和年份

如果有其他问题,请到评论区留言,私信提问,概不回答。也在此鼓励大家独立思考。

本人不会回访,不互关,不互吹,以及谢绝诸如此类事

最近总结了和其他人的私聊,以及一些比较爆笑的东西,以做笑谈,供人饮酒:
一个小博主的奇葩经历

返回目录

附件

IQR 诊断法

IQR 诊断法是一种筛选离群值的算法。针对某一列,求出他的三位分数 Q3,Q1Q3,Q1Q3,Q1, Q3>Q1Q3>Q1Q3>Q1。求出 IQR=Q3−Q1IQR=Q3-Q1IQR=Q3−Q1,之后若 x>Q3+1.5×IQRx > Q3+1.5\times IQRx>Q3+1.5×IQR 或 x<Q1−1.5×IQRx< Q1 - 1.5\times IQRx<Q1−1.5×IQR,则判断 xxx 属于离群值

偏相关系数

偏相关系数不同于完全相关系数,以 Pearson相关系数为例。两个特征 x1,x2x_1, x_2x1​,x2​ 的 Pearson 相关性系数的求法是:
ρ=Cov(x1,x2)Var(x1)⋅Var(x2)\rho = \frac{ Cov(x_1,x_2) } {\sqrt{Var(x_1)\cdot Var(x_2)}} ρ=Var(x1​)⋅Var(x2​)​Cov(x1​,x2​)​

表示 x1,x2x_1,x_2x1​,x2​ 两者的线性相关性,但是,若 x1,x3x_1, x_3x1​,x3​ 有关,x2,x3x_2, x_3x2​,x3​ 有关,那么 ρ12\rho_{12}ρ12​ 也会非常大。

而偏相关系数则不同,它排除了 x1,x2x_1,x_2x1​,x2​ 以外的所有变量的影响。

具体做法是,对于除了 x1,x2x_1, x_2x1​,x2​ 以外已知的变量 x3,x4,⋯,xnx_3,x_4,\cdots,x_nx3​,x4​,⋯,xn​,用 x3,x4,⋯,xnx_3,x_4,\cdots,x_nx3​,x4​,⋯,xn​的线性拟合去拟合 x1,x2x_1, x_2x1​,x2​ 得到 x1′(x3,x4,⋯,xn)x_1^\prime(x_3,x_4,\cdots,x_n)x1′​(x3​,x4​,⋯,xn​) 和 x2′(x3,x4,⋯,xn)x_2^\prime(x_3,x_4,\cdots,x_n)x2′​(x3​,x4​,⋯,xn​),然后求:x1−x1′x_1 - x_1^\primex1​−x1′​ 和 x2−x2′x_2-x_2^\primex2​−x2′​ 的完全相关系数即可3

返回目录

类别不均衡问题

假如 1% 的企业造假,99%的企业不造假。那么,一个只会回答 不造假 的模型,就能达到 99% 的精确度…

单边选择

单边选择旨在删除:冗余数据、边界数据、噪声数据。

单边数据、噪声数据的取出是用:Tomek linke

冗余数据的取出是用 C 集合 + 1NN 模型。

具体过程如下:

何谓 Tomek link?
设两个不同类别的样品 x,yx,yx,y,他们的距离为 δ(x,y)\delta(x,y)δ(x,y),若不存在一个 zzz 使得 δ(x,z)<δ(x,y)orδ(z,y)<δ(x,z)\delta(x,z) < \delta(x, y) ~ or~ \delta(z,y) < \delta(x, z)δ(x,z)<δ(x,y) or δ(z,y)<δ(x,z),则 (x,y)(x,y)(x,y) 是一对 Tomek link。
何谓 1NN + C集?
设训练集为 S,从中筛选出所有小类别数据,和一个随机从大类别数据中筛选出来的样品,构成 C 集。根据 C 集训练一个 k = 1 的 kNN 算法,并用该 kNN 判断 S。将误分类的数据加入 C′C^\primeC′ 中。

于是,若我们先用 C′C^\primeC′ 代替 S,再删去 C′C^\primeC′ 中的 Tomek Link 的主类别数据,就完成了单边选择(过滤主类别)

返回目录

ADASYN

ADASYN 能够将少数类个体,和多数类(主类别)个体的数目,自动地拉到同等数量。

设主类别的样本为 SSS, 少数类样本为 sss,ttt 为样本 xxx 的 kkk 个近邻中,属于主类别的样品们。设 G=len(S)−len(s)G=len(S)-len(s)G=len(S)−len(s)。
forxiins:计算len(t),令ri=len(t)/kforxiins:gi=ri∑ilen(s)ri×Gforjinrange(gi):从xi的k个近邻中选择一个xj,令xnew=xi+rand(0,1)(xj−xi)\begin{aligned} for~ ~ &x_{i}~ in ~~s: \\ &计算 len(t), \\ &令 r_i= len(t) /k \\ for~ ~ &x_{i}~ in ~~s: \\ & g_i = \frac{r_i}{\sum_i^{len(s)}r_i}\times G \\ &for ~ ~ j ~ ~in ~ ~ range(g_i):\\ &~~ ~ ~ ~ ~ 从 x_i 的 k 个近邻中选择一个 x_j,令 x_{new} = x_i + rand(0,1)(x_j-x_i) \end{aligned} for  for  ​xi​ in  s:计算len(t),令ri​=len(t)/kxi​ in  s:gi​=∑ilen(s)​ri​ri​​×Gfor  j  in  range(gi​):      从xi​的k个近邻中选择一个xj​,令xnew​=xi​+rand(0,1)(xj​−xi​)​
注意:若 xix_ixi​ 周围的主类别个数越多,则其需要产生的新样本越多。

交叉验证

交叉验证一般用于缓解随机性引发的问题:一般用于评价模型,筛选模型或参数。

返回目录

网格寻优

网格寻优实际上是一种遍历的方法,用于筛选模型的最佳参数。

KMeans 聚类

K 均值聚类是非常朴素的聚类法:

K 均值聚类将包含 n 个样品的数据集 XXX 分成 k 个部分,每个部分的均值叫聚类中心 μj\mu_jμj​。

聚类的原则是,让 k 个聚类簇的 inertia 最小化, inertia 的计算公式如下:
∑i=0nmin⁡μj∈C(∣∣xi−μj∣∣2)\sum_{i=0}^{n}\min_{\mu_j \in C}(||x_i - \mu_j||^2) i=0∑n​μj​∈Cmin​(∣∣xi​−μj​∣∣2)


  1. 特征 feature 是机器学习的术语,也就是输入变量 ↩︎

  2. 若变量呈正态分布,则相关性也指其他非线性相关性 ↩︎

  3. 根据数学化简,可以用矩阵的行列式的方法求解 ↩︎

2021 泰迪杯 A 题相关推荐

  1. 2021泰迪杯A题-通讯产品销售和盈利能力分析_任务一解题代码

    import pandas as pd 统计 data = pd.read_excel('非洲通讯产品销售数据.xlsx',engine = 'openpyxl',sheet_name = 0) da ...

  2. 2020年泰迪杯C题智慧政务中的文本数据挖掘应用--论文+全部源码分享

    5.2问题二模型的建立与求解 本题要求针对热点问题进行挖掘,主要目的是从群众留言中挖掘出热点问题.也就是给每一条留言都量化一个热度指数.并且根据热度指数进行排序,从而获取热度较高的评价问题.对于问题热 ...

  3. 【第十一届泰迪杯B题产品订单的数据分析与需求预测产品订单的数据分析与需求预测 】第二大问代码分享+解题思路(EDA数据再探索+LightGBM模型)

    [第十一届泰迪杯B题产品订单的数据分析与需求预测]第二大问代码分享+解题思路(EDA数据再探索+LightGBM模型) 写在前面: ​ 拖了这么长时间,一方面是我在找实习面试准备.另一方面是在做第二问 ...

  4. 【第十一届“泰迪杯”数据挖掘挑战赛】泰迪杯c题爬虫采集数据(源码+数据)

    ["第十一届"泰迪杯"数据挖掘挑战赛-- C 题:泰迪内推平台招聘与求职双向推荐系统构建(采集数据)] 问题: 数据详情: 根据工作id获取详细数据(1571条).csv ...

  5. 泰迪杯C题第三问[文本有效性分析] (1)

    导入库 import re # 正则表达式库 import collections # 词频统计库 import numpy as np # numpy数据处理库 import jieba # 中文分 ...

  6. 2021泰迪杯数据分析技能赛B题-肥料登记数据分析

    调用模块: import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns p ...

  7. 第8届泰迪杯C题问题总结

    文章目录 写作模板问题 从网上下载了一个牛逼哄哄的模板,用 Winedit 打开时,却跳出错误弹出.我顿时懵逼了!!! 编译模板时,跳出 Improper alphabetic constant 错误 ...

  8. 智能阅读模型的构建(第六届泰迪杯C题)

    项目描述: 构建智能阅读模型主要通过两个方法来实现,第一个是TF-IDF的变种--TFC-ICF,TFC-ICF较于TF-IDF是将一个问题的所有答案看成一个整体,类比于TF-IDF文本分类的文件夹, ...

  9. 第十一届泰迪杯B题:产品订单的数据分析与需求预测

    赛题描述 一.问题背景 近年来企业外部环境越来越不确定,复杂多变的外部环境,让企业供应链面临较多难题.需求预测作为企业供应链的第一道防线,重要程度不言而喻,然而需求预测受多种因素的影响,导致预测准确率 ...

  10. 2020泰迪杯C题解题流程

    注:本文为赛前所写,仅队内提供大致思路,和实际的解题流程有一定出入,仅供参考,有一些错误,笔者并没有更正(主要是没空),如想深入交流请私信. 1.对留言进行分类 1.1对数据进行分析. 观察数据集规模 ...

最新文章

  1. wake_lock_timeout的使用方法【转】
  2. 牛腩新闻发布系统(2)使用存储过程查询表
  3. 一部IT电影,《反托拉斯行动》,主角加里-文斯顿(蒂姆·罗宾斯饰)影射比尔·盖茨...
  4. 成功解决File frozen importlib._bootstrap, line 219, in _call_with_frames_removed ImportError: DLL lo
  5. postman关闭ssl验证_【第5期】springboot:苹果内购服务端验证
  6. Spring Data JPA: 实现自定义Repository
  7. 修改APACHE的默认站点
  8. 51nod1363 最小公倍数之和
  9. Python使用总结
  10. codeblock添加tools实现git log查看
  11. MATLAB学习之泰勒展开(四)
  12. matlab混沌信号 仿真,MATLABSimulink混沌理论仿真.doc
  13. Unity 编辑器开发实战【Editor Window】- Replacer 替换器
  14. 集合-HashTable
  15. 打印小册子中断了怎么办
  16. 正版2008服务器多少钱,Windows server 2008 R2正版报价多少
  17. 【观察】智能+新时代,智慧酒店未来该何去何从?
  18. 机械键盘按键失灵解决办法(亲测有效,不用换不用拆,5分钟搞定)
  19. 面试题:为什么ConcurrentHashMap的读操作不需要加锁?
  20. Java模板设计模式

热门文章

  1. Linux系统中Tomcat下载+安装+测试【一看就会】
  2. 【数据结构与算法C语言版】基础代码整理 思维导图
  3. 智能算法——遗传算法原理、应用汇总
  4. 电商工具箱之阿里巴巴获取商品
  5. 1688API接口,item_get_app - 获取1688app上原数据
  6. linux通过端口测试网速,【转】Linux下测试网速的工具
  7. STM32F407 FSMC驱动NAND FLASH MX30LF2GE8AB 附带测试程序链接
  8. ESET NOD32 Antivirus – 免费 3个月/ 3PC
  9. Azkaban安装部署(附资源)
  10. oracle下载jdk需要注册怎么办? jdk8下载