不能在 Python 类中使用方法列表,它会破坏深度复制。解决方法?

发布于 2024-10-31 14:30:08 字数 2653 浏览 2 评论 0原文

我正在尝试通过实现 k 最近邻分类器来了解有关 Python 的更多信息。 KNN 的工作原理是根据与现有数据最相似的数据来标记新数据。因此,对于给定的数据表,您尝试确定 3 个最相似的点(如果 k = 3)并选择更频繁的标签。有不同的方法可以确定“相似性”,即某种距离函数。所以你可以实现各种距离函数(余弦距离、曼哈顿距离、欧几里德距离等)并选择你想要的。

我正在尝试制作一些东西,让我可以轻松地交换距离函数,而无需执行案例,到目前为止我的解决方案是仅存储对方法的引用列表。这很棒,但是它在深度复制上中断了,我想弄清楚如何修复我的实现,或者在不需要做案例和让深度复制工作之间找到一个折衷方案。

这是我的配对类

class DataTable:

    def __init__(self, filename,TrueSymbol,FalseSymbol):
        self.t = self.parseCSV(filename)
        self.TrueSymbol = TrueSymbol
        self.FalseSymbol = FalseSymbol
        # This is the problem line of code
        self.distList = [self.euclideanDistance,
                            self.manhattanDistance,
                            self.cosineDistance]

    def nearestNeighbors(self,entry,k=None,distanceMetric=None):
        """
        distanceMetrics you can choose from:
        0 = euclideanDistance
        1 = manhattanDistance
        2 = cosineDistance
        """
        if distanceMetric == None:
            distanceFunction = self.euclideanDistance
        else:
            self.distList[distanceMetric]
        # etc..

    def euclideanDistance(self,entry):
        pass
    def manhattanDistance(self,entry):
        pass
    def cosineDistance(self,entry):
        pass

    # open up that csv
    def parseCSV(self,filename):
        pass

这是调用它的代码 导入 deepcopytestDS import copy

data = deepcopytestDS.DataTable("ionosphere.data","g","b")
deepCopy = copy.deepcopy(data) # crash.

这是调用堆栈

>>> deepCopy = copy.deepcopy(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "/usr/lib/python2.6/copy.py", line 292, in _deepcopy_inst
    state = deepcopy(state, memo)
  File "/usr/lib/python2.6/copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "/usr/lib/python2.6/copy.py", line 255, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/usr/lib/python2.6/copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "/usr/lib/python2.6/copy.py", line 228, in _deepcopy_list
    y.append(deepcopy(a, memo))
  File "/usr/lib/python2.6/copy.py", line 189, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "/usr/lib/python2.6/copy.py", line 323, in _reconstruct
    y = callable(*args)
  File "/usr/lib/python2.6/copy_reg.py", line 93, in __newobj__
    return cls.__new__(cls, *args)
TypeError: instancemethod expected at least 2 arguments, got 0

这次崩溃意味着什么,是否有某种方法可以使深度复制工作而不摆脱交换距离函数的快捷方式?

I'm trying to learn more about Python by implementing a k-Nearest Neighbor classifier. KNN works by labeling the new data based on what existing data its most similar to. So for a given table of data, you try to determine the 3 most similar points (if k = 3) and pick whatever label is more frequent. There's different ways you determine "similarity", some kind of distance function. So you can implement various distance functions (cosine distance, manhattan, euclidean, etc) and pick whichever you want.

I'm trying to make something that lets me swap distance functions in and out easily without doing cases, and the solution I have so far is to just store a list of references to methods. This is great, but it breaks on deepcopy and I want to figure out how to either fix my implementation or come up with a compromise between not needing to do cases and getting deepcopy to work.

Here's my paired down class

class DataTable:

    def __init__(self, filename,TrueSymbol,FalseSymbol):
        self.t = self.parseCSV(filename)
        self.TrueSymbol = TrueSymbol
        self.FalseSymbol = FalseSymbol
        # This is the problem line of code
        self.distList = [self.euclideanDistance,
                            self.manhattanDistance,
                            self.cosineDistance]

    def nearestNeighbors(self,entry,k=None,distanceMetric=None):
        """
        distanceMetrics you can choose from:
        0 = euclideanDistance
        1 = manhattanDistance
        2 = cosineDistance
        """
        if distanceMetric == None:
            distanceFunction = self.euclideanDistance
        else:
            self.distList[distanceMetric]
        # etc..

    def euclideanDistance(self,entry):
        pass
    def manhattanDistance(self,entry):
        pass
    def cosineDistance(self,entry):
        pass

    # open up that csv
    def parseCSV(self,filename):
        pass

And here's the code that calls it
import deepcopytestDS
import copy

data = deepcopytestDS.DataTable("ionosphere.data","g","b")
deepCopy = copy.deepcopy(data) # crash.

Here's the callstack

>>> deepCopy = copy.deepcopy(data)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python2.6/copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "/usr/lib/python2.6/copy.py", line 292, in _deepcopy_inst
    state = deepcopy(state, memo)
  File "/usr/lib/python2.6/copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "/usr/lib/python2.6/copy.py", line 255, in _deepcopy_dict
    y[deepcopy(key, memo)] = deepcopy(value, memo)
  File "/usr/lib/python2.6/copy.py", line 162, in deepcopy
    y = copier(x, memo)
  File "/usr/lib/python2.6/copy.py", line 228, in _deepcopy_list
    y.append(deepcopy(a, memo))
  File "/usr/lib/python2.6/copy.py", line 189, in deepcopy
    y = _reconstruct(x, rv, 1, memo)
  File "/usr/lib/python2.6/copy.py", line 323, in _reconstruct
    y = callable(*args)
  File "/usr/lib/python2.6/copy_reg.py", line 93, in __newobj__
    return cls.__new__(cls, *args)
TypeError: instancemethod expected at least 2 arguments, got 0

What does this crash mean, and is there some way to make deepcopy work without getting rid of my shortcut for swapping distance functions?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

风流物 2024-11-07 14:30:08

这是一个错误: http://bugs.python.org/issue1515

您可以将其放在顶部您的文件以使其正常工作:

import copy
import types

def _deepcopy_method(x, memo):
    return type(x)(x.im_func, copy.deepcopy(x.im_self, memo), x.im_class)
copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method

It was a bug: http://bugs.python.org/issue1515

You can put this at the top of your file to make it work:

import copy
import types

def _deepcopy_method(x, memo):
    return type(x)(x.im_func, copy.deepcopy(x.im_self, memo), x.im_class)
copy._deepcopy_dispatch[types.MethodType] = _deepcopy_method
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文