2022 National Mathematical Modeling-C Question Review Composition Analysis and Identification of Ancient Glass Products

No mês passado, participei do Concurso Nacional de Modelagem Matemática e fiz o problema C. Tive a sorte de ganhar o provincial e enviá-lo para o prêmio nacional. Resolvi o programa e revisei novamente. Aqui vou mostrar brevemente os pequenos partes da primeira, segunda e terceira questões Idéias e processos para resolução de problemas , bem como programas em Python.

Ler e exibir dados:

# 读取数据
data1 = pd.read_excel('附件.xlsx',sheet_name='表单1')
data2 = pd.read_excel('附件.xlsx',sheet_name='表单2')
data3 = pd.read_excel('附件.xlsx',sheet_name='表单3')

dados1: 

 dados2:

dados3:

Pré-processando:

1) Preencha os valores faltantes de cor no formulário 1 e os valores faltantes de composição química no formulário 2

Agrupe os três recursos, exceto a cor: tipo, decoração e desgaste da superfície, e extraia o modo da cor para preencher a cor ausente do ponto de amostra específico.

def get_yanse(x):
    return x.value_counts().index[0]
display(data1.groupby(['类型','表面风化','纹饰'])['颜色'].agg(get_yanse,))
"""
类型  表面风化  纹饰
铅钡  无风化   A     浅蓝
          C      紫
    风化    A     浅蓝
          C     浅蓝
高钾  无风化   A     蓝绿
          C     浅蓝
    风化    B     蓝绿
Name: 颜色, dtype: object
"""

data1[data1['颜色'].isna()]
""""""
文物编号	纹饰	类型	颜色	表面风化
18	19	A	铅钡	NaN	风化
39	40	C	铅钡	NaN	风化
47	48	A	铅钡	NaN	风化
57	58	C	铅钡	NaN	风化
""""""

# 发现缺失数据的对应众数颜色均为浅蓝,使用浅蓝进行填充
data1.fillna('浅蓝',inplace=True)

 De acordo com o significado da pergunta, preencha o valor ausente da composição química no Formulário 2 com 0

data2.fillna(0,inplace=True)

2) Extraia as informações do número da relíquia cultural nas características dos pontos de amostragem da relíquia cultural nos dados do formulário 2 e vincule o formulário 1 através das informações do número da relíquia cultural 

# 提取文物采样点中的文物编号信息
def get_number(x):
    number = re.findall('\d*',x)[0]
    number = int(number[1]) if number[0]=='0' else int(number)
    return number
data2['文物编号'] = data2['文物采样点'].apply(get_number)

# 通过文物编号关联表单1、表单2
data_merge = pd.merge(data1,data2,on = '文物编号')

3) Remova componentes químicos e dados inválidos fora de 85%~105%

Ver dados inválidos:

data_merge[~((zong_chengfen >= 85) & (zong_chengfen <= 105))]

 

# 取出有效数据
data_merge = data_merge[(zong_chengfen >= 85) & (zong_chengfen <= 105)]
# data_merge.to_excel('问题一连接两表并处理后数据.xlsx')

 4) Para os dados combinados, obtenha o tipo de intemperismo do ponto de amostragem de acordo com a descrição da informação no anexo do título, o número da relíquia cultural e a informação do ponto de amostragem da relíquia cultural.

# 获取采样点风化类型信息
# 第一步
def get_fh(x):
    list_ = list(filter(lambda x:len(x)>0, re.findall('[^\d*]*',x)))
    return list_[0] if list_ else np.nan
data_merge['采样点风化类型'] = data_merge['文物采样点'].apply(get_fh)
data_merge['采样点风化类型'].value_counts()
"""
部位       10
未风化点     10
严重风化点     3
Name: 采样点风化类型, dtype: int64
"""

# 第二步
data_merge.replace({'部位':np.nan},inplace=True)
data_merge['采样点风化类型'] = data_merge['采样点风化类型'].fillna(data_merge['表面风化'])
data_merge['采样点风化类型'].value_counts()
"""
风化       29
无风化      25
未风化点     10
严重风化点     3
Name: 采样点风化类型, dtype: int64
"""

# 第三步
data_merge['采样点风化类型'] = data_merge['采样点风化类型'].replace({'无风化':'未风化点', '风化':'风化点'})
data_merge['采样点风化类型'].value_counts()
"""
未风化点     35
风化点      29
严重风化点     3
Name: 采样点风化类型, dtype: int64
"""

Exibir:

with sns.color_palette('rainbow'):
    # 作者封装绘图程序,需要源程序可在作者博客'seaborn'封装中寻找
    count_pieplot(data_merge,1,2,vars = ['采样点风化类型'],hue = '类型',show_value=True)

Pergunta um:

1. Combinado com o tipo de vidro, analise as leis estatísticas de se existem componentes químicos desgastados na superfície de amostras de relíquias culturais

        Para vidro com alto teor de potássio/chumbo-bário, analise estatisticamente a diferença na composição química entre amostras não intemperizadas e intemperizadas para explorar a lei estatística da composição química intemperizada. Use gráficos de linha e gráficos de caixa para análise. Os gráficos de caixa podem não apenas mostrar pontos de amostragem. faixa de distribuição da composição química e, ao mesmo tempo, o valor médio, valor mínimo e máximo podem ser analisados ​​de forma concisa.

Análise do gráfico de linha: Retire o valor médio de cada composição química com ou sem intemperismo, desenhe um gráfico de linha e observe a diferença de composição química com ou sem intemperismo.

# 提取化学名称
def get_huaxue(x):
    return re.findall('\((.*)\)',x)[0]

