使用机器学习处理信号,我以语音信号为例。常见的声学信号特征有:
在这里插入图片描述

这些是声学信号中,常见的手工特征。针对特定的信号,会有一些常用的特征。一些通用的方法有:小波分解,信号分解(提取信号不同频率的特质)、主成分分解等。可以根据问题,先提取信号特征,再将特征输入到机器学习模型中进行建模分析。此外,机器学习(深度学习)技术本身也可以做信号特征的处理,比如以传统的全连接神经网络构造自编码器,或者是以卷积为基的深度学习自编码器(注意要信号的维度来选择不同的网络结构),这些都可以用来提取信号的特征+输出最终结果(分类或回归)。

(1)机器学习做信号分析,常用的提取手段有哪些?(2)哪些信号特征可以用来识别信号?

首先,针对常用的信号特征这个问题,一楼@刘锋博士已经回答的很好了,同时他还给特征分了三类,非常用心。这些特征非常有用,且在教科书上都能够找到相关的定义。我想我就不用在这里重复了,楼主应该可以查查文章,翻一翻书就能找到这部分知识。而我想从一个“更本质的角度”出发回答这个问题。任何能区分目标信号和其他信号的“描述”都能当作目标信号的特征。特征本质就是对一类信号“样貌”的“描述”。举一个例子,我们平时如何区分我们周围的人?我们一般从“身高”、“胖瘦”、“脸型”、“声音”等角度出发去辨别,这些就是我们对一个人“样貌”的定义和描述。信号一样我们可以从“均值”、“方差”、“有效值”、“频率”的角度描述信号的“样貌”。但是,特征的定义是什么呢?我们先看看百度词典的定义:特征,汉语词语,读音为tè zhēng,意思是一事物异于其他事物的特点。人或事物可供识别的特殊的象征或标志。我们可以看到“特征”本身最重要的含义是“事物异于其他事物的特点”。一个事物(这里可以直接认为是信号)的描述有很多,但是真正能称得上特征还必须具备一定的条件,那就是“差异性”。比如描述直流信号(方差都为0、均值为0)时,显然“有效值”能区分两种直流信号,而“均值”和“方差”无法区分两个直流信号。所以,此时我们认为“有效值”才是区分不同直流信号的特征,而不是“均值”和“方差”这样的描述。这充分体现的区分事物的“差异性”。再比如,两个正弦信号(注意幅度都为1、相位都为0)的特征应该是什么?很明显“均值”、“方差”、“有效值”都不适合了,因为你始终能构造出两个具有相同“方差”或“有效值”的两个正弦信号。而学过傅立叶变换的同学知道,区分两个正弦信号最有用的描述就是“频率”。这也就是傅立叶变换的核心“一个信号可以被分解为多个频率不同的正余弦信号的组合”。显然这个任务中“频率”才能称为信号的“特征”。试想一下,如果我要你区分直流和正弦信号呢?这时候你选择“有效值”显然就不合适了。我们可以构造出“有效值”完全相同的直流和正弦信号。而这说明了一个道理,真实情况中特征明显是和“要进行的任务”挂钩的。比如现实生活中区分“梨”和“苹果”,我们可以用“颜色”作为特征,而如果任务变为区分“樱桃”和“苹果”,显然此时“颜色”不再是“特征”,“大小”可能是这个任务应该考虑的特征。因此特征是“考虑任务场景,且具有事物区分度的描述”。这里我引用机械故障诊断领域先驱Simon Braun教授关于“机械特征分析”的定义来说明这个问题:“机械特征分析”—机械设备异常状态导致的振动特征能很容易地同健康状态下的参考特征区分开来上面这句话考虑的场景是“基于振动的机械设备异常分析”,“健康状态下的参考特征区分开来”是对“事物区分度”的表述。如果你真的需要一些即插即用的“描述”(注意我这里用的是描述,不是特征),我还是给你一个我曾经回答这个问题的链接。机械故障诊断及寿命预测中,通俗的讲特征提取是什么意思? - aresmiki的回答 - 知乎。接下来另一个问题,特征提取手段。其实楼主的问题已经回答了这个问题的一小部分。“机器学习”本身就是一种特征提取手段。这里我给楼主一个例子:如何让一个不知道“苹果”和“梨”是什么的人能认识“苹果”呢?有一种方法就是“机器学习”。当他拿一个水果(样本)过来,我们只需要告诉他是不是“苹果”(这就是标签)。第一次他拿了一个大的“梨”过来,我们告诉他不是“苹果”,第二次他拿了一个小的“梨”过来,我们还是告诉他不是“苹果”。通过两次学习他知道了大小不是区分“苹果”和“梨”的关键,第三次他拿了一个带把的“苹果”过来,我们告诉他是“苹果”,第四次他拿了带把的“梨”过来,我们还是告诉他不是“苹果”。这两次他知道带不带把也不是区分两个水果的关键。。。。就这样不断的累积经验最终他会学习到“颜色”是区分他们的关键,他也就总结了“颜色”是这个任务的特征。很显然,这个特征的提取是通过学习。另一种呢就是直接专家经验呢,让一些已经知道的人直接根据经验去总结。回到信号特征的提取手段上面来,第一种就是“用机器学习”来提取特征,典型的就是“神经网络”和“机器学习”,这类方法学习到的特征具有很强的针对性,特定适用于这个任务。第二种就是经验的总结,数学上经验的总结一般用数学公式来描述,如“均值”,“方差”等等,可以看到一般都是基于一些统计手段进行描述。现实中,这些统计的描述太过宽泛,因此我们并不知道这些描述能不能用于我们特定的任务。比如前面“颜色”这个特征是人们在处理“苹果”和“梨”的任务中总结出的一种描述,但是如果换做“樱桃”和“苹果”的案例中就可能不适用。所以我们在使用现成总结好的特征时往往需要有一个过程“特征筛选”,人为的筛选出一些适用的“描述”作为特征。回到主题,第二种特征提取方法本质上人为经验的数学总结(主要适用统计手段)。另一类看是文字描述,本质还是适用数学手段描述的人工经验指标。比如,EMD(经验模态分解)对它想要得到的信号的“特征”描述是:IMF(固有模态函数)的定义⑴函数在整个时间范围内,局部极值点和过零点的数目必须相等,或最多相差一个;⑵在任意时刻点,局部最大值的包络(上包络线)和局部最小值的包络(下包络线) 平均必须为零很显然这两句话依然是对要区分的信号的特征描述。在实际操作过程中,EMD通过“EMD迭代筛分步骤”实现这个特征的数学话,最终从一个复杂信号中提取出所有和定义“特征”相符的信号。上面这个例子实际表述了一个现实,所有的信号分析和处理都是在做“特征”分析。不仅仅是“故障诊断”、“语音识别”等耳熟能详的任务。举例:小波分析将信号分解为和小波基相似的信号,因此给定的这个小波基函数就是一个“特征”的描述,要求分解的信号要和给定的这个基函数一样。傅立叶分析定义的信号的特征就是“频率”,他将信号分解为“频率”不一样的组合。PCA(主成分分析)使用“方差”作为区分信号特征,将信号分解为多个“方差”不同的信号。所以所有信号分析方法背后的本质都有一个“特征”作为目标的指导。就像我们找东西,都需要知道东西是什么,这里的“是什么”就是通过“特征”来描述。先回答这么多吧。。。。有时间再回答最后这个问题“哪些信号特征可以用来识别信号?”OK~~本来想出去,遇到下雨了!还是回来把这个问题回答完吧。实际上,上面我已经回答了这个问题,那些特征可用主要取决于你的任务。应为即使你直接使用现成总结好的特征,你依然面临一个问题“特征筛选”。这个问题非常常见。以机械故障诊断为例,我们经常能看到很多这种文章

