如何用 Python 聚类红外光谱数据
How to Cluster Infrared Spectroscopy Data with Python
我一直在研究使用 sklearn 聚类方法对红外光谱数据进行聚类。我在让聚类处理数据时遇到问题,因为我是新手,我不知道是我的编码方式有误还是我的方法有误。
我的数据,采用 Pandas DataFrame 格式,如下所示:
Index Wavenumbers (cm-1) %Transmission_i ...
0 650 100 ...
. . . ...
. . . ...
. . . ...
n 4000 95 ...
其中,所有光谱的 x 轴是 Wavenumbers (cm-1)
列,后续列 (%Transmission_i
) 是实际数据。我想对这些列进行聚类(根据哪些光谱彼此最相似),因此我正在尝试此代码:
X = np.array([list(df[x].values) for x in df.set_index(x)])
clusters = DBSCAN().fit(X)
其中 df
是我的 DataFrame,np
是 numpy(希望显而易见)。问题是当我打印出集群标签时,它只吐出 -1
什么也没有,这意味着我所有的数据都是噪音。事实并非如此,当我绘制数据时,我可以清楚地看到一些光谱看起来非常相似(它们应该如此)。
如何正确聚类相似的光谱?
编辑:
这是一个最小的工作示例。
import numpy as np
import pandas as pd
import sklearn as sk
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
x = 'x-vals'
def cluster_data(df):
avg_list = []
dif_list = []
for col in df:
if x == col:
continue
avg_list.append(np.mean(df[col].values))
dif_list.append(np.mean(np.diff(df[col].values)))
a = sk.preprocessing.normalize([avg_list], norm='max')[0]
b = sk.preprocessing.normalize([dif_list], norm='max')[0]
X = []
for i,j in zip(a,b):
X.append([i,j])
X = np.array(X)
clusters = DBSCAN(eps=0.2).fit(X)
return clusters.labels_
def plot_clusters(df, clusters):
colors = ['red', 'green', 'blue', 'black', 'pink']
i = 0
for col in df:
if col == x:
continue
color = colors[clusters[i]]
plt.plot(df[x], df[col], color=color)
i +=1
plt.show()
x1 = np.linspace(-np.pi, np.pi, 201)
y1 = np.sin(x1) + 1
y2 = np.cos(x1) + 1
y3 = np.zeros_like(x1) + 2
y4 = np.zeros_like(x1) + 1.9
y5 = np.zeros_like(x1) + 1.8
y6 = np.zeros_like(x1) + 1.7
y7 = np.zeros_like(x1) + 1
y8 = np.zeros_like(x1) + 0.9
y9 = np.zeros_like(x1) + 0.8
y10 = np.zeros_like(x1) + 0.7
df = pd.DataFrame({'x-vals':x1, 'y1':y1, 'y2':y2, 'y3':y3, 'y4':y4,
'y5':y5, 'y6':y6, 'y7':y7, 'y8':y8, 'y9':y9,
'y10':y10})
clusters = cluster_data(df)
plot_clusters(df, clusters)
这会产生以下图,其中红色是簇,粉红色是噪声。
首先,转置您的数据框,以便您按照标准将数据点作为行。它应该是这样的:
Index 650 660 ... 4000
0 100 98 ... 95
1 . . ... .
. . . ... .
n . . ... .
然后你得到你的 X
这样的聚类:
X = df.values
接下来,你集群:
from sklearn.cluster import DBSCAN
cluster = DBSCAN().fit(X)
print(cluster.labels_)
作为光谱数据的推荐,kmeans(缺点:需要事先设置簇数)和self-organizing maps(缺点:软簇而不是硬簇)效果很好。例如,您找到一个示例 here 用于对高光谱数据进行聚类。
我能够找到一个有效的方法,但我不完全相信这是聚类 IR 光谱的最佳方法。
首先,我运行 遍历了所有光谱,并编制了每个光谱的 mean
和 mean of the first derivative
列表。 mean
应该代表光谱的垂直位置,而 mean of the first derivative
应该代表光谱的形状。
avg_list = []
dif_list = []
for col in df:
if x == col:
continue
avg_list.append(np.mean(df[col].values))
dif_list.append(np.mean(np.dif(df[col].values)))
然后我标准化每个列表,这样我就可以根据百分比变化选择一个 eps
值。
a = sk.preprocessing.normalize([avg_list], norm='max')[0]
b = sk.preprocessing.normalize([diff_list], norm='max')[0]
之后,我在二维模式下为 运行nning DBSCAN 创建了一个二维数组。
X = []
for i,j in zip(a,b):
X.append([i,j])
然后我 运行 DBSCAN 聚类方法,eps
参数具有任意百分比差异值。
X = np.array(X)
clusters = DBSCAN(eps=0.2).fit(X)
然后 clusters.labels_
returns 一个数组,其长度为我的 DataFrame 中光谱的数量。它工作得相当好,但它是相当排他的,集群可能会更好。一些更精细的调整会有所帮助。
我一直在研究使用 sklearn 聚类方法对红外光谱数据进行聚类。我在让聚类处理数据时遇到问题,因为我是新手,我不知道是我的编码方式有误还是我的方法有误。
我的数据,采用 Pandas DataFrame 格式,如下所示:
Index Wavenumbers (cm-1) %Transmission_i ...
0 650 100 ...
. . . ...
. . . ...
. . . ...
n 4000 95 ...
其中,所有光谱的 x 轴是 Wavenumbers (cm-1)
列,后续列 (%Transmission_i
) 是实际数据。我想对这些列进行聚类(根据哪些光谱彼此最相似),因此我正在尝试此代码:
X = np.array([list(df[x].values) for x in df.set_index(x)])
clusters = DBSCAN().fit(X)
其中 df
是我的 DataFrame,np
是 numpy(希望显而易见)。问题是当我打印出集群标签时,它只吐出 -1
什么也没有,这意味着我所有的数据都是噪音。事实并非如此,当我绘制数据时,我可以清楚地看到一些光谱看起来非常相似(它们应该如此)。
如何正确聚类相似的光谱?
编辑: 这是一个最小的工作示例。
import numpy as np
import pandas as pd
import sklearn as sk
import matplotlib.pyplot as plt
from sklearn.cluster import DBSCAN
x = 'x-vals'
def cluster_data(df):
avg_list = []
dif_list = []
for col in df:
if x == col:
continue
avg_list.append(np.mean(df[col].values))
dif_list.append(np.mean(np.diff(df[col].values)))
a = sk.preprocessing.normalize([avg_list], norm='max')[0]
b = sk.preprocessing.normalize([dif_list], norm='max')[0]
X = []
for i,j in zip(a,b):
X.append([i,j])
X = np.array(X)
clusters = DBSCAN(eps=0.2).fit(X)
return clusters.labels_
def plot_clusters(df, clusters):
colors = ['red', 'green', 'blue', 'black', 'pink']
i = 0
for col in df:
if col == x:
continue
color = colors[clusters[i]]
plt.plot(df[x], df[col], color=color)
i +=1
plt.show()
x1 = np.linspace(-np.pi, np.pi, 201)
y1 = np.sin(x1) + 1
y2 = np.cos(x1) + 1
y3 = np.zeros_like(x1) + 2
y4 = np.zeros_like(x1) + 1.9
y5 = np.zeros_like(x1) + 1.8
y6 = np.zeros_like(x1) + 1.7
y7 = np.zeros_like(x1) + 1
y8 = np.zeros_like(x1) + 0.9
y9 = np.zeros_like(x1) + 0.8
y10 = np.zeros_like(x1) + 0.7
df = pd.DataFrame({'x-vals':x1, 'y1':y1, 'y2':y2, 'y3':y3, 'y4':y4,
'y5':y5, 'y6':y6, 'y7':y7, 'y8':y8, 'y9':y9,
'y10':y10})
clusters = cluster_data(df)
plot_clusters(df, clusters)
这会产生以下图,其中红色是簇,粉红色是噪声。
首先,转置您的数据框,以便您按照标准将数据点作为行。它应该是这样的:
Index 650 660 ... 4000
0 100 98 ... 95
1 . . ... .
. . . ... .
n . . ... .
然后你得到你的 X
这样的聚类:
X = df.values
接下来,你集群:
from sklearn.cluster import DBSCAN
cluster = DBSCAN().fit(X)
print(cluster.labels_)
作为光谱数据的推荐,kmeans(缺点:需要事先设置簇数)和self-organizing maps(缺点:软簇而不是硬簇)效果很好。例如,您找到一个示例 here 用于对高光谱数据进行聚类。
我能够找到一个有效的方法,但我不完全相信这是聚类 IR 光谱的最佳方法。
首先,我运行 遍历了所有光谱,并编制了每个光谱的 mean
和 mean of the first derivative
列表。 mean
应该代表光谱的垂直位置,而 mean of the first derivative
应该代表光谱的形状。
avg_list = []
dif_list = []
for col in df:
if x == col:
continue
avg_list.append(np.mean(df[col].values))
dif_list.append(np.mean(np.dif(df[col].values)))
然后我标准化每个列表,这样我就可以根据百分比变化选择一个 eps
值。
a = sk.preprocessing.normalize([avg_list], norm='max')[0]
b = sk.preprocessing.normalize([diff_list], norm='max')[0]
之后,我在二维模式下为 运行nning DBSCAN 创建了一个二维数组。
X = []
for i,j in zip(a,b):
X.append([i,j])
然后我 运行 DBSCAN 聚类方法,eps
参数具有任意百分比差异值。
X = np.array(X)
clusters = DBSCAN(eps=0.2).fit(X)
然后 clusters.labels_
returns 一个数组,其长度为我的 DataFrame 中光谱的数量。它工作得相当好,但它是相当排他的,集群可能会更好。一些更精细的调整会有所帮助。