plt.figure(figsize=(10, 8))
plt.subplot(211)
plt.plot(range(14),data_merge.query("采样点风化类型 == '风化点' & 类型 == '高钾'").iloc[:,6:-1].mean(),label = '风化')
plt.plot(range(14),data_merge.query("采样点风化类型 == '未风化点' & 类型 == '高钾'").iloc[:,6:-1].mean(),label = '未风化')
plt.legend()
plt.xticks(range(14),list(map(get_huaxue, data_merge.iloc[:,6:-1].columns)),fontsize = 10)
plt.title('高钾风化与未风化的各成分均值统计对比图',fontsize = 15)
# plt.savefig('高钾风化与未风化的各成分均值统计对比图')

plt.subplot(212)
plt.plot(range(14),data_merge.query("采样点风化类型 == '风化点' & 类型 == '铅钡'").iloc[:,6:-1].mean(),label = '风化')
plt.plot(range(14),data_merge.query("采样点风化类型 == '严重风化点' & 类型 == '铅钡'").iloc[:,6:-1].mean(),label = '严重风化')
plt.plot(range(14),data_merge.query("采样点风化类型 == '未风化点' & 类型 == '铅钡'").iloc[:,6:-1].mean(),label = '未风化')

plt.legend()
plt.xticks(range(14),list(map(get_huaxue, data_merge.iloc[:,6:-1].columns)),fontsize = 10)
plt.title('铅钡风化与未风化的各成分均值统计对比图',fontsize = 15)
# plt.savefig('风化与未风化的各成分均值统计对比图')
plt.subplots_adjust(hspace=0.35)
plt.savefig('风化与未风化的各成分均值统计对比图')

Análise de Boxplot: Retirar Separadamente

def get_colors(color_style):
    cnames = sns.xkcd_rgb
    if color_style =='light':
        colors = list(filter(lambda x:x[:5]=='light',cnames.keys()))
    elif color_style =='dark':
        colors = list(filter(lambda x:x[:4]=='dark',cnames.keys()))
    elif color_style =='all':
        colors = cnames.keys()
    colors = list(map(lambda x:cnames[x], colors))
    return colors

# 封装箱线图
def boxplot(data, rows = 3, cols = 4, figsize = (13, 8), vars  =None, hue = None, width = 0.25,
            order = None, color_style ='light',subplots_adjust = (0.2, 0.2)):
    
    fig = plt.figure(figsize = figsize)
    hue = data[hue] if isinstance(hue,str) and hue in data.columns else hue
    data = data if not vars else data[vars]
    
    colors = get_colors(color_style)
    ax_num = 1
    for col in data.columns:
        if isinstance(data[col].values[0],(np.int64,np.int32,np.int16,np.int8,np.float16,np.float32,np.float64)):
            plt.subplot(rows, cols, ax_num)
            sns.boxplot(x = hue,y = data[col].values,color=random.sample(colors,1)[0],width= width,order = order)
            plt.xlabel(col)
#             data[col].plot(kind = 'box',color=random.sample(colors,1)[0])
            ax_num+=1
    
    plt.subplots_adjust(hspace = subplots_adjust[0],wspace=subplots_adjust[1])
# data_merge
data = pd.read_excel('问题一连接两表并处理后数据.xlsx').iloc[:,1:]

boxplot(data.query("类型 == '高钾'"), 4, 4, hue = '采样点风化类型',
        vars = data.columns[1:].tolist(), figsize=(11, 8), subplots_adjust=(0.52,0.25))
plt.savefig('高钾有无风化化学成分箱线图分析.jpg')

Potássio alto:

boxplot(data.query("类型 == '铅钡'"), 4, 4, hue = '采样点风化类型', vars = data.columns[1:].tolist(),
        figsize=(13, 8), subplots_adjust=(0.55,0.25), order = ['未风化点','风化点','严重风化点'])
plt.savefig('铅钡有无风化化学成分箱线图分析.jpg')

 Chumbo bário: 

Combinando as estatísticas descritivas de elementos químicos e gráficos de caixa e gráficos de linha, podemos observar aproximadamente as leis estatísticas de componentes químicos intemperizados:

  1. O teor de sílica do vidro com alto teor de potássio é relativamente alto e a proporção de óxido de potássio e óxido de alumínio diminui antes e depois do intemperismo, enquanto o teor de sílica aumenta e a proporção de outros componentes químicos não muda muito.
  2. A proporção de dióxido de silício no vidro de chumbo-bário diminui gradualmente com o grau de intemperismo e o grau de diminuição é relativamente grande. A proporção de óxido de chumbo, óxido de bário e pentóxido de fósforo aumenta antes e depois do intemperismo. Comparado com os dados de intemperismo, o proporção de dióxido de enxofre grave A proporção de dióxido de enxofre intemperizado aumentou, enquanto o conteúdo de dióxido de enxofre intemperizado e não intemperizado não foi muito diferente, e as proporções de outros componentes químicos não mudaram muito.