在这里插入图片描述
最简单就是根本不对特征进行选择,让神经网络自己去挑选有用的特征(通过网络权重大小决定特征的重要性)。这中策略“非常简单”,缺陷就是无用特征太多,网络结构太大,难以训练,最后“机器学习”的结果可能不是很满意。如果你想看看第一种技术的一个具体实现案例(包含大量特征计算),可以在这里下载到:案例

扩展阅读:

玩转信号处理与机器学习入门

面对毫无规律的随机信号,看着杂乱无章的振动波形,你是否也像曾经的我一样一头雾水,不知从何处下手。莫慌,接下来小编就带你入门怎样用python处理这些看似毫无卵用实则蕴藏巨大信息的随机信号。我们日常生活中所见的心电图,声波图都是信号在时域上的一种表现,但它们无法呈现出信号在频域上的信息。因此,本文将主要介绍信号从时域到频域上的一些变换,常见的有FFT(快速傅里叶变换),PSD(功率谱密度),auto-correlation(自相关分析)。最后将带你完成一个实例,通过手机采集的振动信号识别人体的动作。

一、介绍
本部分将介绍FFT,PSD,auto-correlation的基本概念以及python代码实现。

1.1 混合信号
在这里插入图片描述
图1 信号在时域上的表现
在这里插入图片描述

