2022 National Mathematical Modeling-C Question Review Análisis de composición e identificación de productos de vidrio antiguos

El mes pasado participé en el Concurso Nacional de Modelamiento Matemático y realicé el problema C. Tuve la suerte de ganar el provincial y enviarlo al premio nacional. Arreglé el programa y lo revisé nuevamente. Aquí mostraré brevemente los pequeños partes de la primera, segunda y tercera preguntas Ideas y procesos para resolver problemas , así como programas Python.

Leer y mostrar datos:

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

datos1: 

 datos2:

datos3:

Preprocesamiento:

1) Complete los valores faltantes de color en el formulario 1 y los valores faltantes de composición química en el formulario 2

Agrupe las tres características excepto el color: tipo, decoración y erosión de la superficie, y extraiga el modo del color para completar el color faltante del punto de muestra 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 acuerdo con el significado de la pregunta, complete el valor faltante de la composición química en el Formulario 2 con 0

data2.fillna(0,inplace=True)

2) Extraiga la información del número de reliquia cultural en las características de los puntos de muestreo de reliquia cultural en los datos del formulario 2 y vincule el formulario 1 a través de la información del número de reliquia 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) Eliminar componentes químicos y datos no válidos fuera del 85 %~105 %

Ver datos no vá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 los datos combinados, obtenga el tipo de meteorización del punto de muestreo de acuerdo con la descripción de la información en el título adjunto, el número de la reliquia cultural y la información del punto de muestreo de la reliquia 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
"""

anexo:

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

Pregunta uno:

1. Combinado con el tipo de vidrio, analice las leyes estadísticas de si hay componentes químicos degradados en la superficie de las muestras de reliquias culturales.

        Para vidrio con alto contenido de potasio/plomo-bario, analice estadísticamente la diferencia en la composición química entre muestras no meteorizadas y meteorizadas para explorar la ley estadística de la composición química meteorizada. Utilice gráficos de líneas y diagramas de caja para el análisis. Los diagramas de caja no solo pueden mostrar puntos de muestra. El rango de distribución de la composición química y, al mismo tiempo, el valor medio, el valor mínimo y máximo se pueden analizar de manera concisa.

Análisis de gráfico de líneas: saque el valor medio de cada composición química con o sin meteorización, dibuje un gráfico de líneas y observe la diferencia de composición química con o sin meteorización.

# 提取化学名称
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álisis de diagrama de caja: sacar por separado

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')

Potasio 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')

 Plomo bario: 

Combinando las estadísticas descriptivas de los elementos químicos y los diagramas de caja y los gráficos de líneas, podemos observar aproximadamente las leyes estadísticas de los componentes químicos degradados:

  1. El contenido de sílice del vidrio con alto contenido de potasio es relativamente alto, y la proporción de óxido de potasio y óxido de aluminio disminuye antes y después de la intemperie, mientras que el contenido de sílice aumenta y la proporción de otros componentes químicos no cambia mucho.
  2. La proporción de dióxido de silicio en el vidrio de plomo-bario disminuye gradualmente con el grado de meteorización y el grado de disminución es relativamente grande. La proporción de óxido de plomo, óxido de bario y pentóxido de fósforo aumenta antes y después de la meteorización. En comparación con los datos de meteorización, la proporción de graves La proporción de dióxido de azufre meteorizado aumentó, mientras que el contenido de dióxido de azufre meteorizado y no meteorizado no fue muy diferente, y las proporciones de otros componentes químicos no cambiaron mucho.

2. Según los datos de detección del punto de meteorización, prediga el contenido de la composición química antes de la meteorización.

     La mayoría de las personas se quedarán atascadas aquí. Básicamente, tuve una idea para la segunda pregunta la primera noche y comencé a agrupar la segunda pregunta, pero me quedé atascado en esta pequeña pregunta hasta la madrugada. Compañeros de equipo, no tuve una buena idea tampoco De hecho, sabía desde el principio que los métodos de aprendizaje automático no se podían usar para modelar, porque es obvio que no hay puntos de coincidencia de muestra antes y después de la meteorización, y todos son datos que pertenecen a diferentes números de reliquias culturales , por lo tanto, el aprendizaje automático no se puede usar. Estoy considerando que tomó un poco de tiempo en otros métodos, y luego pensé en la proporción promedio estadística más simple de la composición química de la muestra no meteorizada y la muestra meteorizada para obtener un coeficiente proporcional, y luego uso la composición química meteorizada para multiplicar esta relación al predecir para obtener el contenido de composición química antes de la meteorización, que también es el método 'promedio' mencionado en la respuesta.

        Sin embargo, este método de contar directamente el valor promedio no es adecuado, porque todavía hay grandes diferencias en el mismo contenido de composición química del mismo tipo de vidrio con el mismo grado de meteorización.Hay una gran cantidad de puntos de muestra individuales, lo que conduce a un valor promedio grande después de tomar el valor medio, que no está en línea con la mayoría de los otros datos.

Para este fenómeno, usamos la función de distribución normal para ponderar         los puntos de muestra para obtener la relación de cambio de composición química antes y después de la meteorización.

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_

 Obtenga la media y la media ponderada de los datos de potasio alto:

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

 

Visualizar:

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()

 Obtenga la media y la media ponderada de los datos de plomo y bario:

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

 

Visualización: 

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()

 

 Obtenga la relación media ponderada antes y después de la meteorización:

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

 predecir:

La composición química del punto de muestra después de la intemperie se multiplica por la relación antes y después de la intemperie para obtener el valor predicho de la composición química antes de la intemperie:

Nota: Pero en el proceso, encontramos que todavía hay un problema, es decir, cuando cierta composición química del punto de muestreo erosionado es 0, no importa cuánto se multiplique la relación, el resultado de la predicción sigue siendo 0, que es diferente de la mayoría de la composición química del punto de muestreo no meteorizado Inconsistente, si la composición después de la meteorización es 0, la predicción antes de la meteorización solo puede ser 0, lo cual no es ideal Incluso si hay una pequeña cantidad de puntos de muestreo no meteorizados, los datos es 0. Para este fenómeno, usamos la composición química antes de la meteorización. La media ponderada se usa como el valor predicho.

Para el análisis antes y después del tratamiento cuando la composición química del punto de muestreo intemperizado es 0 en el momento de la predicción:

Puntos de muestreo no meteorizados con alto contenido de potasio:

Puntos de muestreo de meteorización con alto contenido de potasio:

Como antes, la mayor parte del contenido de óxido de potasio antes de la meteorización contiene un valor y la composición es cercana al 10 %, y la mayor parte del óxido de magnesio también contiene un valor menor que no es cero.

Predicción directa: 

 

 Utilice la media ponderada no meteorizada como predictor:

 

 Los resultados después del procesamiento anterior todavía están dentro del rango válido, por lo que el autor cree que este método es factible y evita predicciones demasiado rígidas.

Programa de predicción de alto contenido de potasio:

# 高钾预测
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 Predicción de Plomo y Bario: 

# 铅钡预测
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 de la predicción: simplemente tome una captura de pantalla para que todos la vean  

pregunta dos

1. Analizar las reglas de clasificación del vidrio con alto contenido de potasio y el vidrio de plomo-bario de acuerdo con los datos adjuntos;

Analice visualmente las diferencias en la composición química de los vidrios con alto contenido de potasio y plomo-bario mediante diagramas de caja para explorar las reglas de clasificación que determinan sus categorías de vidrio:

# 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')

 Distribución de características de análisis de gráfico de densidad

# 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 acuerdo con la figura anterior, la distribución característica de dióxido de silicio, óxido de potasio, óxido de plomo, óxido de bario, pentóxido de fósforo y óxido de estroncio en vidrio con alto contenido de potasio y plomo-bario es bastante diferente, especialmente óxido de plomo, el contenido de óxido de plomo en alto El potasio es básicamente La distribución es 0, y el contenido de óxido de plomo del bario de plomo es relativamente grande, por lo que es probable que estas características, especialmente el óxido de plomo , sean características importantes para distinguir el potasio alto y el bario de plomo, y luego un modelo de predicción de tipo de vidrio se establece para su posterior determinación y verificación .

        El modelo aquí establecido se puede utilizar directamente en la predicción de la Pregunta 3, que es principalmente para predecir los resultados. El modelo seleccionado aquí es relativamente simple, con una pequeña cantidad de datos y características distintivas obvias. El uso de la regresión logística regularizada L1 y los árboles de decisión pueden distinguir completamente los vasos con alto contenido de potasio y los de plomo y bario, y la precisión de la validación cruzada alcanza el 100%. La razón para usar estos dos modelos no solo es simple, sino que también tiene la función de detectar características importantes y no puede verse afectada por la multicolinealidad Veo que muchas personas usan redes neuronales y aplican modelos demasiado complicados tan pronto como surgen. No creo que sea necesario. , el conjunto de datos en sí es pequeño y la regresión logística puede satisfacer la predicción. Por supuesto, también se puede usar un bosque aleatorio o una máquina de vectores de soporte.

        Dado que el proceso es muy simple, solo necesita codificarse y estandarizarse de acuerdo con la tradición para construir el modelo a través de la biblioteca sklearn. Aquí, presentaré las ideas anteriores y no mostraré el programa. Permítame mostrarle algunas visualizaciones del modelo:

   Analizando el mapa de peso de la figura anterior, podemos encontrar que los principales factores decisivos son el dióxido de silicio, el óxido de potasio, el óxido de plomo, el óxido de bario, etc. Entre ellos, el óxido de plomo tiene el mayor peso, es decir, tiene la mayor capacidad de decisión. en los resultados de la clasificación Estos factores influyentes están relacionados con Las conclusiones obtenidas en el análisis de diagramas de caja son consistentes.

 

     El árbol de decisión puede clasificar perfectamente esta muestra. Debido al principio y la naturaleza del árbol de decisión, las condiciones de clasificación aquí son demasiado simples, lo que indica que las características del óxido de plomo pueden distinguir el potasio alto y el plomo-bario , y el límite de decisión es un hiperplano lineal, como la oxidación en el diagrama de caja. En el análisis de las características del plomo, se puede observar que solo se necesita una línea recta para distinguirlos, pero la predicción solo se basa en el contenido de óxido de plomo y se confía demasiado en una sola característica hace que el modelo sea utilizable frente a datos anormales, como ruido o falta de contenido de sílice. Pobre, use un bosque aleatorio en su lugar.

     Tanto la regresión logística como la máquina de vectores de soporte utilizan todas las características como base para la predicción, lo que puede lograr el efecto que queremos en la realidad. Teniendo en cuenta el principio de la máquina de vectores de soporte y el límite superior es más alto que el de la regresión logística, por lo que el modelo final se selecciona aquí como la máquina de vectores de soporte.

Visualización del plano de decisión:

 

      

2. Seleccione la composición química apropiada para cada categoría para dividirla en subcategorías, proporcione el método de división específico y los resultados de la división, y analice la racionalidad y sensibilidad de los resultados de la clasificación. 

         Aquí usamos las características del tipo de meteorización de los puntos de muestreo con alto contenido de potasio y plomo-bario como base de agrupación para la subclasificación. De acuerdo con el significado de la pregunta y el análisis de datos, la composición química del mismo tipo de vidrio cambia mucho antes y después de la intemperie. Por lo tanto, los vidrios intemperizados, no intemperizados y severamente intemperizados se utilizan como subcategorías. El potasio alto se divide en dos categorías: no meteorizado y meteorizado.Se divide en tres categorías: no meteorizado, meteorizado y severamente meteorizado.De acuerdo con el grado de meteorización, los siguientes datos se obtienen de los puntos de muestreo de las muestras de datos originales, y se evalúan los resultados de agrupación posteriores basado en esto:

 Características del filtro:

        Hay varias formas de filtrar entidades:

        El grado de dispersión de cada composición química (seleccionando características con una gran desviación estándar) se puede utilizar como base para la subclasificación, porque para datos de un solo tipo de vidrio, si el grado de dispersión de una determinada característica es pequeño, es decir, el el contenido de la composición es similar, no es adecuado y difícil de usar como base para la subclasificación. La base para una mayor división de categorías, por el contrario, se puede considerar que las características con un alto grado de dispersión tienen espacio para una mayor división.

        También es posible entrenar el modelo de clasificación con la composición química como variable y el tipo de meteorización como etiqueta, y luego seleccionar características por el peso de la característica o la importancia de la característica. En este problema, este método puede ser mejor que el método de selección de la desviación estándar, porque dado que el propósito de la agrupación es claro, los resultados de la agrupación después de las características de detección deben considerarse más adecuados para la situación de meteorización, y la desviación estándar es grande. Las características no son necesariamente adecuadas como características base del agrupamiento, pero pueden afectar el resultado. Aun así, sobre la base del primer método, las características seleccionadas aún pueden ajustarse ligeramente analizando los resultados de la agrupación.

Características de selección aleatoria de bosques:

        Aquí, el modelo de clasificación de bosque aleatorio se usa para la selección de características. El árbol de decisión no se usa porque el conjunto de datos es demasiado simple durante el entrenamiento, y se puede dividir fácilmente por una sola característica, lo que hará que la importancia de la única característica 1 y otras características Ambos son 0, lo que no puede proporcionarnos una base para seleccionar varias características.

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))

  Potasio 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()

Plomo bario:

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
"""

 Plomo bario:

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()

