python中位数为nan_Python Scipy stats.nanmedian()用法及代码示例

本文介绍了如何使用Python Scipy库的nanmedian()函数计算包含Nan值的数组的中位数。通过示例代码展示了在不同维度数据上的应用,以及与普通median()函数的区别。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

scipy.stats.nanmedian(array, axis=0)函数通过忽略沿数组指定轴的数组元素的Nan(不是数字)值来计算中位数。

参数:

array:具有元素(包括Nan值)的输入数组或对象,以计算中位数。

axis:计算中值所沿的轴。默认情况下轴= 0

返回:基于设置参数的数组元素的中位数(忽略Nan值)。

代码1:

# median

import scipy

import numpy as np

arr1 = [1, 3, np.nan, 27, 2, 5]

print("median using nanmedian:", scipy.nanmedian(arr1))

print("median without handling nan value:", scipy.median(arr1))

输出:

median using nanmedian:3.0

median without handling nan value:nan

代码2:多维数据

# median

from scipy import median

from scipy import nanmedian

import numpy as np

arr1 = [[1, 3, 27],

[3, np.nan, 6],

[np.nan, 6, 3],

[3, 6, np.nan]]

print("median is:", median(arr1))

print("median handling nan:", nanmedian(arr1))

# using axis = 0

print("\nmedian is with default axis = 0:\n",

median(arr1, axis = 0))

print("\nmedian handling nan with default axis = 0:\n",

nanmedian(arr1, axis = 0))

# using axis = 1

print("\nmedian is with default axis = 1:\n",

median(arr1, axis = 1))

print("\nmedian handling nan with default axis = 1:\n",

nanmedian(arr1, axis = 1))

输出:

median is:nan

median handling nan:3.0

median is with default axis = 0:

[ nan nan nan]

median handling nan with default axis = 0:

[ 3. 6. 6.]

median is with default axis = 1:

[ 3. nan nan nan]

median handling nan with default axis = 1:

[ 3. 4.5 4.5 4.5]

