首页 > 解决方案 > Unintended dtype conversion leads to uncastable array

问题描述

One of my class methods seems to convert data type from float64 to string.

    def transfer(self, sample):
        """Takes a list, tupel or arry as input."""
        c = self.bias + np.dot(sample[:-1], self.weights)
        return c

If this function gets called manualy with the inputs:

sample = learning_data.loc[0, "1":"3"]
1   -0.383362
2   -0.487992
3    0.000000
Name: 0, dtype: float64
x.transfer(sample)

I get the correct result. But if the function gets called from:

    def learn(self, vector):
    for sample in vector:
        y = self.activator(self.transfer(sample))

        if y != sample[-1]:
            w = self.update_weigts(y, sample)
            b = self.update_bias(y, sample)

        else:
            pass

With:

vector = learing_data.loc[: ,"1":"3"]
     0       1          2       3
565  1  -0.761398   -1.060793   0
670  1  1.861826    1.822200    0
72   1  1.440886    1.718266    0
898  1  -2.472685   -1.699168   0
1773 1  1.075351    4.293892    1

I get the following error:

--> y = self.activator(self.transfer(sample))
TypeError: Cannot cast array data from dtype('float64') to dtype('<U32') 
according to the rule 'safe'

I first checked checked what '

<class 'pandas.core.frame.DataFrame'>
Int64Index: 1400 entries, 565 to 1515
Data columns (total 4 columns):
0    1400 non-null int64
1    1400 non-null float64
2    1400 non-null float64
3    1400 non-null int64
dtypes: float64(2), int64(2)
memory usage: 94.7 KB

There is no stirng type in there and the function get's called like this:

x.learn(learning_data.loc[:, '1':'3'])

So there is no proir manipulation of the datatype to the transfere funktion. The Only thing that get's done to the data is the for loop in the learning function.

What am I missing?

Minimum code to reproduce the Error:

import numpy as np
import pandas as pd
import random

class Perzeptron(object):
    def __init__(self, n):
        """n is the number of weights that are needed."""
        self.weights = np.array([random.uniform(-1, 1) for f in range(n)])
        self.bias =  random.uniform(-1, 1)
        self.rate = 1


    def transfer(self, sample):
        c = self.bias + np.dot(sample[:-1], self.weights)
        return c


    def activator(self, c):
        if c > 0:
            return 1
        else:
            return 0


    def learn(self, vector):
        for sample in vector:
            y = self.activator(self.transfer(sample))

            if y != sample[-1]:
                w = 1  # call to jet another function
                b = 2  # call to jet another function

            else:
                pass

v = {'0': {565: 1, 670: 1, 72: 1, 898: 1, 1773: 1},
'1': {565: -0.761397898, 670: 1.8618260619999998, 72: 1.4408856630000002,
 898: -2.472684622, 1773: 1.0753508809999999},
'2': {565: -1.060793281, 670: 1.8221998209999999, 72: 1.7182657719999999,
 898: -1.699168086, 1773: 4.293891907},
'3': {565: 0, 670: 0, 72: 0, 898: 0, 1773: 1}}

learning_data = pd.Dataframe(v)
x = Perzeptron(2)
x.learn(learning_data.loc[:, '1':'3'])

EDIT:

The problem was that sample didn't have the shape I expected. Droping the 0 column of the Dataframe and using

x.learn(learning_data.values)

gives the result I was looking for.

标签: python-3.xnumpyarray-broadcasting

解决方案


好吧,您是否应该是表中的每一行都不是很清楚,但现在它只是遍历列而不是任何实际数字。所以我能够通过这样做使代码工作。修复位于函数内部的 for 循环中learn()

import numpy as np
import pandas as pd


class Perzeptron(object):
    def __init__(self, n):
        """n is the number of weights that are needed."""
        self.weights = np.array([np.random.uniform(-1, 1) for f in range(n)])
        self.bias = np.random.uniform(-1, 1)
        self.rate = 1

    def transfer(self, sample):
        c = self.bias + np.dot(sample[:-1], self.weights)
        return c

    def activator(self, c):
        if c > 0:
            return 1
        else:
            return 0

    def learn(self, vector):
        for _, sample in vector.iterrows():
            y = self.activator(self.transfer(sample))

            if y != sample[-1]:
                w = 1  # call to jet another function
                b = 2  # call to jet another function

            else:
                pass


v = {'0': {565: 1, 670: 1, 72: 1, 898: 1, 1773: 1},
     '1': {565: -0.761397898, 670: 1.8618260619999998, 72: 1.4408856630000002,
           898: -2.472684622, 1773: 1.0753508809999999},
     '2': {565: -1.060793281, 670: 1.8221998209999999, 72: 1.7182657719999999,
           898: -1.699168086, 1773: 4.293891907},
     '3': {565: 0, 670: 0, 72: 0, 898: 0, 1773: 1}}

learning_data = pd.DataFrame(v)
print(learning_data)
x = Perzeptron(2)
x.learn(learning_data.loc[:, '1':'3'])

推荐阅读