【问题标题】:Error when scaling features for clustering in Python and Sklearn在 Python 和 Sklearn 中为集群缩放特征时出错
【发布时间】:2021-12-04 06:20:21
【问题描述】:

我想用 Python 和 Scikit-Learn 库为我的数据集创建聚类模型。数据集包含连续值和分类值。 我已经编码了分类值,但是当我想缩放功能时,我收到了这个错误:

"Cannot center sparse matrices: pass `with_mean=False` "
ValueError: Cannot center sparse matrices: pass `with_mean=False` instead. See docstring for motivation and alternatives.

我在这一行遇到了这个错误:

features = scaler.fit_transform(features)

我做错了什么?

这是我的代码:

features = df[['InvoiceNo', 'StockCode', 'Description', 'Quantity',
               'UnitPrice', 'CustomerID', 'Country', 'Total Price']]

columns_for_scaling = ['InvoiceNo', 'StockCode', 'Description', 'Quantity', 'UnitPrice', 'CustomerID', 'Country', 'Total Price']

transformerVectoriser = ColumnTransformer(transformers=[('Encoding Invoice number', OneHotEncoder(handle_unknown = "ignore"), ['InvoiceNo']),
                                                        ('Encoding StockCode', OneHotEncoder(handle_unknown = "ignore"), ['StockCode']),
                                                        ('Encoding Description', OneHotEncoder(handle_unknown = "ignore"), ['Description']),
                                                        ('Encoding Country', OneHotEncoder(handle_unknown = "ignore"), ['Country'])],
                                          remainder='passthrough') # Default is to drop untransformed columns

features = transformerVectoriser.fit_transform(features)
print(features.shape)

scaler = StandardScaler()
features = scaler.fit_transform(features)

sum_of_squared_distances = []
for k in range(1,16):
    kmeans = KMeans(n_clusters=k)
    kmeans = kmeans.fit(features)
    sum_of_squared_distances.append(features.inertia_)

预处理前我的数据形状:(401604, 8) 预处理后我的数据形状:(401604, 29800)

【问题讨论】:

  • 错误信息给出了一个简单的解决方案:在缩放器中设置with_mean=False

标签: python machine-learning scikit-learn k-means


【解决方案1】:

如果您在实例化OneHotEncoder 时设置sparse=False,那么StandardScaler() 将按预期工作。

import pandas as pd
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.cluster import KMeans

# define the feature matrix
features = pd.DataFrame({
    'InvoiceNo': np.random.randint(1, 100, 100),
    'StockCode': np.random.randint(100, 200, 100),
    'Description': np.random.choice(['a', 'b', 'c', 'd'], 100),
    'Quantity': np.random.randint(1, 1000, 100),
    'UnitPrice': np.random.randint(5, 10, 100),
    'CustomerID': np.random.choice(['1', '2', '3', '4'], 100),
    'Country': np.random.choice(['A', 'B', 'C', 'D'], 100),
    'Total Price': np.random.randint(100, 1000, 100),
})

# encode the features (set "sparse=False") 
transformerVectoriser = ColumnTransformer(
    transformers=[
        ('Encoding Invoice number', OneHotEncoder(sparse=False, handle_unknown='ignore'), ['InvoiceNo']),
        ('Encoding StockCode', OneHotEncoder(sparse=False, handle_unknown='ignore'), ['StockCode']),
        ('Encoding Description', OneHotEncoder(sparse=False, handle_unknown='ignore'), ['Description']),
        ('Encoding Country', OneHotEncoder(sparse=False, handle_unknown='ignore'), ['Country'])
    ],
    remainder='passthrough'
)

features = transformerVectoriser.fit_transform(features)

# scale the features
scaler = StandardScaler()
features = scaler.fit_transform(features)

# run the cluster analysis
sum_of_squared_distances = []
for k in range(1, 16):
    kmeans = KMeans(n_clusters=k)
    kmeans = kmeans.fit(features)
    sum_of_squared_distances.append(kmeans.inertia_)

或者,您可以使用features = features.toarray() 将稀疏矩阵转换为数组。

import pandas as pd
import numpy as np
from sklearn.compose import ColumnTransformer
from sklearn.preprocessing import OneHotEncoder, StandardScaler
from sklearn.cluster import KMeans

# define the feature matrix
features = pd.DataFrame({
    'InvoiceNo': np.random.randint(1, 100, 100),
    'StockCode': np.random.randint(100, 200, 100),
    'Description': np.random.choice(['a', 'b', 'c', 'd'], 100),
    'Quantity': np.random.randint(1, 1000, 100),
    'UnitPrice': np.random.randint(5, 10, 100),
    'CustomerID': np.random.choice(['1', '2', '3', '4'], 100),
    'Country': np.random.choice(['A', 'B', 'C', 'D'], 100),
    'Total Price': np.random.randint(100, 1000, 100),
})

# encode the features
transformerVectoriser = ColumnTransformer(
    transformers=[
        ('Encoding Invoice number', OneHotEncoder(handle_unknown='ignore'), ['InvoiceNo']),
        ('Encoding StockCode', OneHotEncoder(handle_unknown='ignore'), ['StockCode']),
        ('Encoding Description', OneHotEncoder(handle_unknown='ignore'), ['Description']),
        ('Encoding Country', OneHotEncoder(handle_unknown='ignore'), ['Country'])
    ],
    remainder='passthrough'
)

features = transformerVectoriser.fit_transform(features)
features = features.toarray() # convert sparse matrix to array

# scale the features
scaler = StandardScaler()
features = scaler.fit_transform(features)

# run the cluster analysis
sum_of_squared_distances = []
for k in range(1, 16):
    kmeans = KMeans(n_clusters=k)
    kmeans = kmeans.fit(features)
    sum_of_squared_distances.append(kmeans.inertia_)

【讨论】:

  • 谢谢,但我现在还有其他问题: ArrayMemoryError: Unable to allocate 89.2 GiB for an array with shape (401604, 29800) and data type float64 这是我的数据在预处理前后的形状.预处理前的数据形状:(401604, 8),预处理后的数据形状:(401604, 29800)
  • 另外,即使我减小数据的大小,我也会得到这个:AttributeError: 'numpy.ndarray' object has no attribute 'inertia_'
  • 确实是kmeans.inertia_,而不是features.inertia_
猜你喜欢
  • 2021-03-09
  • 2016-07-28
  • 2012-05-06
  • 2018-02-24
  • 2020-05-31
  • 2019-03-21
  • 2018-07-21
  • 1970-01-01
  • 2019-09-10
相关资源
最近更新 更多