图2 信号在频域上的表现

上图展示了混合信号在时域上的表现形式,图(a)为一频率为1Hz,振幅为2的正弦波信号,图(b)为一频率为5Hz,振幅为1的正弦波信号,图(c)为(a)、(b)两信号的叠加结果。

1.2 FFT
FFT英文全称Fast Fourier Transformation,即快速傅里叶变换,它可以轻松地分析出混合信号中的各频率组成成分。对上述中的混合信号做FFT变换,结果如图2(a),可以明显地看到混合信号包含频率分别为1Hz和5Hz的成分。FFT变换的代码如下:

from scipy.fftpack import fft
 def get_fft_values(y_values, N, f_s):
    f_values = np.linspace(0.0, f_s/2.0, N//2)
    fft_values_ = fft(y_values)
    fft_values = 2.0/N * np.abs(fft_values_[0:N//2])
    return f_values, fft_values

1.3 PSD
PSD英文全称Power Spectral Density,即功率谱密度,它和FFT一样,反映的是信号在频域上的信息。其中PSD频谱图脉冲下方的面积表示信号在该频率上的能量分布。

对上述中的混合信号做PSD变换,结果如图2(b),可以明显地看到混合信号在频率为1Hz和5Hz上的能量分布。PSD变换的代码如下:

from scipy.signal import welch
def get_psd_values(y_values, N, f_s):
    f_values, psd_values = welch(y_values, fs=f_s)
    return f_values, psd_values

1.4 Autocorrelation
Autocorrelation是自相关的意思,它可以求出信号的自相关性,即信号经过一个时延后与自身的相似性。对上述中的混合信号计算Autocorrelation,结果如图2(c)所示

。有趣的是Autocorrelation与PSD是一组FFT变换对,对Autocorrelation作FFT变换可得到PSD,对PSD作IFFT(快速傅里叶逆变换)可得到Autocorrelation。

def autocorr(x):
    result = np.correlate(x, x, mode='full')
    return result[len(result)//2:]
 
def get_autocorr_values(y_values, N, f_s):
    autocorr_values = autocorr(y_values)
    x_values = np.array([ 1.0*jj/f_s for jj in range(0, N)])
    return x_values, autocorr_values

二 实例
经过上面的简单介绍相信你已经了解并掌握了信号在频域上的变换。写下来让我们运用刚学的知识结合机器学习知识来分析一个实例 Human Activity Recognition Using Smartphones Data Set。该数据集通过在30个不同年龄分布的志愿者上做实验采集得到,在志愿者的腰上固定一手机,手机以50Hz的采样频率采集内嵌加速度计和陀螺仪的数据,志愿者被要求做以下六个动作:walking(行走),walking upstairs(爬楼梯),walking downstairs(下楼梯),sitting(坐着),standing(站着),laying(躺下)。在滤除噪声之后,通过滑动窗口的方式将信号切分成2.56s的窗口,每个窗口包含128个样本。该数据集包含三组数据three-axial linear body acceleration(去除重力加速度的加速度计数据)、three-axial linear total acceleration(包含重力加速度的加速度计数据)、three-axial angular velocity(陀螺仪的数据),因此共有九个分量,其中训练集有7392个窗口,测试集有2947个窗口。

图3 数据集分布
在这里插入图片描述

2.1 数据可视化
随机选取一信号,绘出其在时域和频域上的波形图如下所示,绘图代码详见项目链接:

在这里插入图片描述

def get_first_n_peaks(x, y, no_peaks=5):
    x_, y_ = list(x), list(y)
    if len(x_) >= no_peaks:
        return x_[:no_peaks], y_[:no_peaks]
    else:#少于5个peaks,以0填充
        missing_no_peaks = no_peaks-len(x_)
        return x_ + [0]*missing_no_peaks, y_ + [0]*missing_no_peaks


def get_features(x_values, y_values, mph):
    indices_peaks = detect_peaks(y_values, mph=mph)
    peaks_x, peaks_y = get_first_n_peaks(
        x_values[indices_peaks], y_values[indices_peaks])
    return peaks_x + peaks_y


def extract_features_labels(dataset, labels, N, f_s, denominator):
    percentile = 5
    list_of_features = []
    list_of_labels = []
    for signal_no in range(0, len(dataset)):
        features = []
        list_of_labels.append(labels[signal_no])
        for signal_comp in range(0, dataset.shape[2]):
            signal = dataset[signal_no, :, signal_comp]

            signal_min = np.nanpercentile(signal, percentile)
            signal_max = np.nanpercentile(signal, 100-percentile)
            #ijk = (100 - 2*percentile)/10
            #set minimum peak height
            mph = signal_min + (signal_max - signal_min)/denominator

            features += get_features(*get_psd_values(signal, N, f_s), mph)
            features += get_features(*get_fft_values(signal, N, f_s), mph)
            features += get_features(*get_autocorr_values(signal, N, f_s), mph)
        list_of_features.append(features)
    return np.array(list_of_features), np.array(list_of_labels)

X_train, Y_train = extract_features_labels(train_signals, train_labels, N, f_s, denominator)
X_test, Y_test = extract_features_labels(test_signals, test_labels, N, f_s, denominator)

在这里插入图片描述
图5 特征提取详细介绍

2.3 模型训练及结果展示
当构建完特征矩阵以及其对应的标签之后,我们可以选择scikit-learn库中的相关模型进行训练。

clf = RandomForestClassifier(n_estimators=1000)
clf.fit(X_train, Y_train)
print("Accuracy on training set is : {}".format(clf.score(X_train, Y_train)))
print("Accuracy on test set is : {}".format(clf.score(X_test, Y_test)))
Y_test_pred = clf.predict(X_test)
print(classification_report(Y_test, Y_test_pred))

结果如下:
在这里插入图片描述
图6 分类结果展示
在这里插入图片描述
图7 模型比较
正如结果所展示的那样,我们能以相当高的准确率(89%)对这些信号进行分类,取得这个结果,我们甚至都没有做任何手动的特征工程,所有特征都是自动获取的,对于每个变换,我们取前五个峰值的横纵坐标(若少于五个则填充0)。可以理解的一点是,这270个特性中的一些特征将比其他特征提供更多的信息,若我们能主动地选择对分类很重要的特征进行组合,或者对超参数进行优化,相信准确率还能继续提高。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