RandomForestClassfier.fit():ValueError:无法将字符串转换为float

nil*_*lkn 50 python random-forest scikit-learn

给出一个简单的CSV文件:

A,B,C
Hello,Hi,0
Hola,Bueno,1
Run Code Online (Sandbox Code Playgroud)

显然,真正的数据集远比这复杂得多,但是这个数据集再现了错误.我正在尝试为它构建一个随机的森林分类器,如下所示:

cols = ['A','B','C']
col_types = {'A': str, 'B': str, 'C': int}
test = pd.read_csv('test.csv', dtype=col_types)

train_y = test['C'] == 1
train_x = test[cols]

clf_rf = RandomForestClassifier(n_estimators=50)
clf_rf.fit(train_x, train_y)
Run Code Online (Sandbox Code Playgroud)

但是我在调​​用fit()时得到这个回溯:

ValueError: could not convert string to float: 'Bueno'
Run Code Online (Sandbox Code Playgroud)

scikit-learn版本是0.16.1.

RPr*_*sle 53

在使用fit之前,您必须进行一些编码.因为它被告知fit()不接受字符串,但你解决了这个问题.

有几个类可以使用:

就个人而言,我前段时间在StackOverflow上发布了几乎相同的问题.我想要一个可扩展的解决方案,但没有得到任何答案.我选择了将所有字符串二值化的OneHotEncoder.它非常有效但是如果你有很多不同的字符串,那么矩阵将会非常快速地增长并且需要内存.

  • 谢谢。我最终找到了使用DictVectorizer的解决方案。我很惊讶没有更好的文档来处理这样的问题。如果我在这里有足够的业力,我会投票赞成。 (4认同)

Sin*_*ath 12

LabelEncoding为我工作(基本上你要对数据进行特征编码)(mydata是一个字符串数据类型的二维数组):

myData=np.genfromtxt(filecsv, delimiter=",", dtype ="|a20" ,skip_header=1);

from sklearn import preprocessing
le = preprocessing.LabelEncoder()
for i in range(*NUMBER OF FEATURES*):
    myData[:,i] = le.fit_transform(myData[:,i])
Run Code Online (Sandbox Code Playgroud)


far*_*awa 8

您无法传递str给您的模型fit()方法.正如它在这里提到的

培训输入样本.在内部,它将被转换为dtype = np.float32,并且如果稀疏矩阵被提供给稀疏的csc_matrix.

尝试将数据转换为float并尝试LabelEncoder.

  • 嗯,有哪些例子清楚地使用字符串数据?我猜他们已经过时了什么? (3认同)
  • 那么处理这个问题的规范方法是什么?我不是第一个尝试用scikit-learn做这件事的人. (2认同)

jo *_*ova 8

您可能无法通过str适合这种分类器。

例如,如果您有一个名为“等级”的特征列,它有 3 个不同的等级:

A,B和C

您必须通过编码器将那些str “A”、“B”、“C传输到矩阵,如下所示:

A = [1,0,0]

B = [0,1,0]

C = [0,0,1]
Run Code Online (Sandbox Code Playgroud)

因为 对分类str器没有数字意义。

在 scikit-learn 中,OneHotEncoder并且LabelEncoderinpreprocessing模块中可用。但是OneHotEncoder不支持 to fit_transform()of 字符串。转换过程中可能会发生“ValueError:无法将字符串转换为浮点数”。

您可以使用LabelEncoder从 转换str为连续数值。然后你就可以OneHotEncoder随心所欲地转移了。

在 Pandas 数据框中,我必须对所有分类为dtype:object. 以下代码对我有用,希望对您有所帮助。

 from sklearn import preprocessing
    le = preprocessing.LabelEncoder()
    for column_name in train_data.columns:
        if train_data[column_name].dtype == object:
            train_data[column_name] = le.fit_transform(train_data[column_name])
        else:
            pass
Run Code Online (Sandbox Code Playgroud)


Bea*_*ept 8

那么, OneHot 编码标签编码的工作方式之间存在重要差异:

  • 标签编码基本上会将您的字符串变量切换为int. 在这种情况下,找到的第一个类将被编码为1,第二个类将被编码为2,...但是这种编码会产生一个问题。

让我们以变量为例Animal = ["Dog", "Cat", "Turtle"]

如果你在上面使用标签编码器,Animal将会是[1, 2, 3]. 如果您将其解析为机器学习模型,它将解释Dog为 比 更近Cat,并且比 更远Turtle(因为1和之间的距离2小于 和 之间的距离13

当你有序数变量时,标签编码实际上非常好。

例如,如果您有一个值Age = ["Child", "Teenager", "Young Adult", "Adult", "Old"]

那么使用标签编码就完美了。比 离Child更近。你的变量有一个自然的顺序TeenagerYoung Adult

  • 当变量之间没有自然顺序时,OneHot 编码(也由 pd.get_dummies 完成)是最佳解决方案。

让我们回顾一下之前的例子Animal = ["Dog", "Cat", "Turtle"]

它将创建与您遇到的类一样多的变量。在我的示例中,它将创建 3 个二进制变量Dog, Cat and Turtle:如果有的话Animal = "Dog",编码就可以了Dog = 1, Cat = 0, Turtle = 0

然后你可以把这个给你的模型,他永远不会解释比from 更Dog接近。CatTurtle

但 OneHotEncoding 也有缺点。如果你有一个分类变量遇到 50 种类

例如:Dog, Cat, Turtle, Fish, Monkey, ...

那么它将创建 50 个二进制变量,这可能会导致复杂性问题。在这种情况下,您可以创建自己的类并手动更改变量

例如:Turtle, Fish, Dolphin, Shark在同一个类中重新组合Sea Animals,然后应用 OneHotEncoding。


小智 6

我有一个类似的问题,发现pandas.get_dummies()解决了这个问题。具体来说,它将分类数据的列拆分为一组布尔列,每个输入列中的每个唯一值都有一个新列。在您的情况下,您将替换train_x = test[cols]为:

train_x = pandas.get_dummies(test[cols])
Run Code Online (Sandbox Code Playgroud)

这会将train_x数据帧转换为RandomForestClassifier可以接受的以下形式:

   C  A_Hello  A_Hola  B_Bueno  B_Hi
0  0        1       0        0     1
1  1        0       1        1     0
Run Code Online (Sandbox Code Playgroud)