2. De acordo com os dados de detecção do ponto de intemperismo, preveja o conteúdo da composição química antes do intemperismo.

     A maioria das pessoas ficará presa aqui. Basicamente, tive uma ideia para a segunda pergunta na primeira noite e comecei a agrupar a segunda pergunta, mas fiquei preso nessa pequena pergunta até o início da manhã. Companheiros de equipe, não tive uma boa ideia também. Na verdade, eu sabia desde o início que os métodos de aprendizado de máquina não poderiam ser usados ​​para modelagem, porque é óbvio que não há pontos de correspondência de amostra antes e depois do intemperismo, e todos são dados pertencentes a diferentes números de relíquias culturais , portanto, o aprendizado de máquina não pode ser usado. Estou considerando Demorou um pouco em outros métodos e, em seguida, pensei na proporção média estatística mais simples da composição química da amostra não intemperizada e da amostra intemperizada para obter um coeficiente proporcional e, em seguida, usar a composição química intemperizada para multiplicar essa proporção ao prever para obter o conteúdo da composição química antes do intemperismo, que também é o método 'médio' mencionado na resposta.

        No entanto, este método de contagem direta do valor médio não é adequado, porque ainda existem algumas grandes diferenças no mesmo teor de composição química do mesmo tipo de vidro com o mesmo grau de intemperismo. Há uma grande quantidade de pontos de amostragem individuais, o que leva a um grande valor médio após obter o valor médio, o que não está de acordo com a maioria dos outros dados.

Para esse fenômeno, usamos a função de distribuição normal para ponderar         os pontos amostrais para obter a razão de mudança da composição química antes e depois do intemperismo.

from scipy import stats
def zhengtai(x):
    return stats.norm.pdf(x)

# 封装函数,传入高钾或铅钡数据data以及风化采样点类型
def get_mean(data, label):
    d_ = data[data['采样点风化类型'] == label].iloc[:,6:-1].copy()
    # 标准化
    d_scaler = (d_ - d_.mean(axis = 0))/(d_.std(axis = 0))
    # 加权平均
    mean_ = (zhengtai(d_scaler.T).T * d_).sum(axis = 0)/zhengtai(d_scaler.T).T.sum(axis = 0)
    mean_ = mean_.fillna(0)
    # 返回均值与加权均值
    return d_.mean(), mean_

 Obtenha a média e a média ponderada dos dados de alto teor de potássio:

a1, a2 = get_mean(data_merge.query("类型 == '高钾'"), '未风化点')
b1, b2 = get_mean(data_merge.query("类型 == '高钾'"), '风化点')

gj_mean = pd.concat((a1,a2,b1,b2),axis = 1)
gj_mean.columns = ['未风化点均值','未风化点加权均值','风化点均值','风化点加权均值']
gj_mean

 

Vizualizar:

d_ = data_merge.query("类型 == '高钾'")
fig, axes = plt.subplots(4,4,figsize = (16,16))
axes = axes.ravel()
for num,fea in enumerate(data_merge.columns[6:-1]):
    sns.stripplot(x = '采样点风化类型',palette = sns.color_palette('deep',3),
                  y = fea,
                  data =d_,ax = axes[num],
                  jitter = True) # ‘抖
    wfh_mean,wfh_mean_jiaquan = gj_mean[['未风化点均值','未风化点加权均值']].loc[fea,:]
    fh_mean, fh_mean_jiaquan = gj_mean[['风化点均值','风化点加权均值']].loc[fea,:]

    color = ['b','r']
    axes[num].plot([-0.5,0.5],[wfh_mean]*2, c = color[0], label = '未风化均值')
    axes[num].plot([-0.5,0.5],[wfh_mean_jiaquan]*2, '--', c = color[0], label = '未风化加权均值')
    
    axes[num].plot([0.5, 1.5], [fh_mean]*2, c = color[1], label = '风化均值')
    axes[num].plot([0.5, 1.5],[fh_mean_jiaquan]*2, '--', c= color[1], label = '风化加权均值')
    if num==1:
        axes[num].legend()
axes[-1].axis('off')
axes[-2].axis('off')
plt.subplots_adjust(0.2,0.2)
plt.show()

 Obtenha a média e a média ponderada dos dados de chumbo e bário:

a1, a2 = get_mean(data_merge.query("类型 == '铅钡'"), '未风化点')
b1, b2 = get_mean(data_merge.query("类型 == '铅钡'"), '风化点')
c1, c2 = get_mean(data_merge.query("类型 == '铅钡'"), '严重风化点')
qb_mean = pd.concat((a1,a2,b1,b2,c1,c2),axis = 1)
qb_mean.columns = ['未风化点均值','未风化点加权均值','风化点均值','风化点加权均值','严重风化点均值','严重风化点加权均值']
qb_mean

 

Visualização: 

d_ = data_merge.query("类型 == '铅钡'")
fig, axes = plt.subplots(4,4,figsize = (16,16))
axes = axes.ravel()
for num,fea in enumerate(data_merge.columns[6:-1]):
    sns.stripplot(x = '采样点风化类型',palette = sns.color_palette('deep',3),
                  y = fea,
                  data =d_,ax = axes[num], 
                  order = ['未风化点','风化点','严重风化点'],
                  jitter = True) # ‘抖
    
    wfh_mean,wfh_mean_jiaquan = qb_mean[['未风化点均值','未风化点加权均值']].loc[fea,:]
    fh_mean, fh_mean_jiaquan = qb_mean[['风化点均值','风化点加权均值']].loc[fea,:]
    yz_fh_mean, yz_fh_mean_jiaquan = qb_mean[['严重风化点均值','严重风化点加权均值']].loc[fea,:]
    
    color = ['b', 'orange', 'g']
    axes[num].plot([-0.5, 0.5],[wfh_mean]*2, c = color[0], label = '未风化均值')
    axes[num].plot([-0.5, 0.5],[wfh_mean_jiaquan]*2, '--', c = color[0], label = '未风化加权均值')
    
    axes[num].plot([0.5, 1.5], [fh_mean]*2, c = color[1], label = '风化均值')
    axes[num].plot([0.5, 1.5],[fh_mean_jiaquan]*2, '--', c= color[1], label = '风化加权均值')
    
    axes[num].plot([1.5, 2.5],[yz_fh_mean]*2, c = color[2], label = '严重风化均值')
    axes[num].plot([1.5, 2.5],[yz_fh_mean_jiaquan]*2, '--',c = color[2], label = '严重风化加权均值')
    

    axes[num].set_xlabel(None)
    if num==1:
        axes[num].legend()