import numpy as np import pywt import matplotlib.pyplot as plt import scipy.io as scio from sklearn.cluster import DBSCAN from sklearn.manifold import TSNE from sklearn.preprocessing import StandardScaler from scipy.stats import entropy from sklearn.svm import OneClassSVM import joblib def sliding_window(sequence, window_size, step_size): """ 对一维序列进行滑窗切分。 参数: sequence (array-like): 输入的一维序列。 window_size (int): 滑窗的窗口大小。 step_size (int): 滑窗的步长。 返回: np.ndarray: 切分后的窗口数组,每一行是一个窗口。 """ sequence = np.asarray(sequence) n = len(sequence) windows = [ sequence[i:i + window_size] for i in range(0, n - window_size + 1, step_size) ] return np.array(windows) if __name__ == "__main__": # 1. 载入数据 sliding_length, sliding_step = 16384, 16384 dataFile = r'.\subei GGZQ-DIS-G11-001-05.mat' dataTemp = scio.loadmat(dataFile) dataSet = np.array(dataTemp['mm']) dataSet = np.squeeze(dataSet) print(dataSet.shape) signals = sliding_window(dataSet, sliding_length, sliding_step) print(signals.shape) feature_matrix = [] for ii in range(signals.shape[0]): # 小波特征 coeffs = pywt.swt(signals[ii, :], wavelet='db1', level=4, trim_approx=True, norm=True) wavelet_features = np.var(np.array(coeffs)[1:, :], axis=1) # 新增的4个特征 window = signals[ii, :] # 差值 diff = window[:-1] - window[1:] diff_var = np.var(diff) # 极值 extremes = np.max(window) - np.min(window) # 均值 mean_value = np.mean(window) # 交叉熵 hist, _ = np.histogram(window, bins=10) cross_entropy = entropy(hist / hist.sum()) new_features = [diff_var, extremes, mean_value, cross_entropy] combined_features = np.concatenate((wavelet_features, new_features)) feature_matrix.append(combined_features) X = feature_matrix = np.vstack(feature_matrix) # 2. 特征标准化 scaler = StandardScaler() X_scaled = scaler.fit_transform(X) # 3.3 应用 DBSCAN dbscan = DBSCAN(eps=2, min_samples=5) labels = dbscan.fit_predict(X_scaled) # 4. 失真异常定位 anomaly_indices = np.squeeze(np.array(np.nonzero(labels))) anomaly_indices_start = [] anomaly_indices_end = [] for ii in range(anomaly_indices.shape[0]): anomaly_indices_start.append(anomaly_indices[ii] * sliding_step) anomaly_indices_end.append(anomaly_indices[ii] * sliding_step + sliding_length) anomaly_indices_start = np.squeeze(np.array(anomaly_indices_start)) anomaly_indices_end = np.squeeze(np.array(anomaly_indices_end)) # 5. 使用 t-SNE 降维 # 获取样本数量 n_samples = X_scaled.shape[0] # 确保 perplexity 小于样本数量 perplexity = min(30, n_samples - 1) tsne = TSNE(n_components=2, perplexity=perplexity) X_tsne = tsne.fit_transform(X_scaled) # 6. 使用 OC-SVM 进行训练 # 提取 DBSCAN 识别的正常数据(排除噪声点) normal_indices = np.where(labels != -1)[0] X_normal = X_scaled[normal_indices] oc_svm = OneClassSVM(nu=0.05, kernel="rbf", gamma=0.1) oc_svm.fit(X_normal) # 使用正常数据训练 OC-SVM # 7. 保存 OC-SVM 模型和标准化器 joblib.dump(oc_svm, 'oc_svm_model2.pkl') joblib.dump(scaler, 'scaler.pkl') # 保存标准化器 # 8. 可视化 t-SNE 降维聚类结果及失真定位结果 plt.figure(figsize=(8, 6)) plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=labels, cmap='viridis', s=50) plt.title("t-SNE Visualization based on Clustering Results") plt.xlabel("Feature 1") plt.ylabel("Feature 2") plt.colorbar(label="Cluster Label") plt.show() plt.figure(11) plt.plot(dataSet) print(anomaly_indices.shape[0]) for ii in range(anomaly_indices.shape[0]): plt.axvspan(anomaly_indices_start[ii], anomaly_indices_end[ii], facecolor='red', alpha=0.3) plt.show() 在我的代码中我通过对输入数据每个窗口进行8维特征提取,用OC-SVM训练得到了一个决策边界oc_svm_model2.pkl文件,单这个边界是通过8维特征训练得到的,我现在想用T-SNE对这个边界进行降维为2维度,以得到可视化的决策边界,请你整理思路并为我输出可行的代码,输出的代码需要你先运行直到不报错为止
最新发布
03-23
<think>好的,我需要解决如何将训练好的OC-SVM模型在8维特征空间中的决策边界通过t-SNE降维后可视化的问题。首先,我得理清楚思路。 用户已经用8维特征训练了OC-SVM,并保存了模型和标准化器。现在想用t-SNE将这8维数据降到2维,并在二维空间展示决策边界。但t-SNE本身是用于降维的,直接应用可能会让决策边界变形,因为降维后的空间和原始特征空间结构不同。所以,可能需要生成二维网格点,然后反标准化回原始8维,用OC-SVM预测这些点的类别,再在二维平面上绘制等高线。 步骤如下: 1. 加载之前保存的OC-SVM模型和标准化器。 2. 对原始数据应用t-SNE降维,得到二维坐标用于散点图。 3. 在二维t-SNE空间生成网格点。 4. 将这些网格点反标准化回原始8维特征空间?这里可能有问题,因为t-SNE是不可逆的,无法直接反推。所以需要另一种方法,比如在原始8维空间生成网格点,然后降维到2维,再用模型预测。但这样计算量太大,不现实。 或者,可以创建一个二维的网格,每个点对应t-SNE空间中的坐标,然后将这些点映射回原始的高维空间。但t-SNE没有逆变换,所以这种方法不可行。 另一种思路:在二维t-SNE空间中生成网格点,然后使用某种方法近似OC-SVM在降维后的决策边界。这可能不准确,因为t-SNE是非线性变换,决策边界在低维和高维的对应关系复杂。 可能需要采用替代方法,比如在t-SNE降维后的二维数据上重新训练一个分类器,但这已经不是原来的OC-SVM模型了,可能不符合用户需求。 或者,使用一种技巧:在原始高维空间中生成足够多的点,用OC-SVM预测它们的标签,然后降维到二维,绘制决策边界。这需要生成覆盖高维空间的数据点,但实际操作中可能困难,因为维度太高。 另一种可行的方法:在二维t-SNE空间生成网格点,然后利用这些点的坐标,通过某种插值方法预测其类别。这可能需要使用到最近邻或核方法,但可能不够准确。 或者,可以先生成二维网格点,然后将每个点通过某种方式转换为高维空间中的点(例如,使用t-SNE的逆变换,但t-SNE没有逆,所以不可行)。因此,这可能不可行。 可能正确的做法是:在原始数据经过t-SNE降维后的二维空间中,训练一个分类器(如SVM)来近似原始OC-SVM的决策边界。但这样其实是在二维空间重新训练,而不是使用原来的模型,但可以近似可视化。 但用户的需求是展示原始OC-SVM模型的决策边界在t-SNE降维后的投影。这可能需要将高维的决策函数映射到二维,这比较困难,因为t-SNE是非线性的。 所以,或许只能在二维图中绘制原始数据点的预测结果,并用等高线来展示边界。这可以通过在二维空间中进行插值,但可能不够准确。具体步骤可能如下: 1. 使用t-SNE将标准化后的特征矩阵X_scaled降维到2D,得到X_tsne。 2. 在这些二维点上训练一个分类模型(比如另一个SVM),用原始OC-SVM的预测结果作为标签。然后在二维网格上进行预测,绘制决策边界。但这样其实是训练一个代理模型,而不是直接展示原始模型的边界。 用户可能希望直接可视化原始模型在降维后的空间中的边界,但由于降维导致特征空间不同,这需要将高维的决策函数投影到低维,这在数学上可能无法直接实现。 可能的解决方案是:在二维网格点上生成对应的高维特征点,然后用OC-SVM模型进行预测,最后在二维空间绘制等高线。但如何生成高维特征点? 这里的问题是如何根据二维网格点生成合理的高维特征。这可能需要假设其他维度的值,比如取原始数据的均值或中位数,或者通过某种插值方法。但这样会引入假设,可能不准确。 例如,可以固定其他6个维度的值为原始数据的平均值,然后在二维网格上改变两个维度的值,生成高维数据点,用模型预测,从而绘制决策边界。但这样只能展示这两个维度对结果的影响,而忽略了其他维度的影响,可能导致边界不准确。 综合考虑,可能最可行的方法是在t-SNE降维后的二维空间中,使用原始OC-SVM对原始数据点的预测结果,然后通过插值方法生成决策边界。例如,使用网格点,每个点对应一个t-SNE坐标,然后将该点通过某种方法映射回高维空间,用OC-SVM预测。但如何映射回去? 这里的关键是无法将t-SNE的二维点反向映射到原始的高维空间,因为t-SNE没有逆变换函数。因此,这种方法不可行。 因此,可能只能采用另一种方法:生成一个高维网格,覆盖OC-SVM的决策边界附近区域,然后降维到二维,再绘制等高线。但这计算量极大,尤其在8维空间中,网格点的数量会指数增长,无法实际计算。 所以,可能需要采用采样的方法,生成大量随机样本,用OC-SVM预测后,再降维到二维,然后根据预测结果绘制边界。这可以通过以下步骤: 1. 生成大量随机样本,每个样本有8个特征,覆盖合理的范围。 2. 使用OC-SVM预测这些样本的标签(正常或异常)。 3. 使用t-SNE将这些样本连同原始数据一起降维到二维。 4. 在二维空间中绘制这些样本的预测结果,形成决策边界。 但这样生成大量样本可能计算量大,而且t-SNE在包含这些样本后,降维结果可能与原始不同,导致可视化不一致。 或者,可以仅在原始数据的基础上,使用预测结果,通过二维空间中的等高线来绘制边界。例如,使用原始数据的t-SNE坐标和对应的预测结果,训练一个二维分类器,然后绘制其边界。虽然这不是原始模型,但可以近似显示边界。 总结,可能可行的步骤: 1. 加载模型和标准化器。 2. 对原始数据X_scaled进行t-SNE降维,得到X_tsne。 3. 使用原始OC-SVM模型对X_scaled进行预测,得到预测标签。 4. 在X_tsne的二维空间中,使用预测标签,训练一个二维的SVM或其他分类器。 5. 在二维网格上预测这个新分类器的结果,绘制决策边界。 6. 这样,边界是基于原始模型在原始数据的预测结果,而t-SNE降维后的近似。 这可能是一个折中的办法,虽然并非直接展示原始模型的边界,但可以近似。 或者,另一种方法是使用decision_function方法得到每个样本的决策值,然后在二维t-SNE空间中进行插值,绘制等高线。具体步骤如下: 1. 对原始数据X_scaled进行t-SNE降维得到X_tsne。 2. 使用OC-SVM的decision_function获取每个样本的决策值。 3. 在X_tsne的二维空间上,使用网格点,通过插值方法(如线性插值)估计每个网格点的决策值。 4. 根据插值的决策值绘制等高线,如决策值为0的线即为边界。 这种方法不需要生成高维数据,直接在二维空间进行插值,但可能不够准确,因为决策值在高维空间中的分布可能与二维投影中的分布不一致。 综合考虑,这可能是一个可行的方法,尽管存在近似误差。 现在,根据这个思路编写代码: 步骤: 1. 加载模型和标准化器。 2. 对原始数据X_scaled进行t-SNE降维,得到X_tsne。 3. 计算每个样本的decision_function值。 4. 生成二维网格点。 5. 使用griddata等方法插值得到网格点的decision值。 6. 绘制等高线。 但需要注意,t-SNE的坐标可能范围较大,网格需要覆盖这些范围。 可能的代码: import numpy as np import matplotlib.pyplot as plt from scipy.interpolate import griddata # 加载模型和标准化器 oc_svm = joblib.load('oc_svm_model2.pkl') scaler = joblib.load('scaler.pkl') # 假设已经存在X_scaled和X_tsne(原代码中已经计算过) # 获取决策值 decision_values = oc_svm.decision_function(X_scaled) # 生成网格 x_min, x_max = X_tsne[:, 0].min() - 1, X_tsne[:, 0].max() + 1 y_min, y_max = X_tsne[:, 1].min() - 1, X_tsne[:, 1].max() + 1 xx, yy = np.meshgrid(np.linspace(x_min, x_max, 500), np.linspace(y_min, y_max, 500)) # 插值决策值到网格 grid_z = griddata(X_tsne, decision_values, (xx, yy), method='cubic') # 绘制轮廓 plt.figure(figsize=(8, 6)) plt.contourf(xx, yy, grid_z, levels=np.linspace(grid_z.min(), grid_z.max(), 10), cmap='RdBu') plt.contour(xx, yy, grid_z, levels=[0], colors='red') # 决策边界为0 plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=decision_values, cmap='RdBu', edgecolor='k', s=40) plt.colorbar(label='Decision Function Value') plt.title('OC-SVM Decision Boundary via t-SNE and Interpolation') plt.show() 不过,这种方法是否正确取决于插值是否合理。因为t-SNE空间中的点的分布可能不规则,导致插值结果不准确。特别是在数据点稀疏的区域,插值可能不可靠。 或者,可以训练一个回归模型,将t-SNE坐标作为输入,预测decision_values,然后在网格上进行预测。例如,使用支持向量回归或其他模型。这可能更可靠。 修改后的步骤: 1. 使用X_tsne作为特征,decision_values作为目标,训练回归模型。 2. 在网格点上用该模型预测,得到grid_z。 3. 绘制等高线。 代码示例: from sklearn.svm import SVR # 训练回归模型 svr = SVR(kernel='rbf', gamma='scale') svr.fit(X_tsne, decision_values) # 预测网格点 Z = svr.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) # 绘制 plt.contour(xx, yy, Z, levels=[0], colors='red') 这可能比插值更可靠,尤其是当数据点较多时。 综合以上思路,最终的代码可能如下: (需要测试是否可行) 需要确保X_scaled和X_tsne已经存在,比如用户之前的代码已经生成。 现在,整合到用户代码中: 用户原来的代码在训练完OC-SVM后,可以添加以下部分: # 获取决策函数值 decision_values = oc_svm.decision_function(X_scaled) # 使用t-SNE降维后的坐标作为训练数据,决策值作为目标,训练SVR from sklearn.svm import SVR svr = SVR(kernel='rbf', gamma='scale') svr.fit(X_tsne, decision_values) # 生成网格 x_min, x_max = X_tsne[:, 0].min() - 1, X_tsne[:, 0].max() + 1 y_min, y_max = X_tsne[:, 1].min() - 1, X_tsne[:, 1].max() + 1 xx, yy = np.meshgrid(np.linspace(x_min, x_max, 500), np.linspace(y_min, y_max, 500)) # 预测网格点的决策值 Z = svr.predict(np.c_[xx.ravel(), yy.ravel()]) Z = Z.reshape(xx.shape) # 绘制 plt.figure(figsize=(8, 6)) plt.contourf(xx, yy, Z, levels=np.linspace(Z.min(), Z.max(), 10), cmap='RdBu', alpha=0.8) plt.contour(xx, yy, Z, levels=[0], colors='red', linewidths=2) plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=decision_values, cmap='RdBu', edgecolor='k', s=40) plt.colorbar(label='Decision Function Value') plt.title('OC-SVM Decision Boundary via t-SNE and SVR Approximation') plt.show() 这种方法通过回归模型将高维的决策函数映射到t-SNE的二维空间,从而近似显示决策边界。这可能是一个可行的方案。 需要测试这段代码是否能够运行,并且是否产生合理的结果。例如,SVR的参数可能需要调整以获得更好的拟合效果,但作为近似,使用默认参数可能足够。 总结,最终的代码思路是:通过回归模型在t-SNE的二维坐标上预测原始OC-SVM的决策函数值,然后绘制等高线作为决策边界。</think>要实现OC-SVM在t-SNE降维空间的可视化决策边界,可以通过以下步骤实现: ```python import numpy as np import matplotlib.pyplot as plt from sklearn.svm import SVR from scipy.interpolate import griddata # 加载模型和标准化器 oc_svm = joblib.load('oc_svm_model2.pkl') scaler = joblib.load('scaler.pkl') # 获取决策函数值(正常样本的预测结果) decision_values = oc_svm.decision_function(X_scaled) # 创建网格空间 x_min, x_max = X_tsne[:, 0].min() - 1, X_tsne[:, 0].max() + 1 y_min, y_max = X_tsne[:, 1].min() - 1, X_tsne[:, 1].max() + 1 xx, yy = np.meshgrid(np.linspace(x_min, x_max, 500), np.linspace(y_min, y_max, 500)) # 方法1:使用SVR近似决策边界 svr = SVR(kernel='rbf', gamma='scale') svr.fit(X_tsne, decision_values) Z_svr = svr.predict(np.c_[xx.ravel(), yy.ravel()]) Z_svr = Z_svr.reshape(xx.shape) # 方法2:直接插值(需要足够密集的数据点) Z_griddata = griddata( points=X_tsne, values=decision_values, xi=(xx, yy), method='cubic', fill_value=np.nan ) # 可视化设置 plt.figure(figsize=(12, 5)) # SVR近似结果 plt.subplot(121) contour = plt.contour(xx, yy, Z_svr, levels=[0], colors='red') plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=decision_values, cmap='coolwarm', edgecolor='k', s=40) plt.colorbar(label='Decision Value') plt.title('SVR Approximation') # 直接插值结果 plt.subplot(122) plt.contour(xx, yy, Z_griddata, levels=[0], colors='blue') plt.scatter(X_tsne[:, 0], X_tsne[:, 1], c=decision_values, cmap='coolwarm', edgecolor='k', s=40) plt.colorbar(label='Decision Value') plt.title('Griddata Interpolation') plt.tight_layout() plt.show() ``` **原理解释**: 1. **决策函数映射**:通过`decision_function()`获取样本到决策边界的距离,正值表示正常样本,负值表示异常 2. **空间插值**:在t-SNE降维后的二维空间创建网格,使用两种方法重建决策边界: - **SVR回归**:将t-SNE坐标作为特征,决策值作为目标训练回归模型 - **网格插值**:直接使用插值算法估计网格点的决策值 3. **边界绘制**:在0值等高线位置绘制决策边界,红色(SVR)和蓝色(插值)分别表示不同方法的可视化结果 **注意事项**: 1. 两种方法都受限于t-SNE的非线性特性,边界为近似结果 2. 数据密度不足时插值方法可能产生空洞 3. SVR的gamma参数可根据数据分布调整
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值