Detección de características: seleccionando continuamente características de mayor a menor importancia y, después de la agrupación, utilice la puntuación f1 para hacer coincidir el tipo de meteorización de los puntos de muestreo, cuantifique el efecto de ajuste para seleccionar características y elimine la característica si provoca una disminución.

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 anterior:

Las características de la selección de vidrio alto en potasio son: dióxido de silicio, pentóxido de fósforo

Las características seleccionadas del vidrio de plomo-bario son: dióxido de silicio, óxido de plomo, óxido de bario, dióxido de azufre

La precisión de coincidencia de los resultados de agrupamiento de características seleccionados para alto contenido de potasio, plomo y bario y el tipo de meteorización del punto de muestreo de la muestra original es de 0,94 y 0,89, respectivamente.

Utilice las funciones seleccionadas para agrupar de nuevo y guarde los resultados de la agrupación.

Visualice los resultados de la agrupación, dibuje diagramas de dispersión bidimensionales y tridimensionales, y seleccione 2 y 3 características con gran importancia como ejes bidimensionales y tridimensionales (solo hay dos características con alto contenido de potasio seleccionadas en el dibujo tridimensional, y solo necesita agregar otros componentes. El más importante es suficiente, aquí es principalmente para mostrar el efecto de agrupamiento 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:

 

El efecto del agrupamiento jerárquico es básicamente el mismo que el del agrupamiento medio.

Análisis de racionalidad:

Como se muestra en la figura anterior, el mapa tridimensional alto en potasio se agrupa en dos categorías. Combinado con el tipo de meteorización de los puntos de muestra, se puede ver que el que tiene un mayor contenido de sílice en el mapa es después de la meteorización, y el otro con un contenido más bajo son los datos antes de la intemperie, que está en línea con los datos originales. Lo mismo es cierto para el vidrio de plomo-bario. Por ejemplo, el punto rojo en el diagrama bidimensional de tres puntos es el correspondiente punto de meteorización severa, por lo que el resultado de la agrupación se considera razonable.

Análisis de sensibilidad:

Idea: para explorar la sensibilidad de los resultados de la clasificación, usamos el método de control de variables para cambiar el contenido de cada característica en un rango, mientras controlamos el contenido de otras características durante el período, y usamos el modelo de agrupamiento de K-means entrenado para analizar los cambios . Los puntos de muestra se pronostican y la puntuación f1 se utiliza como indicador para cuantificar los resultados de predicción. Si los resultados de predicción de puntos de muestra permanecen sin cambios, los resultados de la clasificación no son sensibles a los cambios en las características individuales y la clasificación los resultados son estables.

Pregunta 3: Analice la composición química de las reliquias culturales de vidrio desconocidas en el Anexo Formulario 3, identifique su tipo y analice la sensibilidad de los resultados de la clasificación.

Simplemente analice si la distribución de características de los datos de prueba es demasiado diferente de la distribución de características del conjunto de entrenamiento y use el modelo establecido en la pregunta 2 para predecir los datos de prueba. Los resultados del uso de máquinas de vectores de soporte o bosques aleatorios son consistentes.

Análisis 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()

          Cambie el contenido de cada característica en un rango y controle el contenido de otras características durante el período. Utilice la puntuación f1 como indicador para cuantificar los resultados de la predicción. Tiene estabilidad.

Supongo que te gusta

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