axes[-1].axis('off')
axes[-2].axis('off')
plt.subplots_adjust(0.2,0.2)
plt.show()

 

 Obtenha a razão média ponderada antes e depois do intemperismo:

w_gj = (gj_mean.iloc[:,1]/gj_mean.iloc[:,3]).replace({np.inf:0})
w_qb = (qb_mean['未风化点加权均值']/qb_mean['风化点加权均值']).replace({np.inf:0})
w_qb_yz = (qb_mean['未风化点加权均值']/qb_mean['严重风化点加权均值']).replace({np.inf:0})

W = pd.DataFrame([w_gj,w_qb,w_qb_yz],index = ['高钾:风化前后加权比例','铅钡:风化前后加权比例','铅钡:严重风化前后加权比例']).T

 prever:

A composição química do ponto de amostragem após o intemperismo é multiplicada pela razão antes e depois do intemperismo para obter o valor previsto da composição química antes do intemperismo:

Nota: Mas no processo, descobrimos que ainda há um problema, ou seja, quando uma determinada composição química do ponto de amostragem intemperizado é 0, não importa o quanto a proporção seja multiplicada, o resultado da previsão ainda é 0, que é diferente da maior parte da composição química do ponto de amostragem não intemperizado Inconsistente, se a composição após o intemperismo for 0, a previsão antes do intemperismo só pode ser 0, o que não é o ideal. Mesmo que haja um pequeno número de pontos de amostragem não intemperizados, os dados é 0. Para este fenômeno, usamos a composição química antes do intemperismo. A média ponderada é usada como o valor previsto.

Para a análise antes e depois do tratamento quando a composição química do ponto de amostragem intemperizado é 0 no momento da previsão:

Pontos de amostragem intemperizados com alto teor de potássio:

Pontos de amostragem de intemperismo de alto potássio:

Como acima, a maior parte do teor de óxido de potássio antes do intemperismo contém um valor e a composição é próxima a 10%, e a maior parte do óxido de magnésio também contém um valor menor que não é zero.

Previsão direta: 

 

 Use a média ponderada sem intemperismo como preditor:

 

 Os resultados após o processamento acima ainda estão dentro da faixa válida, então o autor acredita que este método é viável e evita previsões muito rígidas.

Programa de previsão de alto teor de potássio:

# 高钾预测
fh_gj = data_merge.query("类型 == '高钾' &  采样点风化类型 == '风化点'").iloc[:, 6:-1]
fh_gj = fh_gj.replace({0:np.nan})

data_merge.query("采样点风化类型 == '风化点' & 类型 == '高钾'").iloc[:,6:-1]
gj_pred = fh_gj*W['高钾:风化前后加权比例']

gj_pred = gj_pred.fillna(gj_mean['未风化点加权均值'])
# 规整到100% 注:自己分析是否合理
gj_pred = (gj_pred.T/gj_pred.sum(axis = 1)*100).T

# 补上成分外的特征
d_ = data_merge.loc[gj_pred.index,:][['文物编号','纹饰','类型','颜色',
                                                              '表面风化','文物采样点','采样点风化类型']]
gj_pred = pd.concat((d_, gj_pred), axis = 1)

Programa de previsão de chumbo e bário: 

# 铅钡预测
fh_qb = data_merge.query("类型 == '铅钡' &  采样点风化类型 == '风化点'").iloc[:, 6:-1]
fh_qb = fh_qb.replace({0:np.nan})

yz_fh_qb = data_merge.query("类型 == '铅钡' &  采样点风化类型 == '严重风化点'").iloc[:, 6:-1]
yz_fh_qb = yz_fh_qb.replace({0:np.nan})

qb_pred = (fh_qb * W['铅钡:风化前后加权比例'])
yz_qb_pred = (yz_fh_qb * W['铅钡:严重风化前后加权比例'])

qb_pred = qb_pred.fillna(qb_mean['未风化点加权均值'])
yz_qb_pred = yz_qb_pred.fillna(qb_mean['未风化点加权均值'])

# 规整到100%
qb_pred = (qb_pred.T/qb_pred.sum(axis = 1)*100).T
yz_qb_pred = (yz_qb_pred.T/yz_qb_pred.sum(axis = 1)*100).T

# 合并风化点与严重风化点预测数据
qb_pred = pd.concat((yz_qb_pred,qb_pred))

# 补上成分外特征
d_ = data_merge.loc[qb_pred.index,:][['文物编号','纹饰','类型','颜色',
                                   '表面风化','文物采样点','采样点风化类型']]
qb_pred = pd.concat((d_, qb_pred), axis = 1)

Result = pd.concat((gj_pred, qb_pred)).reset_index().iloc[:, 1:]
# Result.to_excel('加权平均法预测风化前含量结果.xlsx')
Result

Resultado da previsão: basta tirar uma captura de tela para que todos vejam  

pergunta dois

1. Analisar as regras de classificação de vidro de alto potássio e vidro de chumbo-bário de acordo com os dados em anexo;

Analise visualmente as diferenças na composição química de vidros com alto teor de potássio e chumbo-bário por boxplot para explorar as regras de classificação que determinam suas categorias de vidro:

# data_merge
data = pd.read_excel('问题一连接两表并处理后数据.xlsx').iloc[:,1:]
# 作者封装函数
boxplot(data,4,4,hue = '类型', vars = data.columns[1:].tolist(),
        figsize=(11, 8), subplots_adjust=(0.52,0.25))
