我們來探索一下數據集。我們將開始加載分析和預測所需的所有庫:
#Pandas for dataframes
import pandas as pd
#Changing default display option to display all columns
pd.set_option('display.max_columns', 21)
#Numpy for numerical computing
import numpy as np
#Matplotlib for visualization
import matplotlib.pyplot as plt
#Display plots in the notebook
%matplotlib inline
#Seaborn for easier visualization
import seaborn as sns
#Stats package for statistical analysis
from scipy import stats
#Machine learning packages
from sklearn.linear_model import LogisticRegression
from sklearn.ensemble import RandomForestClassifier, GradientBoostingClassifier
from sklearn.model_selection import train_test_split, cross_val_score, cross_val_predict, GridSearchCV
from sklearn.pipeline import make_pipeline, Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_curve, roc_auc_score, auc, accuracy_score, confusion_matrix, classification_report, cohen_kappa_score
from sklearn.utils import resample
from sklearn.dummy import DummyClassifier
from sklearn.model_selection import KFold
#Neural Networks packages
from keras.layers import Dense, Dropout
from keras.models import Sequential
from keras.utils import to_categorical
from keras.wrappers.scikit_learn import KerasClassifier
加載數據集
df = pd.read_csv('/sw_health_raw_data.csv', parse_dates=True)
我們來看看數據集的整體特徵
大多數變量都是數字。我們來看看數據的第一行和最後五行:
兩端的數據看起來一致,並沒有明顯的錯誤。'next_reimage'列中有NaNs,對應於zone = 0。由於'next_reimage'定義了'zone'變量,因此我們不需要將兩者都保留在數據集中,並且只能保留'zone'變量為了預測模型的建立。
現在我們來檢查一下變量是否有缺失值:
#Checking for NaNs
for i in df.columns:
print(i, ": ", df.loc[:,i].isnull().values.any())
數據中沒有缺失值,除了預期的'next_reimage'列。數據集描述中提到了'date'變量,因此也沒有缺失值。
在研究變量的分佈之前,讓我們先做一些清理。我將'日期'轉換為日期時間對象並刪除'next_reimage'變量。此外,讓我們將“Zone”變量的0級別重命名為“7”,以便健康級別的變化看起來更合乎邏輯。
#清理數據集
df_cleaned = df.copy()
df_cleaned ['date'] = pd.to_datetime(df_cleaned.date)
df_cleaned = df_cleaned.drop('next_reimage',axis = 1)
df_cleaned.zone.replace(0,7 ,inplace = True)
接下來,讓我們看看數據集中數值變量的分佈:
變量“free_physical_memory”、“free_virtual_memory”和“daily_average_ram”都有最小值為0,這是沒有意義的。無論系統的性能如何,在現實生活中這些值的最小值不能為零。接下來,“average_time_since_last_boot”具有負值,這也沒有意義。daily_average_ram的最大值是1418.6%,這是不可能的。
讓我們看看發生這種情況的事例的數量:
上述所有情況都表示數據集的一小部分,可以刪除。讓我們放棄那些實例:
#Dropping the erroneous instances
df_cleaned = df_cleaned.loc[(df_cleaned['free_physical_memory'] > 0)]
df_cleaned = df_cleaned.loc[(df_cleaned['free_virtual_memory'] > 0)]
df_cleaned = df_cleaned.loc[(df_cleaned['daily_average_ram'] <= 100)]
df_cleaned = df_cleaned.loc[(df_cleaned['average_time_since_last_boot'] > 0)]
數據集中表示的時間段為3個月:
接下來,讓我們看看每個響應變量(“zone”)的級別是如何分佈的。為這一數量的數據繪製單個的條形圖需要花費大量的計算時間,因此我們將使用匯總表和這些分佈的圖表來評估變量的分佈屬性。首先,讓我們看一下區域的響應數量:
在這裡,我們遇到了真實世界數據集的第一個標誌:幾乎96%的數據集條目屬於區域7(PC沒有問題),這是合乎邏輯的 。實際上,區域1到5僅佔所有數據的0.3%。這使得數據集非常不平衡,這使得標準模型評估指標如準確性得分與這種情況關係不大。在區域1-5之間,每個區域的行數大致相同,區域6的觀察值比前面的5個區域多10倍。
現在讓我們看看通過繪製彙總表和圖形,每個區域變量的平均值是否存在顯著差異:
#Converting a 'groupby' object to a DataFrame
means = df_cleaned.groupby('zone').mean().reset_index()
#Plotting the charts
plt.figure(figsize=(17,16))
plt.subplot(4,2,1)
plt.title('Mean of free physical memory by zones')
plt.plot('zone', 'free_physical_memory', data= means, marker='o', linestyle='dashed')
plt.ylabel('free physical memory')
plt.xlim(7,1)
plt.subplot(4,2,2)
plt.title('Mean of free virtual memory by zones')
plt.plot('zone', 'free_virtual_memory', data= means, marker='o', linestyle='dashed')
plt.ylabel('free virtual memory')
plt.xlim(7,1)
plt.subplot(4,2,3)
plt.title('Mean of daily average ram by zones')
plt.plot('zone', 'daily_average_ram', data= means, marker='o', linestyle='dashed')
plt.ylabel('daily average ram')
plt.xlim(7,1)
plt.subplot(4,2,4)
plt.title('Mean of daily ram std dev by zones')
plt.plot('zone', 'daily_std_dev_ram', data= means, marker='o', linestyle='dashed')
plt.ylabel('daily ram std dev')
plt.xlim(7,1)
plt.subplot(4,2,5)
plt.title('Share of observations with Windows events by zones')
plt.plot('zone', 'windows_events_count', data= means, marker='o', linestyle='dashed')
plt.ylabel('observations with windows events')
plt.xlim(7,1)
plt.subplot(4,2,6)
plt.title('Share of observations with BIOS error by zones')
plt.plot('zone', 'has_bios_error', data= means, marker='o', linestyle='dashed')
plt.ylabel('observations with BIOS error')
plt.xlim(7,1)
plt.subplot(4,2,7)
plt.title('Mean of driver crash count by zones')
plt.plot('zone', 'driver_crash_count', data= means, marker='o', linestyle='dashed')
plt.xlabel('zone')
plt.ylabel('driver crash count')
plt.xlim(7,1)
plt.subplot(4,2,8)
plt.title('Mean of avg time since last boot by zones')
plt.plot('zone', 'average_time_since_last_boot', data= means, marker='o', linestyle='dashed')
plt.xlabel('zone')
plt.ylabel('avgt time')
plt.xlim(7,1)
plt.tight_layout()
plt.show()
基於上述,我們可以做出幾點觀察。首先,隨著設備接近臨界狀態(區域1),空閒物理內存的平均量趨於略微增加,並且隨著設備離開區域7-6進入區域5,空閒虛擬內存量顯著下降。均值的日均RAM值在設備接近臨界狀態時下降約6pp,而該平均值的標準差增加。
在第7區中約95%的觀測值具有Windows事件,而其他區域中該變量接近99%。隨著設備進入5-1區,觀察到的具有BIOS錯誤的觀測份額顯著增加,因此這個變量可能成為即將到來的設備重新映像的有力預測器。
最後,當設備接近臨界狀態時,驅動器崩潰的平均數實際上會減少。自上次啟動以來平均時間的平均值也大幅下降,這意味著接近臨界狀態的設備往往會更頻繁地重新啟動。
一般來說,所有預測因子在“健康”(7-6)和“不健康”(5-1)區域之間的平均值中表現出明顯的差異,所以將它們全部納入預測模型是合理的。然而,區域之間差異的絕對值並不大,這可能會影響預測的準確性。
現在,讓我們用皮爾遜的偏度係數來考察變量按區域分佈的偏度:
#Calculating Pearson's coefficient of skewness for the predictors vs. the levels of the 'zone' variable
3*(df_cleaned.groupby('zone').mean() - df_cleaned.groupby('zone').median())/df_cleaned.groupby('zone').std()
對於所有區域,預測變量的分佈基本上是傾斜的,這意味著存在大量的異常值,並且大多數變量具有正偏差。我們來看看這些變量的區域圖。Pandas的標準boxplot()函數不會產生令人滿意的結果,所以我將不得不為56個圖表創建一個手動網格。我還必須限制x軸,以便刪除一些過度縮小圖表的異常值。
plt.figure(figsize=(30,25))
counter = 1
for i in range(1,8):
plt.subplot(7,8,counter)
plt.title('free_physical_memory')
sns.boxplot(x='free_physical_memory', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.ylabel('zone ' + str(i))
plt.xlabel(' ')
plt.xlim(0, 256156)
counter += 1
plt.subplot(7,8,counter)
plt.title('free_virtual_memory')
sns.boxplot(x='free_virtual_memory', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
plt.xlim(0, 381930)
counter += 1
plt.subplot(7,8,counter)
plt.title('daily_average_ram')
sns.boxplot(x='daily_average_ram', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
plt.xlim(0,100)
counter += 1
plt.subplot(7,8,counter)
plt.title('daily_std_dev_ram')
sns.boxplot(x='daily_std_dev_ram', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
plt.xlim(0,100)
counter += 1
plt.subplot(7,8,counter)
plt.title('windows_events_count')
sns.countplot(x='windows_events_count', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
counter += 1
plt.subplot(7,8,counter)
plt.title('has_bios_error')
sns.countplot(x='has_bios_error', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
counter += 1
plt.subplot(7,8,counter)
plt.title('driver_crash_count')
sns.boxplot(x='driver_crash_count', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
plt.xlim(0,300)
counter += 1
plt.subplot(7,8,counter)
plt.title('average_time_since_last_boot')
sns.boxplot(x='average_time_since_last_boot', data=df_cleaned.loc[df_cleaned['zone'] == i])
plt.xlabel(' ')
plt.xlim(0, 11991245)
counter += 1
plt.tight_layout()
plt.show()
可以看出,所有變量的分佈實際上對於區域1至5是相同的。區域6和7在變量'free_physical_memory','free_virtual_memory','daily_std_dev_ram','driver_crash_count'和'average_time_since_last_boot'中具有明顯更多的異常值。區域6-7的'daily_average_ram'分佈比其他區域更為對稱,並向更大的值移動。另一方面,'daily_std_dev_ram'的平均值小於1-5區。最後,'has_bios_error'變量的分佈與區1-5相比是顛倒的 - 大多數區域6-7設備沒有BIOS錯誤。
統計分析
我們來繪製數據集的關聯熱圖:
#Calculate correlations between the features and predictor
correlations = df_cleaned.corr()
#Make the figsize 7 x 6
plt.figure(figsize=(7,6))
#Plot heatmap of correlations
_ = sns.heatmap(correlations, cmap="Greens", annot=True)
可以看出,“區域”變量與數據集中的預測因子具有非常小的相關性,這並不令人驚訝,因為隨著設備從一個區域向另一個區域前進,預測變量值的絕對值變化很小。與此同時,一些預測因素具有實質相關性:'free_virtual_memory'與'free_physical_memory'強烈正相關,這是合理的,因為較大的虛擬內存會降低系統對空閒物理內存的需求。'daily_average_ram'和'daily_std_dev_ram'與'free_physical_memory'負相關,這也是有意義的,因為如果可用物理內存的數量增加,平均RAM(物理內存)使用量將減少。最後,'daily_average_ram'和'daily_std_dev_ram'之間有一個小的正相關,
對數據集進行下取樣
如前所述,屬於區域1至5的觀察值僅佔所有數據的0.3%,這使得數據集非常不平衡。解決不平衡數據集有多種可能的方法,但是,考慮到我們的數據集大小(5.6M觀察值)和計算限制(建模在具有i7處理器和16Gb RAM的計算機上完成),我會使用下采樣方法。這種方法也是有意義的,因為區域6-7的值的分佈相對平衡,並且具有幾百萬個觀察值與幾千個隨機採樣的觀測值在我們的情況下不會增加太多價值。
如果使用基於雲計算的並行化計算資源,數據集可以保持原樣,但這種方法超出了當前研究項目的範圍。
為了將類別6-7與類別1-5相提並論,我們將隨機抽取類別6和類別7的5,000個觀測值,並創建一個新的下采樣數據集。
#Separating zones 1 and 5
df_1_5 = df_cleaned[((df_cleaned.zone!=6) & (df_cleaned.zone!=7))]
#Separating zones 6 and 7
df_6 = df_cleaned[df_cleaned.zone==6]
df_7 = df_cleaned[df_cleaned.zone==7]
#Downsampling zones 6-7
df_6_downsampled = resample(df_6, replace=True, n_samples=5000, random_state=42)
df_7_downsampled = resample(df_7, replace=True, n_samples=5000, random_state=42)
#Concatenating into one downsampled data frame
df_downsampled = pd.concat([df_1_5, df_6_downsampled, df_7_downsampled])
#Checking the resulting counts of observations
df_downsampled.groupby('zone').count()
最後,我們將下采樣數據集保存到一個文件中。此文件可在GitHub找到(https://github.com/mamnunam/Springboard_Data_Science_track/blob/master/Capstone_2/downsampled_data.csv)。
#將文件保存到
df_downsampled.to_csv('downsampled_data.csv')
擬合預測模型
Logistic迴歸
第一個也是最簡單的預測模型是Logistic迴歸。由於它是一個二元分類器,因此我們需要使用one-vs-rest(OVR)方法分別預測每個區域的概率。我們假設每個區域都獨立於另一個區域(即,一個設備的區域不依賴於另一個設備的區域)。我們將使用StandardScaler來標準化這些特徵。
#Splitting the variables into predictor and target variables. We need to drop 'pcid' and 'date' variables,
#as those variables are not relevant for the purpose of prediction.
X = df_downsampled.drop(['zone', 'pcid', 'date'], axis=1)
y = df_downsampled.zone
#Creating a pipeline with the StandardScaler and one-vs-rest logistic regression object
pipeline = make_pipeline(StandardScaler(), LogisticRegression(random_state=42, multi_class='ovr'))
#Calculating an array of cross-validated scores
scores = cross_val_score(pipeline, X, y, cv=10)
#Displaying the mean prediction accuracy for 95% confidence interval
print("Accuracy: %0.2f (+/- %0.2f)" % (scores.mean(), scores.std() * 2))
這給出了0.27(+/- 0.02)的平均準確度。這是一個非常低的結果,比這些模型通常在乾淨和平衡的研究數據集上產生的結果低幾倍。讓我們看看分類報告來評估不同類別的精確度和召回率。為此,我們需要將數據拆分為訓練和測試集。
#Splitting the data into train and test sets
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42, stratify=y)
#Fitting the model
pipeline.fit(X_train, y_train)
#Creating the classification report
print(classification_report(y_test, pipeline.predict(X_test)))
該模型完全錯過了2-5級,並且對於預測類別7的效果最好,但精度和召回率的值仍然很低。由於數據集顯著的初始不平衡,準確性評分或精度/召回等指標可能不是評估模型質量的最佳指標。讓我們看一下Cohen的Kappa分數作為評估預測質量的替代指標:
儘管Kappa分數的大小的解釋各不相同,但從任何角度來看,0.12都非常低,並且表示預測質量很差。因此,Logistic迴歸似乎不是預測PC健康區的好模型。
在嘗試其他預測模型之前,讓我們擬合一個虛擬分類器並與我們的Logistic迴歸模型進行比較:
#Setting up the pipeline
pipeline_dummy = make_pipeline(StandardScaler(), DummyClassifier(random_state=42))
#Calculating an array of cross-validated scores
scores_dummy = cross_val_score(pipeline_dummy, X, y, cv=10)
#Displaying the mean prediction accuracy for 95% confidence interval
print("Accuracy: %0.2f (+/- %0.2f)" % (scores_dummy.mean(), scores_dummy.std() * 2))
這產生了0.15(+/- 0.01)的精度,其表現比虛擬分類器更差。這證實Logistic迴歸模型不適用於該數據集。
隨機森林和梯度提升
接下來,讓我們嘗試隨機森林和梯度提升,因為這些模型通常為分類問題提供良好的預測質量。我將使用一套“經驗法則”參數來為模型選擇最佳的參數。
#Setting up pipelines with a StandardScaler function to normalize the variables
pipelines = {
'rf' : make_pipeline(StandardScaler(),
RandomForestClassifier(random_state=42, class_weight='balanced')),
'gb' : make_pipeline(StandardScaler(),
GradientBoostingClassifier(random_state=42))
}
#Setting up the "rule of thumb" hyperparameters for the Random Forest
rf_hyperparameters = {
'randomforestclassifier__n_estimators': [100, 200],
'randomforestclassifier__max_features': ['auto', 'sqrt', 0.33]
}
#Setting up the "rule of thumb" hyperparameters for the Gradient Boost
gb_hyperparameters = {
'gradientboostingclassifier__n_estimators': [100, 200],
'gradientboostingclassifier__learning_rate': [0.05, 0.1, 0.2],
'gradientboostingclassifier__max_depth': [1, 3, 5]
}
#Creating the dictionary of hyperparameters
hyperparameters = {
'rf' : rf_hyperparameters,
'gb' : gb_hyperparameters
}
#Creating an empty dictionary for fitted models
fitted_alternative_models = {}
# Looping through model pipelines, tuning each with GridSearchCV and saving it to fitted_logreg_models
for name, pipeline in pipelines.items():
#Creating cross-validation object from pipeline and hyperparameters
alt_model = GridSearchCV(pipeline, hyperparameters[name], cv=10, n_jobs=-1)
#Fitting the model on X_train, y_train
alt_model.fit(X_train, y_train)
#Storing the model in fitted_logreg_models[name]
fitted_alternative_models[name] = alt_model
#Printing the status of the fitting
print(name, 'has been fitted.')
#Displaying the best_score_ for each fitted model
for name, model in fitted_alternative_models.items():
print(name, model.best_score_ )
隨機森林模型的得分為0.377969,而對於梯度增強模型,得分為0.341480。測試數據集的得分非常接近訓練數據集的得分,所以模型在兩個數據集上的表現都適中,比虛擬分類器好2倍以上。得分最高的模型參數:
最佳模型的混淆矩陣:
#創建混淆矩陣
pd.crosstab(y_test,fitted_alternative_models ['rf']。predict(X_test),rownames = ['True'],colnames = ['Predicted'],margin = True)
該模型檢測所有區域(與Logistic迴歸模型不同),對區域6-7具有最高的精確度和召回率。最後,我們來看看Kappa評分:
得分明顯好於Logistic迴歸模型,但仍不是很高。現在讓我們嘗試一種更復雜的建模方法。
神經網絡模型
基於神經網絡的模型在機器學習中被廣泛用於分類目的,儘管它們通常需要大量的計算能力。為了比較NN模型的性能和上面測試的模型的性能,我將建立一個簡單的NN模型,利用幾個“經驗法則”方法來最小化所需的計算。
1)隱藏層的數量:關於確定最佳隱藏層數的方法的觀點不同,但它看起來像是一般情況下第二層(或第三層等)隱藏層的性能改善的情況非常多少數。一個隱藏層通常足以解決大多數問題,因此我將在模型中使用一個隱藏層。
2)隱藏層中的神經元數目:有一些經驗性的“經驗法則”來定義這個數字,最常見的方法之一是取數字,這個數字在輸入大小和輸出大小之間層。我將使用10個神經元的圖層。
3)Dropout:為了控制潛在的過度擬合,我將使用Dropout正則化技術,在訓練期間忽略隨機選擇的神經元。我會在輸入層之後和隱藏層之後添加一個Dropout層,使用20%的“經驗法則”概率,這意味著每5個輸入中有1個會隨機從每個更新週期中排除。
4)精度指標:為了將NN與其他模型進行比較,我首先看一下10倍交叉驗證平均的標準精度指標。為了提高計算效率,我會在10個epochs內完成。大多數深度學習論文基於前5個分類準確性度量來報告模型性能,該度量衡量在前k(在這種情況下為5)預測中的正確預測的準確度。我將計算這個度量以作比較。在Keras中使用Kappa分數並不直接,我將在後端使用Kappa分數,所以在這種情況下,我將跳過計算Kappa分數。
考慮到上述情況,讓我們擬合一個簡單的神經網絡模型:
#Setting the seed
np.random.seed(42)
#Separating predictors into a variable
X_upd = df_downsampled.drop(['zone', 'pcid', 'date'], axis=1)
#Standardazing the predictors
scaler = StandardScaler()
predictors = pd.DataFrame(scaler.fit_transform(X_upd)).as_matrix()
#"One hot" encode for zones and converstion to dummy features
target = to_categorical(df_downsampled.zone.astype(int) - 1, num_classes=7)
#Defining input shape
n_cols=predictors.shape[1]
#Defining the model
def nn_model():
model = Sequential()
model.add(Dense(10, activation='relu', input_shape=(n_cols,)))
model.add(Dropout(0.2))
model.add(Dense(10, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(7, activation='softmax'))
#Compiling the model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy'])
return model
estimator = KerasClassifier(build_fn=nn_model, epochs=10, batch_size=10, verbose=0)
kfold = KFold(n_splits=10, shuffle=True, random_state=42)
results = cross_val_score(estimator, predictors, target, cv=kfold)
print("Accuracy score: %.2f%% (%.2f%%)" % (results.mean()*100, results.std()*100))
這給出了0.2725(+/- 0.060)的Accuracy 分數,這比使用隨機森林和梯度增強模型獲得的更差。低分的原因之一可能是數量較少的時代,但使用交叉驗證計算更多的epochs會在PC上花費太多時間。另外,我們的下采樣數據集非常小,因此在更大的數據集上運行模型可以產生更好的結果。最後,在這種情況下,隱含層和神經元數量的“經驗法則”可能不是最好的。讓我們嘗試增加epochs的數量,同時將數據分成訓練和測試集(67%訓練/ 33%測試)。我還將計算前5分類準確性度量。
#Setting the seed
np.random.seed(42)
#Defining the model
model = Sequential()
model.add(Dense(10, activation='relu', input_shape=(n_cols,)))
model.add(Dropout(0.2))
model.add(Dense(10, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(7, activation='softmax'))
import keras.backend as K
def top_k_categorical_accuracy(y_true, y_pred, k=5):
return K.mean(K.in_top_k(y_pred, K.argmax(y_true, axis=-1), k), axis=-1)
#Compiling the model
model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=[top_k_categorical_accuracy, 'accuracy'])
#whether to shuffle the training data before each epoch
fitted_model = model.fit(predictors, target, validation_split=0.33, epochs=50, batch_size=10, shuffle=True, verbose=0)
基於上述模型,我們來看看模型的精度和損失函數如何隨著epochs的數量而變化:
plt.figure(figsize=(20,5))
plt.subplot(1,3,1)
#Plotting accuracy score for train and validation sets
plt.plot(fitted_model.history['top_k_categorical_accuracy'])
plt.plot(fitted_model.history['val_top_k_categorical_accuracy'])
plt.title('Accuracy score dynamic')
plt.ylabel('Accuracy')
plt.ylim(0, 1)
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.subplot(1,3,2)
#Plotting top-5 categorical accuracy for train and validation sets
plt.plot(fitted_model.history['top_k_categorical_accuracy'])
plt.plot(fitted_model.history['val_top_k_categorical_accuracy'])
plt.title('Top-5 categorical accuracy dynamic')
plt.ylabel('Accuracy')
plt.ylim(0, 1)
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.subplot(1,3,3)
#Plotting loss function dynamic for train and validation sets
plt.plot(fitted_model.history['loss'])
plt.plot(fitted_model.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.tight_layout()
plt.show()
圖表顯示訓練集的分數在幾個epochs內幾乎達到100%,而測試集的分數保持非常接近於零,並且隨著epochs的數量僅略有增加。同時,模型損失迅速增加到20個epochs,然後保持在同一水平。其中一個主要原因可能是測試集的體積小,以及整體數據集小。
它看起來並不像在更多時代測試模型是有意義的,但我們可以嘗試用不同的訓練/測試分割來測試它:
#Setting the seed
np.random.seed(42)
#Defining the model
model2 = Sequential()
model2.add(Dense(10, activation='relu', input_shape=(n_cols,)))
model2.add(Dropout(0.2))
model2.add(Dense(10, activation='relu'))
model2.add(Dropout(0.2))
model2.add(Dense(7, activation='softmax'))
import keras.backend as K
def top_k_categorical_accuracy(y_true, y_pred, k=5):
return K.mean(K.in_top_k(y_pred, K.argmax(y_true, axis=-1), k), axis=-1)
#Compiling the model
model2.compile(loss='categorical_crossentropy', optimizer='adam', metrics=[top_k_categorical_accuracy, 'accuracy'])
#whether to shuffle the training data before each epoch
fitted_model2 = model2.fit(predictors, target, validation_split=0.4, epochs=50, batch_size=10, shuffle=True, verbose=0)
plt.figure(figsize=(20,5))
plt.subplot(1,3,1)
#Plotting accuracy score for train and validation sets
plt.plot(fitted_model2.history['top_k_categorical_accuracy'])
plt.plot(fitted_model2.history['val_top_k_categorical_accuracy'])
plt.title('Accuracy score dynamic')
plt.ylabel('Accuracy')
plt.ylim(0, 1)
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.subplot(1,3,2)
#Plotting top-5 categorical accuracy for train and validation sets
plt.plot(fitted_model2.history['top_k_categorical_accuracy'])
plt.plot(fitted_model2.history['val_top_k_categorical_accuracy'])
plt.title('Top-5 categorical accuracy dynamic')
plt.ylabel('Accuracy')
plt.ylim(0, 1)
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.subplot(1,3,3)
#Plotting loss function dynamic for train and validation sets
plt.plot(fitted_model2.history['loss'])
plt.plot(fitted_model2.history['val_loss'])
plt.title('Model loss')
plt.ylabel('Loss')
plt.xlabel('Epoch')
plt.legend(['train', 'test'], loc='upper left')
plt.tight_layout()
plt.show()
測試子集的準確性得分明顯較高,而具有較大測試子集的模型的損失增加的速度稍慢,因此在更大或完整的數據集上檢查模型的性能肯定有意義。
總而言之,使用標準“經驗法則”參數配置的神經網絡模型比隨機森林或梯度增強模型執行得更差,並且用於神經網絡模型的訓練和測試分裂的準確性的差異更加劇烈。儘管如此,一個精細調整的神經網絡模型可能會產生更好的性能,但是這種模型需要使用基於雲計算的並行化計算功能對整個數據集進行訓練,這超出了該項目的範圍。另外,可以使用更細緻的層數微調,神經元和其他參數來獲得更好的結果。
結論
隨機森林模型在精度和Kappa評分方面都表現出了其他模型的最佳性能。這些分數的絕對值很低,因此這個模型很難用來預測PC在任何現實情況下的健康狀況。儘管如此,該模型的性能幾乎是虛擬分類器的2倍,因此可以對其進行微調和改進,以產生更好的結果。此外,如上所述,神經網絡模型的性能不如stellar,通過對模型進行全數據集的訓練和對模型參數的微調,可以獲得可能更好的結果。最後,還有一個額外的機會,雖然計算量很大,但可能是幾個預測模型的組合。
為了允許更多的實驗和更快的結果,以上建議的所有改進都應該利用基於雲的並行計算,因為在單個PC上擬合此類分類模型(尤其是在試圖找到最佳的模型參數和學習率時)可能是一項艱鉅的任務(如果不是幾乎不現實的話)。
一般來說,上述研究項目展示了“開箱即用”和標準化模型在真實數據集上的表現,而且,毫不奇怪,這些模型的準確率比通常在乾淨、準備充分的研究數據集中觀察到的準確率低好幾倍。
閱讀更多 不靠譜的貓 的文章