首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用数据挖掘技术确定肿瘤的良恶性决策树

用数据挖掘技术确定肿瘤的良恶性决策树
EN

Stack Overflow用户
提问于 2022-11-25 04:47:27
回答 1查看 64关注 0票数 0

我必须从.csv文件中读取患者数据,并使用决策树根据每个患者正在读取的数据来确定肿瘤是良性还是恶性。

我真的在为如何开始这件事而挣扎。到目前为止,我已经编写了从.csv文件读取数据并将数据存储到向量中的代码,如下所示,这些代码分布在几个头文件和cpp文件上。

根据我收集的信息,我可以创建一个父决策类,然后我要处理的每个属性都是子类。不确定这是否有意义。请让我知道。

下面,您将找到我要处理的属性以及一个图形树,它显示了如何确定肿瘤是良性的还是恶性的,我需要将其作为代码的基础。我还将包含.csv文件的一个小示例。

请给我一些指导,作为我如何做这件事。我对指针表示法有很大的困难。如有任何指导,将不胜感激。

代码语言:javascript
复制
CSVLine.h
代码语言:javascript
复制
#ifndef CSVLINE_H
#define CSVLINE_H

#include <string>
#include <sstream>
#include <vector>

using namespace std;

class CSVLine
{
private:
    vector<string> data;

public:
    CSVLine() {}
    CSVLine(const CSVLine& other)
    {
        data = other.data;
    }

    CSVLine operator = (const CSVLine& other)
    {
        data = other.data;
    }
    ~CSVLine() {}

    void parse(string line, char delimiter = ',');
    string getString(int columnNumber);
    int getInt(int columnNumber);
};

#endif
代码语言:javascript
复制
CSVLine.cpp
代码语言:javascript
复制
#include "CSVLine.h"

void CSVLine::parse(string line, char delimiter)
{
    stringstream inLine(line);

    string tempColumn = "";

    while (getline(inLine, tempColumn, delimiter))
    {
        data.push_back(tempColumn);
    }
}

string CSVLine::getString(int columnNumber)
{
    return data[columnNumber];
}

int CSVLine::getInt(int columnNumber)
{
    return atoi(data[columnNumber].c_str());
}
代码语言:javascript
复制
CSVReader.h
代码语言:javascript
复制
#ifndef CSVREADER_H
#define CSVREADER_H

#include <vector>
#include <fstream>
#include <iostream>

#include "CSVLine.h"

using namespace std;

class CSVReader
{
public:
    CSVReader() {}

    vector<CSVLine> read(string fileName);
};

#endif
代码语言:javascript
复制
CSVReader.cpp
代码语言:javascript
复制
#include "CSVReader.h"

vector<CSVLine> CSVReader::read(string fileName)
{
    ifstream inputFile;
    vector<CSVLine> lines;
    inputFile.open(fileName.c_str());
    string line = "";

    while (getline(inputFile, line))
    {
        CSVLine csvLine;
        csvLine.parse(line);
        lines.push_back(csvLine);
    }

    return lines;
}
代码语言:javascript
复制
EN

回答 1

Stack Overflow用户

发布于 2022-11-25 05:41:45

我会这么做的。

首先,我会将特性表转换为高阶宏

代码语言:javascript
复制
#define FOREACH_FEATURE(OP)                     \
  OP(1, SampleCodeNumber, int, -1)              \
  OP(2, ClumpThickness, int, -1)                \
  OP(3, UniformityOfCellSize, int, -1)
// Fill in the rest of the table of features here yourself

然后,我将使用这个宏生成一个具有像这样的病人所有特征的结构:

代码语言:javascript
复制
struct PatientData {
#define DECL_FEATURE(index, name, type, init) type name = init;
  FOREACH_FEATURE(DECL_FEATURE)
#undef DECL_FEATURE

  PatientData() {}
  
  PatientData(CSVLine& src) {
#define READ_FEATURE(index, name, type, init) name = src.getInt(index-1);
    FOREACH_FEATURE(READ_FEATURE)
#undef READ_FEATURE
  }
};