plt.savefig('高钾铅钡玻璃化学成分箱线图分析.jpg')

 Distribuição de recursos de análise de plotagem de densidade

# stat = "count", "frequency", "density", "probability"
def distplot(data, rows = 3, cols = 4, bins = 10, vars = None, hue = None, kind = 'hist',stat = 'count', shade = True,
             figsize = (12, 5), color_style = 'all', alpha = 0.7, subplots_adjust = (0.3, 0.2)):
    assert kind in ['hist', 'kde','both'], "kind must == 'hist' or 'kde'"
    assert stat in ["count", "frequency", "density", "probability"], 'stat must in ["count", "frequency", "density", "probability"]'
    
    fig = plt.figure(figsize = figsize)
    hue_name = hue  if isinstance(hue,str) or hue==None else hue.name
    hue = data[hue] if isinstance(hue,str) and hue in data.columns else hue
    data = data if not vars else data[vars]
    
    colors = get_colors(color_style)
    
    ax_num = 1
    for col in data.columns:
        if isinstance(data[col].values[0],(np.int64,np.int32,np.int16,np.int8,np.float16,np.float32,np.float64)) and col!=hue_name:
            plt.subplot(rows, cols, ax_num)
            if kind == 'hist':
                sns.histplot(x = data.loc[:,col],bins = bins,color=random.sample(colors,1)[0],hue = hue,alpha = alpha,stat = stat)
            elif kind == 'kde':
                sns.kdeplot(x = data.loc[:,col],color=random.sample(colors,1)[0],alpha = alpha,hue = hue,shade = shade)
            else:
                sns.distplot(x = data.loc[:,col],color=random.sample(colors,1)[0],kde=True,bins = bins,)
                plt.xlabel(col)
            ax_num+=1

    plt.subplots_adjust(hspace = subplots_adjust[0],wspace=subplots_adjust[1])
with sns.color_palette('rainbow_r'):
    distplot(data.iloc[:,1:],4,4,kind = 'kde',figsize=(11,7),subplots_adjust=(0.5,0.35),hue = '类型')

       De acordo com a figura acima, a distribuição característica de dióxido de silício, óxido de potássio, óxido de chumbo, óxido de bário, pentóxido de fósforo e óxido de estrôncio em alto potássio e vidro de chumbo-bário é bastante diferente, especialmente óxido de chumbo, o conteúdo de óxido de chumbo em alto o potássio é basicamente A distribuição está em 0, e o teor de óxido de chumbo do bário de chumbo é relativamente grande, então essas características, especialmente o óxido de chumbo , provavelmente são características importantes para distinguir potássio alto e bário de chumbo e, em seguida, um modelo de previsão do tipo de vidro é estabelecido para posterior determinação e verificação .

        O modelo aqui estabelecido pode ser usado diretamente na previsão da Questão 3, que é principalmente prever os resultados. O modelo selecionado aqui é relativamente simples, a quantidade de dados é pequena e possui características distintivas óbvias. O uso de regressão logística regularizada L1 e árvore de decisão pode distinguir completamente vidro de alto teor de potássio e chumbo-bário, e a precisão da validação cruzada atinge 100%. A razão para usar esses dois modelos não é apenas simples, mas também tem a função de triar características importantes e não pode ser afetada pela multicolinearidade . Vejo que muitas pessoas usam redes neurais e aplicam modelos muito complicados assim que surgem . Não acho que seja necessário. , o conjunto de dados em si é pequeno e a regressão logística pode satisfazer a previsão. Claro, a floresta aleatória ou a máquina de vetores de suporte também podem ser usadas.

        Como o processo é muito simples, ele só precisa ser codificado e padronizado de acordo com a tradição para construir o modelo por meio da biblioteca sklearn. Aqui, apresentarei as ideias acima e não mostrarei o programa. Deixe-me mostrar algumas visualizações do modelo:

   Analisando o mapa de peso da figura acima, podemos verificar que os principais fatores decisivos são o dióxido de silício, óxido de potássio, óxido de chumbo, óxido de bário, etc. Dentre eles, o óxido de chumbo tem o maior peso, ou seja, tem a maior determinação sobre os resultados da classificação Esses fatores de influência estão relacionados com As conclusões obtidas na análise do boxplot são consistentes.

 

     A árvore de decisão pode classificar perfeitamente esta amostra. Devido ao princípio e à natureza da árvore de decisão, as condições de classificação aqui são muito simples, indicando que as características do óxido de chumbo podem distinguir alto potássio e chumbo-bário , e o limite de decisão é um hiperplano linear, como oxidação no diagrama de caixa Na análise das características do chumbo, pode-se observar que apenas uma linha reta é necessária para distingui-los, mas a previsão é baseada apenas no teor de óxido de chumbo e muita confiança em um único recurso torna o modelo utilizável em face de dados anormais, como ruído ou falta de conteúdo de sílica. Ruim, use floresta aleatória em vez disso.

     Tanto a regressão logística quanto a máquina de vetores de suporte usam todos os recursos como base para a previsão, o que pode alcançar o efeito que desejamos na realidade. Considerando o princípio da máquina de vetores de suporte e o limite superior é maior que o da regressão logística, o modelo final é selecionado aqui como a máquina de vetores de suporte.

Exibição do plano de decisão:

 

      

