<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 如何開發人類活動識別的一維卷積神經網絡模型 > 原文: [https://machinelearningmastery.com/cnn-models-for-human-activity-recognition-time-series-classification/](https://machinelearningmastery.com/cnn-models-for-human-activity-recognition-time-series-classification/) 人類活動識別是將由專用線束或智能電話記錄的加速度計數據序列分類為已知的明確定義的運動的問題。 該問題的經典方法涉及基于固定大小的窗口和訓練機器學習模型(例如決策樹的集合)的時間序列數據中的手工制作特征。困難在于此功能工程需要該領域的深厚專業知識。 最近,已經證明,諸如循環神經網絡和一維卷積神經網絡(CNN)之類的深度學習方法可以在很少或沒有數據特征工程的情況下提供具有挑戰性的活動識別任務的最新結果,而不是使用特征學習原始數據。 在本教程中,您將了解如何開發一維卷積神經網絡,用于人類活動識別問題的時間序列分類。 完成本教程后,您將了解: * 如何為標準人類活動識別數據集加載和準備數據,并開發單個 1D CNN 模型,以在原始數據上實現出色的表現。 * 如何進一步調整模型的表現,包括數據轉換,過濾器映射和內核大小。 * 如何開發一種復雜的多頭一維卷積神經網絡模型,提供類似集合的結果。 讓我們開始吧。 ![How to Develop 1D Convolutional Neural Network Models for Human Activity Recognition](https://img.kancloud.cn/34/54/3454208d5464c387ab484839f46967f8_640x425.jpg) 如何開發用于人類活動識別的一維卷積神經網絡模型 照片由 [Wolfgang Staudt](https://www.flickr.com/photos/wolfgangstaudt/2204054918/) ,保留一些權利。 ## 教程概述 本教程分為四個部分;他們是: 1. 使用智能手機數據集進行活動識別 2. 開發一維卷積神經網絡 3. 調諧一維卷積神經網絡 4. 多頭一維卷積神經網絡 ## 使用智能手機數據集進行活動識別 [人類活動識別](https://en.wikipedia.org/wiki/Activity_recognition),或簡稱為 HAR,是基于使用傳感器的移動痕跡來預測人正在做什么的問題。 標準的人類活動識別數據集是 2012 年推出的“使用智能手機數據集的活動識別”。 它由 Davide Anguita 等人準備并提供。來自意大利熱那亞大學的 2013 年論文“[使用智能手機進行人類活動識別的公共領域數據集](https://upcommons.upc.edu/handle/2117/20897)”中對該數據集進行了全面描述。該數據集在他們的 2012 年論文中用機器學習算法建模,標題為“[使用多類硬件友好支持向量機](https://link.springer.com/chapter/10.1007/978-3-642-35395-6_30)在智能手機上進行人類活動識別。“ 數據集可用,可以從 UCI 機器學習庫免費下載: * [使用智能手機數據集進行人類活動識別,UCI 機器學習庫](https://archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones) 該數據來自 30 名年齡在 19 至 48 歲之間的受試者,其執行六項標準活動中的一項,同時佩戴記錄運動數據的腰部智能手機。記錄執行活動的每個受試者的視頻,并從這些視頻手動標記移動數據。 以下是在記錄其移動數據的同時執行活動的主體的示例視頻。 &lt;iframe allow="autoplay; encrypted-media" allowfullscreen="" frameborder="0" height="375" src="https://www.youtube.com/embed/XOEN9W05_4A?feature=oembed" width="500"&gt;&lt;/iframe&gt; 進行的六項活動如下: 1. 步行 2. 走上樓 3. 走樓下 4. 坐在 5. 常設 6. 鋪設 記錄的運動數據是來自智能手機的 x,y 和 z 加速度計數據(線性加速度)和陀螺儀數據(角速度),特別是三星 Galaxy S II。以 50Hz(即每秒 50 個數據點)記錄觀察結果。每個受試者進行兩次活動,一次是左側設備,另一次是右側設備。 原始數據不可用。相反,可以使用預處理版本的數據集。預處理步驟包括: * 使用噪聲濾波器預處理加速度計和陀螺儀。 * 將數據拆分為 2.56 秒(128 個數據點)的固定窗口,重疊率為 50%。 * 將加速度計數據分割為重力(總)和身體運動分量。 特征工程應用于窗口數據,并且提供具有這些工程特征的數據的副本。 從每個窗口提取在人類活動識別領域中常用的許多時間和頻率特征。結果是 561 元素的特征向量。 根據受試者的數據,將數據集分成訓練(70%)和測試(30%)組。訓練 21 個,測試 9 個。 使用旨在用于智能手機的支持向量機(例如定點算術)的實驗結果導致測試數據集的預測準確度為 89%,實現與未修改的 SVM 實現類似的結果。 該數據集是免費提供的,可以從 UCI 機器學習庫下載。 數據以單個 zip 文件的形式提供,大小約為 58 兆字節。此下載的直接鏈接如下: * [UCI HAR Dataset.zip](https://archive.ics.uci.edu/ml/machine-learning-databases/00240/UCI%20HAR%20Dataset.zip) 下載數據集并將所有文件解壓縮到當前工作目錄中名為“HARDataset”的新目錄中。 ## 開發一維卷積神經網絡 在本節中,我們將為人類活動識別數據集開發一維卷積神經網絡模型(1D CNN)。 [卷積神經網絡](https://machinelearningmastery.com/crash-course-convolutional-neural-networks/)模型是為圖像分類問題而開發的,其中模型在稱為特征學習的過程中學習二維輸入的內部表示。 可以在一維數據序列上利用相同的過程,例如在用于人類活動識別的加速和陀螺儀數據的情況下。該模型學習從觀察序列中提取特征以及如何將內部特征映射到不同的活動類型。 使用 CNN 進行序列分類的好處是,他們可以直接從原始時間序列數據中學習,而不需要領域專業知識來手動設計輸入功能。該模型可以學習時間序列數據的內部表示,并且理想地實現與適合具有工程特征的數據集版本的模型相當的表現。 本節分為 4 部分;他們是: 1. 加載數據 2. 擬合和評估模型 3. 總結結果 4. 完整的例子 ### 加載數據 第一步是將原始數據集加載到內存中。 原始數據中有三種主要信號類型:總加速度,車身加速度和車身陀螺儀。每個都有三個數據軸。這意味著每個時間步長總共有九個變量。 此外,每個數據系列已被劃分為 2.65 秒數據的重疊窗口,或 128 個時間步長。這些數據窗口對應于上一節中工程特征(行)的窗口。 這意味著一行數據具有(128 * 9)或 1,152 個元素。這比前一節中 561 個元素向量的大小小一倍,并且可能存在一些冗余數據。 信號存儲在 train 和 test 子目錄下的/ _Inertial Signals_ /目錄中。每個信號的每個軸都存儲在一個單獨的文件中,這意味著每個訓練和測試數據集都有九個要加載的輸入文件和一個要加載的輸出文件。在給定一致的目錄結構和文件命名約定的情況下,我們可以批量加載這些文件。 輸入數據采用 CSV 格式,其中列由空格分隔。這些文件中的每一個都可以作為 NumPy 數組加載。下面的 _load_file()_ 函數在給定文件的文件路徑的情況下加載數據集,并將加載的數據作為 NumPy 數組返回。 ```py # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values ``` 然后,我們可以將給定組(訓練或測試)的所有數據加載到單個三維 NumPy 陣列中,其中陣列的尺寸為[_ 樣本,時間步長,特征 _]。 為了更清楚,有 128 個時間步和 9 個特征,其中樣本數是任何給定原始信號數據文件中的行數。 下面的 _load_group()_ 函數實現了這種行為。 [dstack()NumPy 函數](https://docs.scipy.org/doc/numpy-1.14.0/reference/generated/numpy.dstack.html)允許我們將每個加載的 3D 數組堆疊成單個 3D 數組,其中變量在第三維(特征)上分開。 ```py # load a list of files into a 3D array of [samples, timesteps, features] def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded ``` 我們可以使用此功能加載給定組的所有輸入信號數據,例如訓練或測試。 下面的 _load_dataset_group()_ 函數使用訓練和測試目錄之間的一致命名約定加載單個組的所有輸入信號數據和輸出數據。 ```py # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y ``` 最后,我們可以加載每個訓練和測試數據集。 輸出數據定義為類號的整數。我們必須對這些類整數進行熱編碼,以使數據適合于擬合神經網絡多類分類模型。我們可以通過調用 [to_categorical()Keras 函數](https://keras.io/utils/#to_categorical)來實現。 下面的 _load_dataset()_ 函數實現了這種行為,并返回訓練并測試 _X_ 和 _y_ 元素,以便擬合和評估定義的模型。 ```py # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy ``` ### 擬合和評估模型 現在我們已將數據加載到內存中以便進行建模,我們可以定義,擬合和評估 1D CNN 模型。 我們可以定義一個名為 _evaluate_model()_ 的函數,它接受訓練和測試數據集,擬合訓練數據集上的模型,在測試數據集上對其進行評估,并返回模型表現的估計值。 首先,我們必須使用 Keras 深度學習庫來定義 CNN 模型。該模型需要使用[_ 樣本,時間步長,特征 _]進行三維輸入。 這正是我們加載數據的方式,其中一個樣本是時間序列數據的一個窗口,每個窗口有 128 個時間步長,時間步長有九個變量或特征。 模型的輸出將是一個六元素向量,包含屬于六種活動類型中每種活動類型的給定窗口的概率。 在擬合模型時需要這些輸入和輸出維度,我們可以從提供的訓練數據集中提取它們。 ```py n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] ``` 為簡單起見,該模型被定義為順序 Keras 模型。 我們將模型定義為具有兩個 1D CNN 層,然后是用于正則化的丟失層,然后是池化層。通常以兩個為一組定義 CNN 層,以便為模型提供從輸入數據學習特征的良好機會。 CNN 非常快速地學習,因此 dropout 層旨在幫助減緩學習過程,并希望能夠產生更好的最終模型。池化層將學習的特征減少到其大小的 1/4,將它們合并到最基本的元素。 在 CNN 和匯集之后,將學習的特征展平為一個長向量,并在用于進行預測的輸出層之前通過完全連接的層。完全連接的層理想地在學習的特征和輸出之間提供緩沖,目的是在進行預測之前解釋學習的特征。 對于此模型,我們將使用 64 個并行要素圖的標準配置和 3 的內核大小。要素圖是處理或解釋輸入的次數,而內核大小是被視為輸入時間步數的數量。輸入序列被讀取或處理到特征映射上。 隨機梯度下降的有效 [Adam](https://machinelearningmastery.com/adam-optimization-algorithm-for-deep-learning/) 版本將用于優化網絡,并且鑒于我們正在學習多類別分類問題,將使用分類交叉熵損失函數。 下面列出了該模型的定義。 ```py model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=64, kernel_size=3, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) ``` 該模型適用于固定數量的時期,在這種情況下為 10,并且將使用 32 個樣本的批量大小,其中在更新模型的權重之前將 32 個數據窗口暴露給模型。 模型擬合后,將在測試數據集上進行評估,并返回測試數據集上擬合模型的精度。 下面列出了完整的 _evaluate_model()_ 函數。 ```py # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=64, kernel_size=3, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit(trainX, trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate(testX, testy, batch_size=batch_size, verbose=0) return accuracy ``` 網絡結構或選擇的超參數沒有什么特別之處;它們只是這個問題的起點。 ### 總結結果 我們無法從單一評估中判斷模型的技能。 其原因是神經網絡是隨機的,這意味著當在相同數據上訓練相同的模型配置時將產生不同的特定模型。 這是網絡的一個特征,它為模型提供了自適應能力,但需要對模型進行稍微復雜的評估。 我們將多次重復對模型的評估,然后在每次運行中總結模型的表現。例如,我們可以調用 _evaluate_model()_ 共 10 次。這將導致必須總結的模型評估分數。 ```py # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy) score = score * 100.0 print('>#%d: %.3f' % (r+1, score)) scores.append(score) ``` 我們可以通過計算和報告績效的均值和標準差來總結得分樣本。均值給出了數據集上模型的平均精度,而標準差給出了精度與平均值的平均方差。 下面的函數 _summarize_results()_ 總結了運行的結果。 ```py # summarize scores def summarize_results(scores): print(scores) m, s = mean(scores), std(scores) print('Accuracy: %.3f%% (+/-%.3f)' % (m, s)) ``` 我們可以將重復評估,結果收集和結果匯總捆綁到實驗的主要功能中,稱為 _run_experiment()_,如下所示。 默認情況下,在報告模型表現之前,會對模型進行 10 次評估。 ```py # run an experiment def run_experiment(repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy) score = score * 100.0 print('>#%d: %.3f' % (r+1, score)) scores.append(score) # summarize results summarize_results(scores) ``` ### 完整的例子 現在我們已經擁有了所有的部分,我們可以將它們組合成一個有效的例子。 完整的代碼清單如下。 ```py # cnn model from numpy import mean from numpy import std from numpy import dstack from pandas import read_csv from matplotlib import pyplot from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers import Dropout from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.utils import to_categorical # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values # load a list of files and return as a 3d numpy array def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=64, kernel_size=3, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit(trainX, trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate(testX, testy, batch_size=batch_size, verbose=0) return accuracy # summarize scores def summarize_results(scores): print(scores) m, s = mean(scores), std(scores) print('Accuracy: %.3f%% (+/-%.3f)' % (m, s)) # run an experiment def run_experiment(repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy) score = score * 100.0 print('>#%d: %.3f' % (r+1, score)) scores.append(score) # summarize results summarize_results(scores) # run the experiment run_experiment() ``` 運行該示例首先打印已加載數據集的形狀,然后打印訓練和測試集的形狀以及輸入和輸出元素。這確認了樣本數,時間步長和變量,以及類的數量。 接下來,創建和評估模型,并為每個模型打印調試消息。 最后,打印分數樣本,然后是平均值和標準差。我們可以看到該模型表現良好,實現了在原始數據集上訓練的約 90.9%的分類準確度,標準偏差約為 1.3。 這是一個很好的結果,考慮到原始論文發表了 89%的結果,在具有重域特定特征工程的數據集上進行了訓練,而不是原始數據集。 注意:鑒于算法的隨機性,您的具體結果可能會有所不同。 ```py (7352, 128, 9) (7352, 1) (2947, 128, 9) (2947, 1) (7352, 128, 9) (7352, 6) (2947, 128, 9) (2947, 6) >#1: 91.347 >#2: 91.551 >#3: 90.804 >#4: 90.058 >#5: 89.752 >#6: 90.940 >#7: 91.347 >#8: 87.547 >#9: 92.637 >#10: 91.890 [91.34713267729894, 91.55072955548015, 90.80420766881574, 90.05768578215134, 89.75229046487954, 90.93993892093654, 91.34713267729894, 87.54665761791652, 92.63657957244655, 91.89005768578215] Accuracy: 90.787% (+/-1.341) ``` 現在我們已經看到了如何加載數據并適合 1D CNN 模型,我們可以研究是否可以通過一些超參數調整來進一步提升模型的技能。 ## 調諧一維卷積神經網絡 在本節中,我們將調整模型,以進一步提高問題的表現。 我們將看三個主要方面: 1. 數據準備 2. 過濾器數量 3. 內核的大小 ### 數據準備 在上一節中,我們沒有執行任何數據準備。我們按原樣使用了數據。 每個主要數據集(身體加速度,身體陀螺儀和總加速度)已經縮放到-1,1 的范圍。不清楚數據是按受試者縮放還是跨所有受試者。 可能導致改進的一種可能的變換是在擬合模型之前標準化觀察。 標準化是指改變每個變量的分布,使其平均值為零,標準差為 1.只有每個變量的分布是高斯分布才真正有意義。 我們可以通過繪制訓練數據集中每個變量的直方圖來快速檢查每個變量的分布。 這方面的一個小難點是數據被分成 128 個時間步長的窗口,重疊 50%。因此,為了更好地了解數據分布,我們必須首先刪除重復的觀察(重疊),然后刪除數據的窗口。 我們可以使用 NumPy 來做到這一點,首先切割數組并僅保留每個窗口的后半部分,然后將窗口展平為每個變量的長向量。這很快且很臟,并且意味著我們在第一個窗口的前半部分丟失了數據。 ```py # remove overlap cut = int(trainX.shape[1] / 2) longX = trainX[:, -cut:, :] # flatten windows longX = longX.reshape((longX.shape[0] * longX.shape[1], longX.shape[2])) ``` 下面列出了加載數據,展平數據以及為九個變量中的每一個繪制直方圖的完整示例。 ```py # plot distributions from numpy import dstack from pandas import read_csv from keras.utils import to_categorical from matplotlib import pyplot # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values # load a list of files and return as a 3d numpy array def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy # plot a histogram of each variable in the dataset def plot_variable_distributions(trainX): # remove overlap cut = int(trainX.shape[1] / 2) longX = trainX[:, -cut:, :] # flatten windows longX = longX.reshape((longX.shape[0] * longX.shape[1], longX.shape[2])) print(longX.shape) pyplot.figure() xaxis = None for i in range(longX.shape[1]): ax = pyplot.subplot(longX.shape[1], 1, i+1, sharex=xaxis) ax.set_xlim(-1, 1) if i == 0: xaxis = ax pyplot.hist(longX[:, i], bins=100) pyplot.show() # load data trainX, trainy, testX, testy = load_dataset() # plot histograms plot_variable_distributions(trainX) ``` 運行該示例將創建一個包含九個直方圖的圖形,一個用于訓練數據集中的每個變量。 圖的順序與加載數據的順序相匹配,具體如下: 1. 總加速度 x 2. 總加速度 y 3. 總加速度 z 4. 身體加速 x 5. 身體加速度 y 6. 身體加速度 z 7. 身體陀螺儀 x 8. 身體陀螺儀 y 9. Body Gyroscope z 我們可以看到每個變量都具有類似高斯分布,除了第一個變量(總加速度 x)。 總加速度數據的分布比身體數據更平坦,這更加尖銳。 我們可以探索使用數據的冪變換來使分布更加高斯,盡管這是一個練習。 ![Histograms of each variable in the training data set](https://img.kancloud.cn/07/81/0781000d3475916edb5223fe92a30ee0_1280x960.jpg) 訓練數據集中每個變量的直方圖 數據具有足夠的高斯類似性,以探索標準化變換是否有助于模型從原始觀測中提取顯著信號。 名為 _scale_data()_ 的以下函數可用于在擬合和評估模型之前標準化數據。 StandardScaler scikit-learn 類將用于執行轉換。它首先適合訓練數據(例如,找到每個變量的平均值和標準差),然后應用于訓練和測試集。 標準化是可選的,因此我們可以應用該過程并將結果與??相同的代碼路徑進行比較,而無需在受控實驗中進行標準化。 ```py # standardize data def scale_data(trainX, testX, standardize): # remove overlap cut = int(trainX.shape[1] / 2) longX = trainX[:, -cut:, :] # flatten windows longX = longX.reshape((longX.shape[0] * longX.shape[1], longX.shape[2])) # flatten train and test flatTrainX = trainX.reshape((trainX.shape[0] * trainX.shape[1], trainX.shape[2])) flatTestX = testX.reshape((testX.shape[0] * testX.shape[1], testX.shape[2])) # standardize if standardize: s = StandardScaler() # fit on training data s.fit(longX) # apply to training and test data longX = s.transform(longX) flatTrainX = s.transform(flatTrainX) flatTestX = s.transform(flatTestX) # reshape flatTrainX = flatTrainX.reshape((trainX.shape)) flatTestX = flatTestX.reshape((testX.shape)) return flatTrainX, flatTestX ``` 我們可以更新 _evaluate_model()_ 函數來獲取參數,然后使用此參數來決定是否執行標準化。 ```py # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy, param): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] # scale data trainX, testX = scale_data(trainX, testX, param) model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=64, kernel_size=3, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit(trainX, trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate(testX, testy, batch_size=batch_size, verbose=0) return accuracy ``` 我們還可以更新 _run_experiment()_,為每個參數重復實驗 10 次;在這種情況下,只有兩個參數將被評估[ _False,True_ ],分別沒有標準化和標準化。 ```py # run an experiment def run_experiment(params, repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # test each parameter all_scores = list() for p in params: # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy, p) score = score * 100.0 print('>p=%d #%d: %.3f' % (p, r+1, score)) scores.append(score) all_scores.append(scores) # summarize results summarize_results(all_scores, params) ``` 這將產生兩個可以比較的結果樣本。 我們將更新 _summarize_results()_ 函數,以匯總每個配置參數的結果樣本,并創建一個箱形圖來比較每個結果樣本。 ```py # summarize scores def summarize_results(scores, params): print(scores, params) # summarize mean and standard deviation for i in range(len(scores)): m, s = mean(scores[i]), std(scores[i]) print('Param=%d: %.3f%% (+/-%.3f)' % (params[i], m, s)) # boxplot of scores pyplot.boxplot(scores, labels=params) pyplot.savefig('exp_cnn_standardize.png') ``` 這些更新將允許我們直接比較之前模型擬合的結果和數據集標準化后的模型擬合。 它也是一個通用的更改,允許我們在以下部分中評估和比較其他參數集的結果。 完整的代碼清單如下。 ```py # cnn model with standardization from numpy import mean from numpy import std from numpy import dstack from pandas import read_csv from matplotlib import pyplot from sklearn.preprocessing import StandardScaler from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers import Dropout from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.utils import to_categorical # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values # load a list of files and return as a 3d numpy array def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy # standardize data def scale_data(trainX, testX, standardize): # remove overlap cut = int(trainX.shape[1] / 2) longX = trainX[:, -cut:, :] # flatten windows longX = longX.reshape((longX.shape[0] * longX.shape[1], longX.shape[2])) # flatten train and test flatTrainX = trainX.reshape((trainX.shape[0] * trainX.shape[1], trainX.shape[2])) flatTestX = testX.reshape((testX.shape[0] * testX.shape[1], testX.shape[2])) # standardize if standardize: s = StandardScaler() # fit on training data s.fit(longX) # apply to training and test data longX = s.transform(longX) flatTrainX = s.transform(flatTrainX) flatTestX = s.transform(flatTestX) # reshape flatTrainX = flatTrainX.reshape((trainX.shape)) flatTestX = flatTestX.reshape((testX.shape)) return flatTrainX, flatTestX # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy, param): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] # scale data trainX, testX = scale_data(trainX, testX, param) model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=64, kernel_size=3, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit(trainX, trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate(testX, testy, batch_size=batch_size, verbose=0) return accuracy # summarize scores def summarize_results(scores, params): print(scores, params) # summarize mean and standard deviation for i in range(len(scores)): m, s = mean(scores[i]), std(scores[i]) print('Param=%s: %.3f%% (+/-%.3f)' % (params[i], m, s)) # boxplot of scores pyplot.boxplot(scores, labels=params) pyplot.savefig('exp_cnn_standardize.png') # run an experiment def run_experiment(params, repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # test each parameter all_scores = list() for p in params: # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy, p) score = score * 100.0 print('>p=%s #%d: %.3f' % (p, r+1, score)) scores.append(score) all_scores.append(scores) # summarize results summarize_results(all_scores, params) # run the experiment n_params = [False, True] run_experiment(n_params) ``` 運行該示例可能需要幾分鐘,具體取決于您的硬件。 為每個評估的模型打印表現。在運行結束時,總結了每個測試配置的表現,顯示了平均值和標準偏差。 我們可以看到,在建模之前看起來確實標準化數據集確實導致表現的小提升,從大約 90.4%的準確度(接近我們在上一節中看到的)到大約 91.5%的準確度。 注意:鑒于算法的隨機性,您的具體結果可能會有所不同。 ```py (7352, 128, 9) (7352, 1) (2947, 128, 9) (2947, 1) (7352, 128, 9) (7352, 6) (2947, 128, 9) (2947, 6) >p=False #1: 91.483 >p=False #2: 91.245 >p=False #3: 90.838 >p=False #4: 89.243 >p=False #5: 90.193 >p=False #6: 90.465 >p=False #7: 90.397 >p=False #8: 90.567 >p=False #9: 88.938 >p=False #10: 91.144 >p=True #1: 92.908 >p=True #2: 90.940 >p=True #3: 92.297 >p=True #4: 91.822 >p=True #5: 92.094 >p=True #6: 91.313 >p=True #7: 91.653 >p=True #8: 89.141 >p=True #9: 91.110 >p=True #10: 91.890 [[91.48286392941975, 91.24533423820834, 90.83814048184594, 89.24329826942655, 90.19341703427214, 90.46487953851374, 90.39701391245333, 90.56667797760434, 88.93790295215473, 91.14353579911774], [92.90804207668816, 90.93993892093654, 92.29725144214456, 91.82219205972176, 92.09365456396336, 91.31319986426874, 91.65252799457076, 89.14149983033593, 91.10960298608755, 91.89005768578215]] [False, True] Param=False: 90.451% (+/-0.785) Param=True: 91.517% (+/-0.965) ``` 還創建了結果的框和胡須圖。 這允許以非參數方式比較兩個結果樣本,顯示每個樣本的中值和中間 50%。 我們可以看到,標準化的結果分布與沒有標準化的結果分布完全不同。這可能是一個真正的效果。 ![Box and whisker plot of 1D CNN with and without standardization](https://img.kancloud.cn/e5/34/e5349a567bd506526cf44f7f51449beb_640x480.jpg) 有和沒有標準化的 1D CNN 的盒子和須狀圖 ### 過濾器數量 現在我們有了一個實驗框架,我們可以探索不同的模型的其他超參數。 CNN 的一個重要超參數是濾波器映射的數量。我們可以嘗試一系列不同的值,從比我們開發的第一個模型中使用的 64 個更少到更多。 具體來說,我們將嘗試以下數量的功能圖: ```py n_params = [8, 16, 32, 64, 128, 256] ``` 我們可以使用上一節中的相同代碼并更新 _evaluate_model()_ 函數,以使用提供的參數作為 Conv1D 層中的過濾器數量。我們還可以更新 _summarize_results()_ 函數,將箱圖保存為 _exp_cnn_filters.png_ 。 完整的代碼示例如下所示。 ```py # cnn model with filters from numpy import mean from numpy import std from numpy import dstack from pandas import read_csv from matplotlib import pyplot from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers import Dropout from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.utils import to_categorical # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values # load a list of files and return as a 3d numpy array def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy, n_filters): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] model = Sequential() model.add(Conv1D(filters=n_filters, kernel_size=3, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=n_filters, kernel_size=3, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit(trainX, trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate(testX, testy, batch_size=batch_size, verbose=0) return accuracy # summarize scores def summarize_results(scores, params): print(scores, params) # summarize mean and standard deviation for i in range(len(scores)): m, s = mean(scores[i]), std(scores[i]) print('Param=%d: %.3f%% (+/-%.3f)' % (params[i], m, s)) # boxplot of scores pyplot.boxplot(scores, labels=params) pyplot.savefig('exp_cnn_filters.png') # run an experiment def run_experiment(params, repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # test each parameter all_scores = list() for p in params: # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy, p) score = score * 100.0 print('>p=%d #%d: %.3f' % (p, r+1, score)) scores.append(score) all_scores.append(scores) # summarize results summarize_results(all_scores, params) # run the experiment n_params = [8, 16, 32, 64, 128, 256] run_experiment(n_params) ``` 運行該示例將為每個指定數量的過濾器重復實驗。 在運行結束時,將顯示每個過濾器數量的結果摘要。 隨著濾波器圖數量的增加,我們可以看到平均表現提升的趨勢。方差保持不變,可能 128 個特征映射可能是網絡的良好配置。 ```py ... Param=8: 89.148% (+/-0.790) Param=16: 90.383% (+/-0.613) Param=32: 90.356% (+/-1.039) Param=64: 90.098% (+/-0.615) Param=128: 91.032% (+/-0.702) Param=256: 90.706% (+/-0.997) ``` 還創建了結果的框和胡須圖,允許比較每個過濾器數量的結果。 從圖中可以看出,隨著特征圖數量的增加,中值分類精度(框中的橙色線)的趨勢向上。我們確實看到了 64 個特征圖(我們的實驗中的默認值或基線)的下降,這是令人驚訝的,并且可能在 32,128 和 256 個過濾器圖中具有穩定性的平臺。也許 32 將是一個更穩定的配置。 ![Box and whisker plot of 1D CNN with different numbers of filter maps](https://img.kancloud.cn/3d/5f/3d5fd3f9cb67fe2d52eb139c4f0b2aea_640x480.jpg) 具有不同數量的濾波器映射的 1D CNN 的盒子和須狀圖 ### 內核的大小 內核的大小是 1D CNN 調整的另一個重要的超參數。 內核大小控制輸入序列的每個“_ 讀取 _”中考慮的時間步數,然后將其投影到特征圖上(通過卷積過程)。 較大的內核大小意味著不太嚴格的數據讀取,但可能會導致輸入的更通用的快照。 除了默認的三個時間步長之外,我們可以使用相同的實驗設置并測試一套不同的內核大小。完整的值列表如下: ```py n_params = [2, 3, 5, 7, 11] ``` 完整的代碼清單如下: ```py # cnn model vary kernel size from numpy import mean from numpy import std from numpy import dstack from pandas import read_csv from matplotlib import pyplot from keras.models import Sequential from keras.layers import Dense from keras.layers import Flatten from keras.layers import Dropout from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.utils import to_categorical # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values # load a list of files and return as a 3d numpy array def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy, n_kernel): verbose, epochs, batch_size = 0, 15, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] model = Sequential() model.add(Conv1D(filters=64, kernel_size=n_kernel, activation='relu', input_shape=(n_timesteps,n_features))) model.add(Conv1D(filters=64, kernel_size=n_kernel, activation='relu')) model.add(Dropout(0.5)) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dense(n_outputs, activation='softmax')) model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit(trainX, trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate(testX, testy, batch_size=batch_size, verbose=0) return accuracy # summarize scores def summarize_results(scores, params): print(scores, params) # summarize mean and standard deviation for i in range(len(scores)): m, s = mean(scores[i]), std(scores[i]) print('Param=%d: %.3f%% (+/-%.3f)' % (params[i], m, s)) # boxplot of scores pyplot.boxplot(scores, labels=params) pyplot.savefig('exp_cnn_kernel.png') # run an experiment def run_experiment(params, repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # test each parameter all_scores = list() for p in params: # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy, p) score = score * 100.0 print('>p=%d #%d: %.3f' % (p, r+1, score)) scores.append(score) all_scores.append(scores) # summarize results summarize_results(all_scores, params) # run the experiment n_params = [2, 3, 5, 7, 11] run_experiment(n_params) ``` 運行該示例依次測試每個內核大小。 結果總結在運行結束時。隨著內核大小的增加,我們可以看到模型表現的普遍提高。 結果表明,籽粒大小為 5 可能是好的,平均技能為約 91.8%,但也許大小為 7 或 11 也可能同樣好,標準偏差較小。 ```py ... Param=2: 90.176% (+/-0.724) Param=3: 90.275% (+/-1.277) Param=5: 91.853% (+/-1.249) Param=7: 91.347% (+/-0.852) Param=11: 91.456% (+/-0.743) ``` 還創建了結果的框和胡須圖。 結果表明,較大的內核大小確實會產生更好的準確性,并且內核大小 7 可能在良好表現和低方差之間提供了良好的平衡。 ![Box and whisker plot of 1D CNN with different numbers of kernel sizes](https://img.kancloud.cn/f3/bf/f3bfce34c43e5669b36386890c6cb14e_640x480.jpg) 具有不同內核大小的 1D CNN 的盒子和須狀圖 這只是調整模型的開始,盡管我們關注的可能是更重要的元素。探索上述某些發現的組合可能會很有趣,看看表現是否可以進一步提升。 將重復次數從 10 增加到 30 或更多以確定它是否會導致更穩定的結果也可能是有趣的。 ## 多頭卷積神經網絡 CNN 的另一種流行方法是使用多頭模型,其中模型的每個頭使用不同大小的內核讀取輸入時間步長。 例如,三頭模型可以具有三種不同的內核大小 3,5,11,允許模型以三種不同的分辨率讀取和解釋序列數據。然后,在進行預測之前,來自所有三個頭的解釋在模型內連接并由完全連接的層解釋。 我們可以使用 Keras 功能 API 實現多頭 1D CNN。有關此 API 的溫和介紹,請參閱帖子: * [如何使用 Keras 功能 API 進行深度學習](https://machinelearningmastery.com/keras-functional-api-deep-learning/) 下面列出了 _evaluate_model()_ 函數的更新版本,它創建了一個三頭 CNN 模型。 我們可以看到模型的每個頭部都是相同的結構,盡管內核大小是變化的。然后,在進行預測之前,三個頭在被解釋之前進入單個合并層。 ```py # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] # head 1 inputs1 = Input(shape=(n_timesteps,n_features)) conv1 = Conv1D(filters=64, kernel_size=3, activation='relu')(inputs1) drop1 = Dropout(0.5)(conv1) pool1 = MaxPooling1D(pool_size=2)(drop1) flat1 = Flatten()(pool1) # head 2 inputs2 = Input(shape=(n_timesteps,n_features)) conv2 = Conv1D(filters=64, kernel_size=5, activation='relu')(inputs2) drop2 = Dropout(0.5)(conv2) pool2 = MaxPooling1D(pool_size=2)(drop2) flat2 = Flatten()(pool2) # head 3 inputs3 = Input(shape=(n_timesteps,n_features)) conv3 = Conv1D(filters=64, kernel_size=11, activation='relu')(inputs3) drop3 = Dropout(0.5)(conv3) pool3 = MaxPooling1D(pool_size=2)(drop3) flat3 = Flatten()(pool3) # merge merged = concatenate([flat1, flat2, flat3]) # interpretation dense1 = Dense(100, activation='relu')(merged) outputs = Dense(n_outputs, activation='softmax')(dense1) model = Model(inputs=[inputs1, inputs2, inputs3], outputs=outputs) # save a plot of the model plot_model(model, show_shapes=True, to_file='multichannel.png') model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit([trainX,trainX,trainX], trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate([testX,testX,testX], testy, batch_size=batch_size, verbose=0) return accuracy ``` 創建模型時,會創建網絡體系結構圖;如下所示,它清楚地說明了構建的模型如何組合在一起。 ![Plot of the Multi-Headed 1D Convolutional Neural Network](https://img.kancloud.cn/8d/2e/8d2e55e876cecfb9bde44103f13e5322_1247x848.jpg) 多頭一維卷積神經網絡的圖 模型的其他方面可以在各個方面變化,例如過濾器的數量或甚至數據本身的準備。 下面列出了多頭 1D CNN 的完整代碼示例。 ```py # multi-headed cnn model from numpy import mean from numpy import std from numpy import dstack from pandas import read_csv from matplotlib import pyplot from keras.utils import to_categorical from keras.utils.vis_utils import plot_model from keras.models import Model from keras.layers import Input from keras.layers import Dense from keras.layers import Flatten from keras.layers import Dropout from keras.layers.convolutional import Conv1D from keras.layers.convolutional import MaxPooling1D from keras.layers.merge import concatenate # load a single file as a numpy array def load_file(filepath): dataframe = read_csv(filepath, header=None, delim_whitespace=True) return dataframe.values # load a list of files and return as a 3d numpy array def load_group(filenames, prefix=''): loaded = list() for name in filenames: data = load_file(prefix + name) loaded.append(data) # stack group so that features are the 3rd dimension loaded = dstack(loaded) return loaded # load a dataset group, such as train or test def load_dataset_group(group, prefix=''): filepath = prefix + group + '/Inertial Signals/' # load all 9 files as a single array filenames = list() # total acceleration filenames += ['total_acc_x_'+group+'.txt', 'total_acc_y_'+group+'.txt', 'total_acc_z_'+group+'.txt'] # body acceleration filenames += ['body_acc_x_'+group+'.txt', 'body_acc_y_'+group+'.txt', 'body_acc_z_'+group+'.txt'] # body gyroscope filenames += ['body_gyro_x_'+group+'.txt', 'body_gyro_y_'+group+'.txt', 'body_gyro_z_'+group+'.txt'] # load input data X = load_group(filenames, filepath) # load class output y = load_file(prefix + group + '/y_'+group+'.txt') return X, y # load the dataset, returns train and test X and y elements def load_dataset(prefix=''): # load all train trainX, trainy = load_dataset_group('train', prefix + 'HARDataset/') print(trainX.shape, trainy.shape) # load all test testX, testy = load_dataset_group('test', prefix + 'HARDataset/') print(testX.shape, testy.shape) # zero-offset class values trainy = trainy - 1 testy = testy - 1 # one hot encode y trainy = to_categorical(trainy) testy = to_categorical(testy) print(trainX.shape, trainy.shape, testX.shape, testy.shape) return trainX, trainy, testX, testy # fit and evaluate a model def evaluate_model(trainX, trainy, testX, testy): verbose, epochs, batch_size = 0, 10, 32 n_timesteps, n_features, n_outputs = trainX.shape[1], trainX.shape[2], trainy.shape[1] # head 1 inputs1 = Input(shape=(n_timesteps,n_features)) conv1 = Conv1D(filters=64, kernel_size=3, activation='relu')(inputs1) drop1 = Dropout(0.5)(conv1) pool1 = MaxPooling1D(pool_size=2)(drop1) flat1 = Flatten()(pool1) # head 2 inputs2 = Input(shape=(n_timesteps,n_features)) conv2 = Conv1D(filters=64, kernel_size=5, activation='relu')(inputs2) drop2 = Dropout(0.5)(conv2) pool2 = MaxPooling1D(pool_size=2)(drop2) flat2 = Flatten()(pool2) # head 3 inputs3 = Input(shape=(n_timesteps,n_features)) conv3 = Conv1D(filters=64, kernel_size=11, activation='relu')(inputs3) drop3 = Dropout(0.5)(conv3) pool3 = MaxPooling1D(pool_size=2)(drop3) flat3 = Flatten()(pool3) # merge merged = concatenate([flat1, flat2, flat3]) # interpretation dense1 = Dense(100, activation='relu')(merged) outputs = Dense(n_outputs, activation='softmax')(dense1) model = Model(inputs=[inputs1, inputs2, inputs3], outputs=outputs) # save a plot of the model plot_model(model, show_shapes=True, to_file='multichannel.png') model.compile(loss='categorical_crossentropy', optimizer='adam', metrics=['accuracy']) # fit network model.fit([trainX,trainX,trainX], trainy, epochs=epochs, batch_size=batch_size, verbose=verbose) # evaluate model _, accuracy = model.evaluate([testX,testX,testX], testy, batch_size=batch_size, verbose=0) return accuracy # summarize scores def summarize_results(scores): print(scores) m, s = mean(scores), std(scores) print('Accuracy: %.3f%% (+/-%.3f)' % (m, s)) # run an experiment def run_experiment(repeats=10): # load data trainX, trainy, testX, testy = load_dataset() # repeat experiment scores = list() for r in range(repeats): score = evaluate_model(trainX, trainy, testX, testy) score = score * 100.0 print('>#%d: %.3f' % (r+1, score)) scores.append(score) # summarize results summarize_results(scores) # run the experiment run_experiment() ``` 運行該示例在每次重復實驗時打印模型的表現,然后將估計得分總結為平均值和標準差,正如我們在第一種情況下使用簡單的 1D CNN 所做的那樣。 我們可以看到該模型的平均表現約為 91.6%的分類精度,標準偏差約為 0.8。 該示例可以用作探索各種其他模型的基礎,這些模型改變不同模型超參數甚至跨輸入頭的不同數據準備方案。 考慮到該模型中資源的相對三倍,將此結果與單頭 CNN 進行比較并不是一個蘋果對蘋果的比較。也許蘋果與蘋果的比較將是具有相同架構的模型,并且在模型的每個輸入頭上具有相同數量的過濾器。 ```py >#1: 91.788 >#2: 92.942 >#3: 91.551 >#4: 91.415 >#5: 90.974 >#6: 91.992 >#7: 92.162 >#8: 89.888 >#9: 92.671 >#10: 91.415 [91.78825924669155, 92.94197488971835, 91.55072955548015, 91.41499830335935, 90.97387173396675, 91.99185612487275, 92.16152019002375, 89.88802171700034, 92.67051238547675, 91.41499830335935] Accuracy: 91.680% (+/-0.823) ``` ## 擴展 本節列出了一些擴展您可能希望探索的教程的想法。 * **日期準備**。探索其他數據準備方案,例如數據標準化以及標準化后的標準化。 * **網絡架構**。探索其他網絡架構,例如更深入的 CNN 架構和更深層的全連接層,用于解釋 CNN 輸入功能。 * **診斷**。使用簡單的學習曲線診斷來解釋模型在時期中的學習方式,以及更多的正則化,不同的學習率,或不同的批量大小或時期數可能導致更好的表現或更穩定的模型。 如果你探索任何這些擴展,我很想知道。 ## 進一步閱讀 如果您希望深入了解,本節將提供有關該主題的更多資源。 ### 文件 * [使用智能手機進行人類活動識別的公共領域數據集](https://upcommons.upc.edu/handle/2117/20897),2013 年。 * [智能手機上的人類活動識別使用多類硬件友好支持向量機](https://link.springer.com/chapter/10.1007/978-3-642-35395-6_30),2012。 ### 用品 * [使用智能手機數據集進行人類活動識別,UCI 機器學習庫](https://archive.ics.uci.edu/ml/datasets/human+activity+recognition+using+smartphones) * [活動識別,維基百科](https://en.wikipedia.org/wiki/Activity_recognition) * [使用智能手機傳感器的活動識別實驗,視頻](https://www.youtube.com/watch?v=XOEN9W05_4A)。 ## 摘要 在本教程中,您了解了如何開發一維卷積神經網絡,用于人類活動識別問題的時間序列分類。 具體來說,你學到了: * 如何為標準人類活動識別數據集加載和準備數據,并開發單個 1D CNN 模型,以在原始數據上實現出色的表現。 * 如何進一步調整模型的表現,包括數據轉換,過濾器映射和內核大小。 * 如何開發一種復雜的多頭一維卷積神經網絡模型,提供類似集合的結果。 你有任何問題嗎? 在下面的評論中提出您的問題,我會盡力回答。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看