然后,我将从一个PatientData对象构造一个CSVLine对象。

代码语言:javascript
复制
CSVLine line = ...;
PatientData patientData(line);

然后,我将将决策树作为嵌套的if-statements实现在patientData对象上:

代码语言:javascript
复制
if (patientData.UniformityOfCellSize <= 2) {
  // ...
} else {
  // ...
}

这将使您开始,但您需要完成和可能扩展FOREACH_FEATURE宏和实现决策树.

节点和指针方法

如果您不想像上面那样实现您的树,那么抛出上面的代码,然后执行以下操作。首先包括我们需要的几个文件,并实现一个Feature类:

代码语言:javascript
复制
#include <memory>
#include <functional>

struct Feature {
  int index1;
  int apply(CSVLine& line) const {return line.getInt(index1-1);}
};

并将特性表转换为Feature,如下所示:

代码语言:javascript
复制
Feature SampleCodeNumber{1};
Feature ClumpThickness{2};
Feature UniformityOfCellSize{3};
// Fill in the rest yourself

我们将使用一个std::function<bool(CSVLine)>来决定树中的分支:

代码语言:javascript
复制
typedef std::function<bool(CSVLine&)> BranchCondition;

重载Featuredouble的比较运算符以返回BranchCondition,可以灵活地表示BranchConditions:

代码语言:javascript
复制
#define DEF_FEATURE_OP(op) BranchCondition operator op (Feature f, double x) {return [f, x](CSVLine& line) {return f.apply(line) op x;};}
DEF_FEATURE_OP(<)
DEF_FEATURE_OP(<=)
DEF_FEATURE_OP(>)
DEF_FEATURE_OP(>=)
#undef DEF_FEATURE_OP

我们还需要声明分类的返回值:

代码语言:javascript
复制
enum class Severity {
  Benign, Malign
};

作为决策树的基类,我们声明

代码语言:javascript
复制
class PatientClassifier {
public:
  virtual Severity classify(CSVLine& p) const = 0;
  virtual ~PatientClassifier() {}
};

并将其与用于构造常量值的函数severity一起实现:

代码语言:javascript
复制
class ConstantClassifier : public PatientClassifier {
public:
  ConstantClassifier(Severity v) : _value(v) {}
  Severity classify(CSVLine&) const override {return _value;}
private:
  Severity _value;
};

std::shared_ptr<PatientClassifier> severity(Severity v) {
  return std::make_shared<ConstantClassifier>(v);
}

对于分支情况和一个函数branch

代码语言:javascript
复制
class BranchingClassifier : public PatientClassifier {
public:
  BranchingClassifier(
    BranchCondition f,
    const std::shared_ptr<PatientClassifier>& onTrue,
    const std::shared_ptr<PatientClassifier>& onFalse)
    : _f(f), _onTrue(onTrue), _onFalse(onFalse) {}
  
  Severity classify(CSVLine& p) const override {
    return (_f(p)? _onTrue : _onFalse)->classify(p);
  }
private:
  BranchCondition _f;
  std::shared_ptr<PatientClassifier> _onTrue;
  std::shared_ptr<PatientClassifier> _onFalse;
};

std::shared_ptr<PatientClassifier> branch(
  BranchCondition f,
  const std::shared_ptr<PatientClassifier>& onTrue,
  const std::shared_ptr<PatientClassifier>& onFalse) {
  return std::make_shared<BranchingClassifier>(f, onTrue, onFalse);
}

然后我们建造树就像

代码语言:javascript
复制
  auto decisionTree = branch(
    UniformityOfCellSize <= 2.0,
    severity(Severity::Benign),
    severity(Severity::Malign));

  CSVLine line;
  auto result = decisionTree->classify(line);

注意:您不需要为CSVLine定制复制构造函数和赋值操作符。getInt方法可以标记为const

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/74568450

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档