2. Selecione a composição química apropriada para cada categoria para dividi-la em subcategorias, forneça o método de divisão específico e os resultados da divisão e analise a racionalidade e a sensibilidade dos resultados da classificação. 

         Aqui usamos as características do tipo de intemperismo dos pontos de amostragem de alto teor de potássio e chumbo-bário como a base de agrupamento para a subclassificação. De acordo com o significado da pergunta e a análise dos dados, a composição química do mesmo tipo de vidro muda muito antes e depois do intemperismo. Portanto, os vidros intemperizados, não intemperizados e severamente intemperizados são usados ​​como subcategorias. Alto potássio é dividido em duas categorias: não intemperizado e intemperizado. É dividido em três categorias: não intemperizado, intemperizado e severamente intemperizado. De acordo com o grau de intemperismo, os seguintes dados são obtidos dos pontos de amostragem das amostras de dados originais e os resultados de agrupamento subsequentes são avaliados com base nisso:

 Recursos do filtro:

        Existem várias maneiras de filtrar recursos:

        O grau de dispersão de cada composição química (selecionando características com grande desvio padrão) pode ser usado como base para subclassificação, pois para dados de um único tipo de vidro, se o grau de dispersão de uma determinada característica for pequeno, ou seja, o o conteúdo da composição é semelhante, não é adequado e difícil de usar como base para subclassificação.A base para posterior divisão de categorias, ao contrário, recursos com alto grau de dispersão podem ser considerados como tendo espaço para posterior divisão.

        Também é possível treinar o modelo de classificação com a composição química como variável e o tipo de intemperismo como rótulo e, em seguida, selecionar recursos pelo peso do recurso ou pela importância do recurso. Nesse problema, esse método pode ser melhor do que o método de seleção de desvio padrão, porque, como o objetivo do agrupamento é claro, os resultados do agrupamento após os recursos de triagem precisam ser considerados mais adequados para a situação de intemperismo e o desvio padrão é grande .As características não são necessariamente adequadas como características básicas do agrupamento, mas podem afetar o resultado. Mesmo assim, com base no primeiro método, as feições selecionadas ainda podem ser ligeiramente ajustadas pela análise dos resultados do agrupamento.

Recursos de seleção de floresta aleatória:

        Aqui, o modelo de classificação de floresta aleatória é usado para seleção de recursos. A árvore de decisão não é usada porque o conjunto de dados é muito simples durante o treinamento e pode ser facilmente dividido por um único recurso, o que tornará a importância do único recurso 1 e outros recursos. Ambos são 0, o que não pode fornecer uma base para selecionarmos vários recursos.

from sklearn.cluster import KMeans, AgglomerativeClustering,DBSCAN
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import GridSearchCV 
from sklearn.metrics import f1_score
from sklearn.model_selection import cross_val_score 
from itertools import permutations


data = pd.read_excel('问题一连接两表并处理后数据.xlsx').iloc[:,1:]
d1 = data.query("类型 == '高钾'")
d1.index = range(len(d1))
d2 = data.query("类型 == '铅钡'")
d2.index = range(len(d2))

  Potássio alto:

x = d1.drop('采样点风化类型', axis = 1).iloc[:, 6:]
y = d1['采样点风化类型']

model = RandomForestClassifier()
# 参数调优
parameters = {'max_depth':range(1,5),'min_samples_leaf':[1,2],'criterion':['gini','entropy'],'min_impurity_decrease':[0.01,0.02,0.025]}

grid_search = GridSearchCV(model, parameters,cv=5) 
grid_search.fit(x, y)  # 传入数据

print('网格搜索最高精度为:',grid_search.best_score_)
print('参数最优值:',grid_search.best_params_) 
model.fit(x, y)

gj_fea_df = pd.DataFrame([x.columns,model.feature_importances_],index = ['化学成分','特征重要性']).T
gj_fea_df.sort_values('特征重要性', ascending = False)
"""
化学成分	特征重要性
0	二氧化硅(SiO2)	0.231851
5	氧化铝(Al2O3)	0.170588
2	氧化钾(K2O)	0.146777
3	氧化钙(CaO)	0.138207
6	氧化铁(Fe2O3)	0.097733
10	五氧化二磷(P2O5)	0.096698
7	氧化铜(CuO)	0.034813
4	氧化镁(MgO)	0.02908
8	氧化铅(PbO)	0.017656
11	氧化锶(SrO)	0.017181
12	氧化锡(SnO2)	0.009706
9	氧化钡(BaO)	0.007264
1	氧化钠(Na2O)	0.002448
13	二氧化硫(SO2)	0.0
"""
# 获取降序后的重要性特征列表
gj_fea = gj_fea_df.sort_values('特征重要性', ascending = False)['化学成分'].tolist()

Chumbo bário:

gj_fea = dt.T.loc[:,'高钾(标准差)'].sort_values(ascending = False).index
dt.T.loc[:,'高钾(标准差)'].sort_values(ascending = False)

"""
二氧化硅(SiO2)     14.466726
氧化钾(K2O)        5.307753
氧化钙(CaO)        3.308126
氧化铝(Al2O3)      3.076662
氧化铁(Fe2O3)      1.566033
氧化铜(CuO)        1.492236
五氧化二磷(P2O5)     1.280603
氧化钠(Na2O)       1.088707
氧化钡(BaO)        0.841629
氧化镁(MgO)        0.711802
氧化锡(SnO2)       0.556257
氧化铅(PbO)        0.514144
二氧化硫(SO2)       0.157164
氧化锶(SrO)        0.043866
Name: 高钾(标准差), dtype: float64
"""

 Chumbo bário:

x = d2.drop('采样点风化类型', axis = 1).iloc[:, 6:]
y = d2['采样点风化类型']

# 参数调优
model = RandomForestClassifier()
parameters = {'max_depth':range(1,5),'min_samples_leaf':[1,2],'criterion':['gini','entropy'],'min_impurity_decrease':[0.01,0.02]}

