學(xué)建模國賽C題解析:古代玻璃成分分析與風(fēng)化效應(yīng)預(yù)測)
1. 項目概述與核心價值看到“古代玻璃制品的成分分析與鑒別”這個題目很多初次接觸數(shù)學(xué)建模的同學(xué)可能會有點懵覺得這離我們熟悉的編程、算法有點遠(yuǎn)。但恰恰相反這正是數(shù)學(xué)建模國賽的魅力所在——它要求你跳出純技術(shù)的舒適區(qū)將數(shù)學(xué)工具、數(shù)據(jù)分析方法和計算機技術(shù)應(yīng)用于一個具體的、跨學(xué)科的復(fù)雜問題中。2022年C題本質(zhì)上是一個融合了化學(xué)計量學(xué)、模式識別、統(tǒng)計推斷和文物保護科學(xué)的綜合性數(shù)據(jù)分析項目。簡單來說題目給了我們一批古代玻璃文物的化學(xué)成分檢測數(shù)據(jù)比如二氧化硅、氧化鈉、氧化鉀、氧化鈣等各種氧化物的含量百分比。我們的核心任務(wù)就是扮演一個“文物偵探”或“材料科學(xué)家”通過這些冷冰冰的數(shù)據(jù)回答一系列關(guān)鍵問題這批文物里哪些是高鉀玻璃哪些是鉛鋇玻璃它們的化學(xué)成分有什么規(guī)律不同風(fēng)化程度的玻璃成分發(fā)生了什么變化能否根據(jù)有限的、有缺失的數(shù)據(jù)去預(yù)測未知文物的類型甚至推斷其可能的產(chǎn)地和年代信息這不僅僅是套幾個模型跑一下那么簡單。它考驗的是你從實際問題中抽象出數(shù)學(xué)問題的能力、對數(shù)據(jù)本身深刻的理解、以及將分析結(jié)果翻譯回現(xiàn)實語言的邏輯。整個過程就像是在處理一份來自古代的“材料配方單”我們需要用現(xiàn)代的數(shù)據(jù)科學(xué)工具去解讀古人的工藝密碼。對于有志于從事數(shù)據(jù)分析、人工智能、考古科技等交叉領(lǐng)域的同學(xué)來說這道題是一次絕佳的練兵機會。接下來我將結(jié)合解題思路和關(guān)鍵代碼實現(xiàn)拆解這道題的每一個環(huán)節(jié)分享我們當(dāng)時是如何一步步抽絲剝繭的。2. 解題核心思路與整體設(shè)計面對這樣一個多任務(wù)、數(shù)據(jù)驅(qū)動的題目切忌一上來就埋頭寫代碼。一個好的解題框架能讓你事半功倍避免在錯誤的方向上浪費大量時間。我們的整體思路遵循了“數(shù)據(jù)理解 - 數(shù)據(jù)預(yù)處理 - 探索性分析 - 模型構(gòu)建與求解 - 結(jié)果分析與可視化”的標(biāo)準(zhǔn)數(shù)據(jù)分析流程但每個環(huán)節(jié)都緊密結(jié)合了題目的特殊要求。2.1 問題拆解與任務(wù)對應(yīng)首先我們必須把賽題冗長的描述轉(zhuǎn)化為清晰、可執(zhí)行的數(shù)據(jù)分析任務(wù)。題目通常包含多個小問它們之間往往存在邏輯遞進關(guān)系。分類與規(guī)律挖掘?qū)?yīng)第一問這是基礎(chǔ)。根據(jù)給定的化學(xué)成分?jǐn)?shù)據(jù)按照“高鉀”和“鉛鋇”的劃分標(biāo)準(zhǔn)對文物進行準(zhǔn)確分類。然后分別對這兩大類玻璃進行描述性統(tǒng)計分析尋找其成分含量的統(tǒng)計規(guī)律如均值、方差、范圍、成分之間的關(guān)聯(lián)性相關(guān)性分析以及可能的子類劃分聚類分析。這一步的目標(biāo)是建立對數(shù)據(jù)的“第一印象”。風(fēng)化效應(yīng)分析對應(yīng)第二問這是關(guān)鍵。分析風(fēng)化前后玻璃化學(xué)成分的變化規(guī)律。哪些成分容易流失如堿金屬氧化物哪些成分相對穩(wěn)定或可能富集需要分別討論高鉀玻璃和鉛鋇玻璃在風(fēng)化行為上的異同。這里涉及到差異性檢驗如t檢驗、Mann-Whitney U檢驗和變化程度的量化如計算風(fēng)化前后成分含量的差值或比值。風(fēng)化點預(yù)測與敏感性分析對應(yīng)第三、四問這是深化。基于風(fēng)化規(guī)律預(yù)測風(fēng)化點的原始化學(xué)成分。這本質(zhì)上是一個回歸或矩陣補全問題——我們已知未風(fēng)化部分的數(shù)據(jù)和風(fēng)化規(guī)律要去反推缺失部分風(fēng)化點的原始值。同時還需要分析哪些化學(xué)成分的變化對風(fēng)化最敏感這可以通過計算各成分在風(fēng)化前后的變異系數(shù)、或構(gòu)建預(yù)測模型的特征重要性來評估。未知文物鑒別與分類對應(yīng)第五問及延伸這是綜合應(yīng)用。給出一批新的、類型未知的文物數(shù)據(jù)利用前面建立的分類模型如邏輯回歸、支持向量機、隨機森林等對其進行鑒別。同時還可以基于成分?jǐn)?shù)據(jù)嘗試進行亞類劃分比如鉛鋇玻璃是否可再分為高鉛型、高鋇型或關(guān)聯(lián)分析探討成分與紋飾、顏色、出土環(huán)境等的潛在關(guān)系。2.2 技術(shù)棧選型與工具準(zhǔn)備工欲善其事必先利其器。針對以上任務(wù)我們選擇了以Python為核心的數(shù)據(jù)科學(xué)工具棧原因在于其強大的庫生態(tài)和靈活性。數(shù)據(jù)分析與處理Pandas和NumPy是基石。Pandas的DataFrame結(jié)構(gòu)非常適合處理這種行列清晰的成分表格數(shù)據(jù)其數(shù)據(jù)清洗、分組聚合、合并連接等功能不可或缺??茖W(xué)計算與統(tǒng)計分析SciPy和Statsmodels。用于進行各種統(tǒng)計檢驗t檢驗、方差分析、相關(guān)性檢驗、擬合分布以及更高級的統(tǒng)計建模。機器學(xué)習(xí)與建模Scikit-learn。這個庫提供了幾乎我們所需的所有機器學(xué)習(xí)算法從預(yù)處理標(biāo)準(zhǔn)化、缺失值填充、到分類邏輯回歸、SVM、隨機森林、回歸、聚類K-Means層次聚類、到模型評估一站式解決。數(shù)據(jù)可視化Matplotlib和Seaborn。用于繪制各種統(tǒng)計圖表如成分含量分布箱線圖、相關(guān)性熱力圖、聚類樹狀圖、PCA降維散點圖等。可視化不僅是呈現(xiàn)結(jié)果的手段更是探索數(shù)據(jù)、發(fā)現(xiàn)規(guī)律的重要工具。缺失值處理與高級建模對于第三問的風(fēng)化點預(yù)測可能會用到更專門的工具如fancyimpute庫中的矩陣補全算法如KNN插補、矩陣分解或自行構(gòu)建回歸模型。注意在比賽環(huán)境中不建議盲目追求最新、最復(fù)雜的模型。模型的可解釋性和與問題的貼合度比單純的精度更重要。例如對于成分規(guī)律總結(jié)清晰的統(tǒng)計描述和可視化可能比一個復(fù)雜的黑箱模型更有說服力。3. 數(shù)據(jù)預(yù)處理從原始數(shù)據(jù)到可用特征拿到的數(shù)據(jù)通常不是“干凈”的。直接建模等于“垃圾進垃圾出”。預(yù)處理環(huán)節(jié)至關(guān)重要往往能決定后續(xù)分析的成敗。3.1 數(shù)據(jù)加載與初步審查import pandas as pd import numpy as np # 假設(shè)數(shù)據(jù)保存在‘glass_data.csv’中包含文物編號、類型、風(fēng)化情況、以及各種氧化物含量列 df pd.read_csv(glass_data.csv) # 1. 查看數(shù)據(jù)概覽 print(“數(shù)據(jù)形狀”, df.shape) # (樣本數(shù) 特征數(shù)) print(“\n前5行數(shù)據(jù)”) print(df.head()) print(“\n數(shù)據(jù)基本信息”) print(df.info()) print(“\n描述性統(tǒng)計”) print(df.describe()) # 2. 檢查缺失值 missing_sum df.isnull().sum() print(“\n各列缺失值數(shù)量”) print(missing_sum[missing_sum 0]) # 只顯示有缺失的列這一步能讓我們快速了解有多少件文物行測量了哪些成分列有沒有缺失值數(shù)據(jù)類型是否正確特別是“風(fēng)化點”的數(shù)據(jù)很可能整行或整列為空需要特別標(biāo)記。3.2 缺失值處理策略古代玻璃數(shù)據(jù)中缺失值非常常見可能因為檢測限、樣品污染或數(shù)據(jù)記錄不全。處理時需要謹(jǐn)慎區(qū)分情況整列缺失或全為零如果某個化學(xué)成分如P2O5在所有樣本中都是缺失或為零可以考慮直接刪除該特征因為它不提供任何信息。部分缺失Missing at Random對于數(shù)值型特征氧化物含量不宜簡單用0或均值填充因為0代表不含該成分有特定化學(xué)意義。常用方法有中位數(shù)/均值填充在同一類玻璃高鉀/鉛鋇內(nèi)部進行填充更合理。K近鄰KNN填充利用其他成分相似的樣本的值來填充。多重插補更嚴(yán)謹(jǐn)?shù)珡?fù)雜。對于類別型特征如紋飾可以用“未知”或眾數(shù)填充。from sklearn.impute import KNNImputer # 假設(shè)我們決定對數(shù)值型成分列使用KNN填充先分離特征和標(biāo)簽 feature_columns [‘SiO2’ ‘Na2O’ ‘K2O’ …] # 所有氧化物列名 df_features df[feature_columns].copy() # 初始化KNN插補器選擇鄰居數(shù) imputer KNNImputer(n_neighbors5, weights‘distance’) df_features_filled pd.DataFrame(imputer.fit_transform(df_features), columnsdf_features.columns) # 將填充后的特征合并回原數(shù)據(jù)框 df[feature_columns] df_features_filled實操心得對于風(fēng)化點預(yù)測問題第三問處理缺失值的策略需要調(diào)整。風(fēng)化點的數(shù)據(jù)不能參與任何基于全體數(shù)據(jù)的填充過程否則會造成數(shù)據(jù)泄露。正確的做法是先將風(fēng)化點數(shù)據(jù)單獨取出僅使用未風(fēng)化點的數(shù)據(jù)訓(xùn)練一個填充或預(yù)測模型再用這個模型去預(yù)測風(fēng)化點的缺失值。3.3 數(shù)據(jù)標(biāo)準(zhǔn)化與特征工程化學(xué)成分?jǐn)?shù)據(jù)通常是百分比量綱一致但數(shù)值范圍差異可能很大例如SiO2可能高達70%而某些微量元素不到1%。對于基于距離的模型如K-Means聚類 KNN和某些對尺度敏感的模型需要進行標(biāo)準(zhǔn)化。from sklearn.preprocessing import StandardScaler scaler StandardScaler() df_features_scaled scaler.fit_transform(df_features_filled) df_scaled pd.DataFrame(df_features_scaled, columnsfeature_columns) df_scaled[‘類型’] df[‘類型’].values # 將標(biāo)簽列加回來特征工程方面可以考慮比值特征如K2O/(K2ONa2O)鉀鈉比這可能對區(qū)分高鉀玻璃有指示意義??偤蜋z查各氧化物百分比之和應(yīng)接近100%考慮誤差。如果總和偏差過大可能意味著數(shù)據(jù)有問題或存在未測成分。風(fēng)化相關(guān)特征對于第二問可以計算“風(fēng)化程度”指標(biāo)或者直接使用“風(fēng)化前-風(fēng)化后”的差值作為新特征。4. 核心問題一分類與成分規(guī)律挖掘4.1 基于規(guī)則的分類驗證題目已經(jīng)給出了分類標(biāo)準(zhǔn)高鉀、鉛鋇但數(shù)據(jù)中可能已有“類型”列。第一步是驗證或執(zhí)行這一分類。如果數(shù)據(jù)中只有化學(xué)成分我們需要根據(jù)定義來劃分。例如鉛鋇玻璃通常指PbO和BaO含量顯著高于其他類型。# 假設(shè)根據(jù)經(jīng)驗或題目提示定義閾值 def classify_glass(row): if row[‘PbO’] 10 and row[‘BaO’] 5: # 閾值需根據(jù)數(shù)據(jù)分布調(diào)整 return ‘鉛鋇玻璃’ elif row[‘K2O’] row[‘Na2O’] and row[‘K2O’] 5: # 高鉀玻璃的簡單判據(jù) return ‘高鉀玻璃’ else: return ‘未知’ df[‘預(yù)測類型’] df.apply(classify_glass, axis1) # 與已有標(biāo)簽對比檢查一致性4.2 描述性統(tǒng)計與可視化分析分類后分別對兩組數(shù)據(jù)進行統(tǒng)計分析這是回答“成分規(guī)律”最直接的方法。import seaborn as sns import matplotlib.pyplot as plt # 1. 分組描述性統(tǒng)計 grouped df_scaled.groupby(‘類型’)[feature_columns] description grouped.describe().T # 轉(zhuǎn)置以便查看 print(description.loc[(:, [‘mean’ ‘std’ ‘50%’]) :]) # 查看均值、標(biāo)準(zhǔn)差、中位數(shù) # 2. 繪制成分含量分布箱線圖以SiO2為例 plt.figure(figsize(10 6)) sns.boxplot(x‘類型’ y‘SiO2’ datadf) plt.title(‘高鉀玻璃與鉛鋇玻璃SiO2含量分布對比’) plt.ylabel(‘SiO2含量 (%)’) plt.show() # 3. 繪制多成分平行坐標(biāo)圖觀察整體模式 from pandas.plotting import parallel_coordinates plt.figure(figsize(12 6)) parallel_coordinates(df[df[‘類型’].isin([‘高鉀’ ‘鉛鋇’])][[‘類型’] feature_columns[:8]] ‘類型’) # 選取前8個特征避免線條過密 plt.title(‘兩類玻璃化學(xué)成分平行坐標(biāo)圖’) plt.show()4.3 相關(guān)性分析與聚類探索了解各成分之間的相互關(guān)系以及每類玻璃內(nèi)部是否存在亞類。# 1. 計算并繪制相關(guān)性熱力圖以高鉀玻璃為例 df_high_k df_scaled[df_scaled[‘類型’]‘高鉀’][feature_columns] corr_matrix df_high_k.corr() plt.figure(figsize(10 8)) sns.heatmap(corr_matrix annotTrue fmt‘.2f’ cmap‘coolwarm’ center0) plt.title(‘高鉀玻璃化學(xué)成分相關(guān)性熱力圖’) plt.show() # 2. 主成分分析PCA降維可視化 from sklearn.decomposition import PCA pca PCA(n_components2) X_pca pca.fit_transform(df_features_scaled) df[‘PCA1’] df[‘PCA2’] X_pca[: 0] X_pca[: 1] plt.figure(figsize(10 8)) sns.scatterplot(x‘PCA1’ y‘PCA2’ hue‘類型’ style‘風(fēng)化’ datadf s100) plt.title(‘PCA降維可視化顏色類型 標(biāo)記風(fēng)化’) plt.xlabel(f‘PC1 ({pca.explained_variance_ratio_[0]:.2%})’) plt.ylabel(f‘PC2 ({pca.explained_variance_ratio_[1]:.2%})’) plt.legend(bbox_to_anchor(1.05 1) loc‘upper left’) plt.tight_layout() plt.show() # 3. 層次聚類探索亞類 from scipy.cluster.hierarchy import dendrogram linkage Z linkage(df_high_k ‘ward’) plt.figure(figsize(12 5)) dendrogram(Z labelsdf[df[‘類型’]‘高鉀’].index.tolist()) plt.title(‘高鉀玻璃層次聚類樹狀圖’) plt.xlabel(‘樣本編號’) plt.ylabel(‘距離’) plt.show()通過PCA圖我們可以直觀看到兩類玻璃是否能在成分空間中被明顯區(qū)分以及風(fēng)化樣本是否聚集在特定區(qū)域。層次聚類可以幫助我們發(fā)現(xiàn)高鉀或鉛鋇玻璃內(nèi)部是否存在自然的成分分組這可能對應(yīng)不同的工藝或時期。5. 核心問題二風(fēng)化效應(yīng)機理分析這是本題的物理化學(xué)核心。我們需要量化風(fēng)化帶來的變化。5.1 數(shù)據(jù)準(zhǔn)備配對樣本與未配對樣本理想情況是有同一文物風(fēng)化前后配對的數(shù)據(jù)。但賽題數(shù)據(jù)更可能是同一批文物中有些風(fēng)化嚴(yán)重有些輕微或未風(fēng)化。我們需要將樣本按“類型”和“風(fēng)化程度”分組。# 假設(shè)有‘風(fēng)化程度’列或根據(jù)‘表面風(fēng)化’列為‘是’/‘否’來劃分 df[‘是否風(fēng)化’] df[‘表面風(fēng)化’].map({‘是’: 1 ‘否’: 0}) # 分組比較 weathered df[df[‘是否風(fēng)化’]1] unweathered df[df[‘是否風(fēng)化’]0] # 分別對高鉀和鉛鋇玻璃進行對比 for glass_type in [‘高鉀’ ‘鉛鋇’]: w_subset weathered[weathered[‘類型’]glass_type][feature_columns] uw_subset unweathered[unweathered[‘類型’]glass_type][feature_columns] print(f”\n {glass_type}玻璃 風(fēng)化 vs 未風(fēng)化 成分均值對比 “) mean_comparison pd.DataFrame({ ‘風(fēng)化均值’: w_subset.mean() ‘未風(fēng)化均值’: uw_subset.mean() ‘絕對變化’: w_subset.mean() - uw_subset.mean() ‘相對變化(%)’: (w_subset.mean() - uw_subset.mean()) / uw_subset.mean() * 100 }) print(mean_comparison.sort_values(by‘絕對變化’ ascendingFalse))5.2 統(tǒng)計顯著性檢驗均值差異可能由偶然導(dǎo)致需要進行統(tǒng)計檢驗。由于成分?jǐn)?shù)據(jù)不一定符合正態(tài)分布且樣本量可能不大曼-惠特尼U檢驗非參數(shù)檢驗通常比t檢驗更穩(wěn)健。from scipy.stats import mannwhitneyu significant_changes [] for col in feature_columns: for glass_type in [‘高鉀’ ‘鉛鋇’]: w_data weathered[(weathered[‘類型’]glass_type)][col].dropna() uw_data unweathered[(unweathered[‘類型’]glass_type)][col].dropna() if len(w_data) 3 and len(uw_data) 3: # 確保有足夠樣本 stat p mannwhitneyu(w_data uw_data alternative‘two-sided’) if p 0.05: # 顯著性水平設(shè)為0.05 significant_changes.append({ ‘成分’: col ‘類型’: glass_type ‘p值’: p ‘風(fēng)化中位數(shù)’: np.median(w_data) ‘未風(fēng)化中位數(shù)’: np.median(uw_data) }) significant_df pd.DataFrame(significant_changes) print(“\n風(fēng)化前后有顯著變化的成分”) print(significant_df.sort_values([‘類型’ ‘p值’]))5.3 風(fēng)化規(guī)律總結(jié)與機理推斷根據(jù)上述分析我們可以總結(jié)高鉀玻璃風(fēng)化通常表現(xiàn)為K2ONa2O等堿金屬氧化物顯著流失含量降低而SiO2Al2O3等網(wǎng)絡(luò)形成體相對富集百分比升高。可能伴隨CaO的流失。鉛鋇玻璃風(fēng)化除了堿金屬流失PbO可能發(fā)生溶出或轉(zhuǎn)化為不溶化合物如碳酸鉛導(dǎo)致其含量變化復(fù)雜。BaO的行為也可能有特殊性。共性P2O5MgO等成分的變化趨勢也需要關(guān)注。注意事項在解釋“含量升高”時務(wù)必謹(jǐn)慎。這通常是相對含量的升高因為其他成分如堿金屬流失了導(dǎo)致剩余成分的百分比增加而非絕對量增加。在報告中應(yīng)明確指出這一點避免產(chǎn)生“風(fēng)化產(chǎn)生了新成分”的誤解。6. 核心問題三風(fēng)化點預(yù)測與敏感性分析6.1 預(yù)測模型構(gòu)建思路預(yù)測風(fēng)化點的原始成分可以看作一個有監(jiān)督的回歸問題。對于每個化學(xué)成分我們都可以訓(xùn)練一個模型。輸入特征X該文物未風(fēng)化部分的所有化學(xué)成分含量。假設(shè)一個文物有多個采樣點其中一些是未風(fēng)化的已知原始成分一些是風(fēng)化的已知當(dāng)前成分未知原始成分。我們可以用未風(fēng)化點的數(shù)據(jù)作為訓(xùn)練特征。預(yù)測目標(biāo)y對于某個特定的化學(xué)成分如SiO2其原始含量。關(guān)鍵點對于風(fēng)化點我們只知道它風(fēng)化后的當(dāng)前成分。但我們的模型目標(biāo)是預(yù)測其風(fēng)化前的原始成分。因此我們不能直接用風(fēng)化點的當(dāng)前數(shù)據(jù)作為特征來訓(xùn)練。我們需要找到一個映射關(guān)系從同一文物未風(fēng)化點的當(dāng)前成分到該文物任何點包括風(fēng)化點的原始成分。一種簡化而有效的思路是假設(shè)同一文物不同點位在未風(fēng)化狀態(tài)下成分是均勻的或存在某種可推斷的空間關(guān)系。那么一個風(fēng)化點的原始成分就應(yīng)該等于該文物未風(fēng)化點成分的某種“代表值”如均值。更復(fù)雜的模型可以考慮成分之間的協(xié)同變化關(guān)系。# 假設(shè)數(shù)據(jù)結(jié)構(gòu)每一行是一個采樣點包含文物ID、點位編號、是否風(fēng)化點、各成分當(dāng)前含量。 # 我們需要為每個文物建立一個從“未風(fēng)化點數(shù)據(jù)”到“該文物原始成分均值”的映射。 # 步驟1計算每個文物未風(fēng)化點的成分均值作為該文物的“原始成分參考值” df[‘文物ID’] … # 從編號中提取文物ID unweathered_means df[df[‘是否風(fēng)化’]0].groupby(‘文物ID’)[feature_columns].mean().reset_index() unweathered_means.rename(columns{col: f’ref_{col}‘ for col in feature_columns} inplaceTrue) # 步驟2將參考值合并回原數(shù)據(jù)框但只合并到未風(fēng)化點作為訓(xùn)練標(biāo)簽 df_train df[df[‘是否風(fēng)化’]0].merge(unweathered_means on‘文物ID’ how‘left’) # 步驟3對每一種成分訓(xùn)練一個回歸模型以未風(fēng)化點的當(dāng)前成分為特征以該文物的參考值為目標(biāo) from sklearn.ensemble import RandomForestRegressor from sklearn.model_selection import cross_val_score prediction_models {} for comp in feature_columns: X_train df_train[feature_columns].values y_train df_train[f’ref_{comp}‘].values model RandomForestRegressor(n_estimators100 random_state42) # 使用交叉驗證評估模型在該文物內(nèi)部預(yù)測的能力 scores cross_val_score(model X_train y_train cv5 scoring‘r2’) print(f”訓(xùn)練{comp}預(yù)測模型交叉驗證R^2平均分{scores.mean():.3f}“) model.fit(X_train y_train) prediction_models[comp] model # 步驟4預(yù)測風(fēng)化點的原始成分 df_weathered df[df[‘是否風(fēng)化’]1].copy() for comp in feature_columns: X_pred df_weathered[feature_columns].values df_weathered[f’pred_original_{comp}‘] prediction_models[comp].predict(X_pred)6.2 敏感性分析哪些成分最不穩(wěn)定敏感性分析旨在找出在風(fēng)化過程中變化最大、最不穩(wěn)定的成分。我們可以用變異系數(shù)或風(fēng)化前后差值的中位數(shù)絕對值來衡量。sensitivity_list [] for comp in feature_columns: for glass_type in [‘高鉀’ ‘鉛鋇’]: # 計算該類玻璃風(fēng)化前后的差值 w_vals weathered[weathered[‘類型’]glass_type][comp] uw_vals unweathered[unweathered[‘類型’]glass_type][comp] # 使用中位數(shù)差值的絕對值來度量變化幅度避免極端值影響 median_change np.median(np.abs(w_vals - uw_vals.mean())) # 近似計算 # 或者計算風(fēng)化組內(nèi)部的變異系數(shù) cv w_vals.std() / w_vals.mean() if w_vals.mean() ! 0 else np.nan sensitivity_list.append({ ‘成分’: comp ‘類型’: glass_type ‘變化幅度中位數(shù)’: median_change ‘風(fēng)化組變異系數(shù)’: cv }) sensitivity_df pd.DataFrame(sensitivity_list) print(“\n成分風(fēng)化敏感性排序變化幅度越大越敏感”) print(sensitivity_df.sort_values([‘類型’ ‘變化幅度中位數(shù)’] ascending[True False]))7. 核心問題四未知文物鑒別與模型應(yīng)用7.1 構(gòu)建分類鑒別模型現(xiàn)在我們利用已標(biāo)注類型的數(shù)據(jù)構(gòu)建一個分類器用于預(yù)測新文物的類型。from sklearn.model_selection import train_test_split from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import classification_report confusion_matrix # 準(zhǔn)備數(shù)據(jù)使用已分類且數(shù)據(jù)質(zhì)量較好的樣本 df_labeled df.dropna(subset[‘類型’]).copy() X df_labeled[feature_columns] y df_labeled[‘類型’] # 劃分訓(xùn)練集和測試集 X_train X_test y_train y_test train_test_split(X y test_size0.2 random_state42 stratifyy) # 訓(xùn)練隨機森林分類器 clf RandomForestClassifier(n_estimators200 max_depth10 random_state42) clf.fit(X_train y_train) # 在測試集上評估 y_pred clf.predict(X_test) print(“分類性能報告”) print(classification_report(y_test y_pred)) print(“\n混淆矩陣”) print(confusion_matrix(y_test y_pred)) # 查看特征重要性了解哪些化學(xué)成分對分類貢獻大 feature_importance pd.DataFrame({ ‘feature’: feature_columns ‘importance’: clf.feature_importances_ }).sort_values(‘importance’ ascendingFalse) print(“\n特征重要性排序”) print(feature_importance.head(10))7.2 模型應(yīng)用與結(jié)果解釋訓(xùn)練好模型后就可以對新的未知文物數(shù)據(jù)進行預(yù)測。# 假設(shè)new_data是新的文物化學(xué)成分DataFrame new_data pd.read_csv(‘new_unknown_glass.csv’) # 確保特征列與訓(xùn)練時一致并進行相同的預(yù)處理填充、標(biāo)準(zhǔn)化 new_data_processed … # 應(yīng)用與訓(xùn)練數(shù)據(jù)相同的預(yù)處理流程 new_predictions clf.predict(new_data_processed[feature_columns]) new_data[‘預(yù)測類型’] new_predictions # 不僅可以給出類別還可以給出概率增加可信度 prediction_proba clf.predict_proba(new_data_processed[feature_columns]) for i glass_type in enumerate(clf.classes_): new_data[f’{glass_type}_概率‘] prediction_proba[: i] print(new_data[[‘文物編號’ ‘預(yù)測類型’ ‘高鉀玻璃_概率’ ‘鉛鋇玻璃_概率’]].head())實操心得在數(shù)學(xué)建模論文中不要只扔出一個準(zhǔn)確率。要結(jié)合特征重要性和成分規(guī)律分析來解釋模型。例如如果模型主要依據(jù)PbO和BaO來分類這與我們之前發(fā)現(xiàn)的鉛鋇玻璃特征相符那么模型的決策就是可解釋的、合理的。如果發(fā)現(xiàn)某個不起眼的微量元素權(quán)重很高就需要回到數(shù)據(jù)本身檢查是否存在噪聲或特殊關(guān)聯(lián)。8. 常見問題、避坑指南與進階思考在實際解題和編碼過程中我們遇到了不少坑也總結(jié)出一些能讓你的解決方案更出彩的要點。8.1 數(shù)據(jù)層面的陷阱成分加和問題玻璃化學(xué)成分?jǐn)?shù)據(jù)總和應(yīng)接近100%。如果發(fā)現(xiàn)大量樣本總和遠(yuǎn)低于或高于100%需檢查是否存在重大缺失或誤差。處理時可以選擇歸一化到100%但需在報告中說明。異常值處理箱線圖或3σ原則可以幫助發(fā)現(xiàn)異常值。對于明顯偏離群體、且可能由測量誤差導(dǎo)致的極端值需要謹(jǐn)慎處理如用上下限截斷或視為缺失值并分析其對模型的影響。類別不平衡如果高鉀和鉛鋇玻璃的樣本數(shù)量懸殊分類模型可能會偏向多數(shù)類??梢允褂眠^采樣SMOTE、欠采樣或調(diào)整類別權(quán)重如class_weight‘balanced’來應(yīng)對。8.2 模型選擇與驗證避免過擬合尤其是在樣本量不大的情況下。務(wù)必使用交叉驗證來評估模型泛化能力而不是只看訓(xùn)練集準(zhǔn)確率。隨機森林、邏輯回歸等模型相對不容易過擬合。模型對比不要只用一個模型??梢試L試邏輯回歸、SVM、隨機森林、XGBoost等在驗證集上比較它們的性能。選擇那個性能穩(wěn)定、可解釋性好的模型。風(fēng)化預(yù)測的特殊性第三問的預(yù)測模型其驗證方式很特殊。因為你沒有風(fēng)化點的真實原始值。一種評估思路是在未風(fēng)化數(shù)據(jù)上**人為“腐蝕”**一部分?jǐn)?shù)據(jù)模擬風(fēng)化如按一定比例降低堿金屬含量然后用剩余未風(fēng)化部分訓(xùn)練模型去預(yù)測這些“模擬風(fēng)化點”的原始值與真實值比較來評估模型效果。8.3 結(jié)果呈現(xiàn)與論文寫作一圖勝千言多用高質(zhì)量的圖表。PCA散點圖、成分對比箱線圖、相關(guān)性熱力圖、聚類樹狀圖、特征重要性條形圖都是非常有效的展示工具。確保圖表清晰、有標(biāo)注、配色專業(yè)。分析緊扣問題每一個分析步驟、每一個模型結(jié)果都要回答賽題中的一個具體問題。在論文中形成“問題 - 方法 - 結(jié)果 - 分析 - 結(jié)論”的清晰鏈條。靈敏度分析對于你設(shè)定的關(guān)鍵參數(shù)如分類閾值、KNN的K值、聚類數(shù)目、模型超參數(shù)進行簡單的靈敏度分析說明你的結(jié)果對這些參數(shù)的選擇不敏感是穩(wěn)健的。討論局限性誠實地指出你方法的假設(shè)和局限性。例如“假設(shè)同一文物未風(fēng)化點成分均勻”、“未考慮微量元素的影響”、“風(fēng)化過程模擬較為簡化”等。這體現(xiàn)了批判性思維。8.4 代碼實現(xiàn)技巧模塊化與函數(shù)化將數(shù)據(jù)加載、預(yù)處理、分析、建模、畫圖等步驟寫成獨立的函數(shù)或類。這使代碼清晰、易于調(diào)試和復(fù)用。使用PipelineScikit-learn的Pipeline可以將預(yù)處理和建模步驟封裝起來避免數(shù)據(jù)泄露尤其在進行交叉驗證時非常安全。設(shè)置隨機種子在涉及隨機性的操作如數(shù)據(jù)分割、隨機森林前使用np.random.seed()和random_state參數(shù)確保結(jié)果可復(fù)現(xiàn)。注釋與文檔關(guān)鍵步驟和復(fù)雜邏輯加上簡明注釋。這對團隊協(xié)作和后期檢查至關(guān)重要。這道2022年國賽C題是一個經(jīng)典的數(shù)據(jù)分析驅(qū)動的研究型題目。它沒有標(biāo)準(zhǔn)答案考察的是你運用數(shù)據(jù)科學(xué)工具解決一個模糊、開放的現(xiàn)實問題的全過程能力。從數(shù)據(jù)清洗的耐心到探索性分析的洞察力再到模型構(gòu)建的嚴(yán)謹(jǐn)性最后到結(jié)果闡釋的邏輯性每一個環(huán)節(jié)都至關(guān)重要。希望這份詳細(xì)的思路和代碼參考能幫助你搭建起解決此類問題的完整框架。在實際比賽中最重要的是形成你自己團隊的故事線并用數(shù)據(jù)和模型清晰地把它講出來。