grid_search = GridSearchCV(model, parameters,cv=5) 
grid_search.fit(x, y)  # 传入数据

print('网格搜索最高精度为:',grid_search.best_score_)
print('参数最优值:',grid_search.best_params_) 
model.fit(x, y)

qb_fea_df = pd.DataFrame([x.columns,model.feature_importances_],index = ['化学成分','特征重要性']).T
qb_fea_df.sort_values('特征重要性', ascending = False)
"""
化学成分	特征重要性
0	二氧化硅(SiO2)	0.227769
8	氧化铅(PbO)	0.207812
3	氧化钙(CaO)	0.092374
10	五氧化二磷(P2O5)	0.087535
11	氧化锶(SrO)	0.06342
5	氧化铝(Al2O3)	0.056736
7	氧化铜(CuO)	0.050561
9	氧化钡(BaO)	0.042228
13	二氧化硫(SO2)	0.03454
4	氧化镁(MgO)	0.033355
2	氧化钾(K2O)	0.030859
1	氧化钠(Na2O)	0.027895
6	氧化铁(Fe2O3)	0.027078
12	氧化锡(SnO2)	0.017839
"""
# 获取铅钡重要性降序特征列表
qb_fea = qb_fea_df.sort_values('特征重要性', ascending = False)['化学成分'].tolist()

Recursos de triagem: Ao selecionar continuamente recursos de importância alta a baixa e, após o agrupamento, use o escore f1 para corresponder ao tipo de intemperismo dos pontos de amostragem, quantificar o efeito de ajuste para selecionar recursos e excluir o recurso se ele causar um declínio.

def pinggu_gj(pred):
    score = 0
    for i in permutations([0,1]):
        true1 = d1['采样点风化类型'].replace({'未风化点':i[0],'风化点':i[1]})
        score_ = f1_score(pred, true1, average='weighted')
        score = score_ if score_>score else score
    return score

def pinggu_qb(pred):
    score = 0
    for i in permutations([0,1,2]):
        true2 = d2['采样点风化类型'].replace({'未风化点':i[0], '风化点':i[1], '严重风化点':i[2]})
        score_ = f1_score(pred, true2, average='weighted')
        score = score_ if score_>score else score
    return score

gj_score = 0
qb_score = 0
gj_del_fea = []
qb_del_fea = []
best_gj_fea = []
best_qb_fea = []
for i in range(1, 15):
    fea1 = gj_fea[:i].copy()
    for g in gj_del_fea:
        fea1.remove(g)
    d1_x = d1[fea1]
    
    fea2 = qb_fea[:i].copy()
    for g in qb_del_fea:
        fea2.remove(g)
    d2_x = d2[fea2]
    
    model1 = KMeans( n_clusters=2)
    scaler1 = StandardScaler()
    a1 = scaler1.fit_transform(d1_x)
    y1 = model1.fit_predict(a1)
    d1_['label'] = y1
    if pinggu_gj(d1_['label']) > gj_score: 
        gj_score = pinggu_gj(d1_['label'])
        best_gj_fea = fea1
    else:
        gj_del_fea.append(gj_fea[i-1])
        
    scaler2 = StandardScaler()
    model2 = KMeans( n_clusters=3)
    a2 = scaler2.fit_transform(d2_x)
    y2 = model2.fit_predict(a2)
    d2_['label'] = y2
    if pinggu_qb(d2_['label']) > qb_score:
        qb_score = pinggu_qb(d2_['label'])
        best_qb_fea = fea2
    else:
        qb_del_fea.append(qb_fea[i-1])

        
print(f'高钾数据选择的特征:{best_gj_fea}')
# 高钾数据选择的特征:['二氧化硅(SiO2)', '五氧化二磷(P2O5)']

print(f'铅钡数据选择的特征:{best_qb_fea}')
# 铅钡数据选择的特征:['二氧化硅(SiO2)', '氧化铅(PbO)', '氧化钡(BaO)', '二氧化硫(SO2)']

print(f'高钾f1-score:', gj_score, '铅钡f1-score:', qb_score )
# 高钾f1-score: 0.9435154217762913 铅钡f1-score: 0.8987315891105979

Como resultado acima:

As características da seleção de vidro de alto potássio são: dióxido de silício, pentóxido de fósforo

As características selecionadas do vidro de chumbo-bário são: dióxido de silício, óxido de chumbo, óxido de bário, dióxido de enxofre

A precisão de correspondência dos resultados de agrupamento de recursos selecionados para alto potássio, chumbo e bário e o tipo de intemperismo do ponto de amostragem da amostra original são 0,94 e 0,89, respectivamente

Use os recursos selecionados para agrupar novamente e salve os resultados do agrupamento.

Visualize os resultados do agrupamento, desenhe gráficos de dispersão bidimensionais e tridimensionais e selecione 2 e 3 recursos com alta importância como eixos bidimensionais e tridimensionais (existem apenas dois recursos de alto potássio selecionados no desenho tridimensional, e só precisa adicionar outros componentes O mais importante é suficiente, aqui é principalmente para mostrar o efeito de agrupamento aproximado).

d1_ = pd.concat((d1.loc[:,['文物编号','类型','文物采样点']], d1.loc[:,'二氧化硅(SiO2)':'二氧化硫(SO2)']),axis = 1)
d2_ = pd.concat((d2.loc[:,['文物编号','文物采样点']], d2.loc[:,'二氧化硅(SiO2)':'二氧化硫(SO2)']),axis = 1)

d1_x = d1[['二氧化硅(SiO2)', '五氧化二磷(P2O5)']]
d2_x = d2[['二氧化硅(SiO2)', '氧化铅(PbO)', '氧化钡(BaO)', '二氧化硫(SO2)']]

# 均值聚类
model1 = KMeans( n_clusters=2)
scaler1 = StandardScaler()
a1 = scaler1.fit_transform(d1_x)
y1 = model1.fit_predict(a1)
d1_['label'] = y1

scaler2 = StandardScaler()
model2 = KMeans( n_clusters=3)
a2 = scaler2.fit_transform(d2_x)
y2 = model2.fit_predict(a2)
d2_['label'] = y2

from mpl_toolkits.mplot3d import Axes3D
fig = plt.figure(figsize=(15,8))

# ax = fig.add_subplot(121, projection='3d')
ax = plt.subplot(121)
for i in range(d1_['label'].nunique()):
    data = d1_[d1_['label']==i]
    ax.scatter(data['二氧化硅(SiO2)'],data['五氧化二磷(P2O5)'],c=colors[i],label =i)
#     ax.scatter(data['二氧化硅(SiO2)'],data['五氧化二磷(P2O5)'],data['氧化铝(Al2O3)'],c=colors[i],label =i)
ax.set_xlabel('二氧化硅(SiO2)')
ax.set_ylabel('五氧化二磷(P2O5)')
# ax.set_zlabel('氧化铝(Al2O3)')
plt.title('高钾:Kmeans聚类结果图',fontsize = 15)
plt.legend()
# plt.savefig('高钾聚类效果三维散点图')


# ax = fig.add_subplot(122, projection='3d')
ax = plt.subplot(122)
for i in range(d2_['label'].nunique()):
    data = d2_[d2_['label']==i]
    ax.scatter(data['二氧化硅(SiO2)'],data['氧化铅(PbO)'],c=colors[i],label =i)
#     ax.scatter(data['二氧化硅(SiO2)'],data['氧化铅(PbO)'],data['氧化钡(BaO)'],c=colors[i],label =i)
ax.set_xlabel('二氧化硅(SiO2)')
ax.set_ylabel('氧化铅(PbO)')
# ax.set_zlabel('氧化钡(BaO)')
plt.title('铅钡:Kmeans聚类聚类结果图',fontsize = 15)
plt.legend()
# plt.savefig('铅钡聚类效果三维散点图')
plt.savefig('Kmeans聚类聚类结果图')
plt.show()

 

 3D:

 

O efeito do agrupamento hierárquico é basicamente o mesmo do agrupamento médio.

Análise de racionalidade:

Conforme mostrado na figura acima, o mapa tridimensional de alto teor de potássio é agrupado em duas categorias. Combinado com o tipo de intemperismo dos pontos de amostragem, pode-se ver que aquele com maior teor de sílica no mapa é após o intemperismo, e o outro com um conteúdo menor são os dados antes do intemperismo, que estão de acordo com os dados originais. O mesmo é verdade para o vidro de chumbo-bário. Por exemplo, o ponto vermelho no diagrama bidimensional de três pontos é o correspondente ponto de intemperismo severo, portanto o resultado do agrupamento é considerado razoável.

Análise sensitiva:

Ideia: Para explorar a sensibilidade dos resultados da classificação, usamos o método de variável de controle para alterar o conteúdo de cada recurso em um intervalo, enquanto controlamos o conteúdo de outros recursos durante o período e usamos o modelo de agrupamento K-means treinado para analisar as alterações . Os pontos de amostragem são previstos e o escore f1 é usado como um indicador para quantificar os resultados da previsão. Se os resultados da previsão do ponto de amostragem permanecerem inalterados, os resultados da classificação não serão sensíveis a alterações em recursos individuais e a classificação resultados são estáveis.

Questão 3: Analisar a composição química de relíquias culturais de vidro desconhecidas no Anexo Formulário 3, identificar seu tipo e analisar a sensibilidade dos resultados da classificação.

Basta analisar se a distribuição de recursos dos dados de teste é muito diferente da distribuição de recursos do conjunto de treinamento e usar o modelo estabelecido na questão 2 para prever os dados de teste. Os resultados do uso de máquinas de vetores de suporte ou florestas aleatórias são consistentes.

Análise visual:

def boxplot1(data1,data2, rows = 3, cols = 4,figsize = (13, 8),color_style ='light'):
    fig = plt.figure(figsize = figsize)
    colors = get_colors(color_style=color_style)
    ax_num = 1
    for col in data1.columns:
        if isinstance(data1[col][0],(np.int, np.float)):
            plt.subplot(rows, cols, ax_num)
            data_ = pd.DataFrame([data1[col].values,data2[col].values],index = ['原数据','表单3数据']).T
            sns.boxplot(data = data_,color=random.sample(colors,1)[0],width=0.2,)
#             sns.histplot(data = data_,color=random.sample(colors,1)[0],kde = True)

            plt.xlabel(col)
#             data[col].plot(kind = 'box',color = random.sample(darkcolors,1)[0])
            ax_num+=1
    plt.subplots_adjust(hspace = 0.5)
data3 = data3.fillna(0)
d_ = data_merge.iloc[:,6:-1]

boxplot1(data4,d_,4,4)
plt.savefig('原数据与表单3数据箱线图分析分布情况')
plt.show()

          Altere o conteúdo de cada recurso em um intervalo e controle o conteúdo de outros recursos durante o período. Use o escore f1 como um indicador para quantificar os resultados da previsão. Tem estabilidade.

Acho que você gosta

Origin blog.csdn.net/weixin_46707493/article/details/127348898
Recomendado
Clasificación