第一步实现:ETL的设计分三部分:数据抽取(Data Extraction)、数据的清洗转换(Data Transformation)、数据的加载(Data Loading).
构建一个数据容器类,其中包含转换后的MNIST手写数据。还实现了一个数据处理程序,该数据处理程序将提取并转换数据以供将来的算法实现使用。
#ifndef __DATA_H
#define __DATA_H#include <iostream>
#include <vector>
#include "stdint.h"
#include "stdio.h"// 数据类
class data
{std::vector<uint8_t>* feature_vector; // 特征向量uint8_t label; // 标签int enum_label; // 枚举标签 A->1, B->2, C->3, D->4, E->5, F->6, G->7, H->8, I->9, J->10public:data(); // 构造函数~data(); // 析构函数void set_feature_vector(std::vector<uint8_t> *); // 设置特征向量void append_to_feature_vector(uint8_t); // 向特征向量追加数据void set_label(uint8_t); // 设置标签void set_enum_label(int); // 设置枚举标签int get_feature_vector_size(); // 获取特征向量大小uint8_t get_label(); // 获取标签uint8_t get_enumerated_label(); // 获取枚举标签std::vector<uint8_t>* get_feature_vector(); // 获取特征向量};#endif
这段代码定义了一个名为 data
的类,用于处理特征向量和标签。首先,代码使用了头文件保护机制,通过 #ifndef
、#define
和 #endif
来防止重复包含头文件 data.hpp
。
在 data
类中,有三个私有成员变量:feature_vector
是一个指向 std::vector<uint8_t>
的指针,用于存储特征向量;label
是一个 uint8_t
类型的变量,用于存储标签;enum_label
是一个整数,用于存储枚举标签,注释中说明了不同字符对应的整数值(例如,A 对应 1,B 对应 2,依此类推)。
在公共成员函数部分,data
类提供了一些方法来操作和访问这些成员变量:
void set_feature_vector(std::vector<uint8_t> *)
:设置特征向量的指针。void append_to_feature_vector(uint8_t)
:向特征向量中追加一个uint8_t
类型的值。void set_label(uint8_t)
:设置标签。void set_enum_label(int)
:设置枚举标签。
此外,还有一些方法用于获取成员变量的值:
int get_feature_vector_size()
:获取特征向量的大小。uint8_t get_label()
:获取标签。uint8_t get_enumerated_label()
:获取枚举标签。std::vector<uint8_t>* get_feature_vector()
:获取特征向量的指针。
这些方法使得 data
类能够灵活地操作和访问特征向量和标签,适用于需要处理大量数据的场景。
#include "data.hpp"data::data(){feature_vector = new std::vector<uint8_t>;
}data::~data()
{delete feature_vector;
}void data::set_feature_vector(std::vector<uint8_t> *vect)
{feature_vector = vect;
}void data::append_to_feature_vector(uint8_t val)
{feature_vector->push_back(val);
}void data::set_label(uint8_t val)
{label = val;
}void data::set_enum_label(int val)
{enum_label = val;
}int data::get_feature_vector_size()
{return feature_vector->size();
}uint8_t data::get_label()
{return label;
}
uint8_t data::get_enumerated_label()
{return enum_label;
}std::vector<uint8_t>* data::get_feature_vector()
{return feature_vector;
}
这段代码实现了 data
类的构造函数、析构函数以及多个成员函数。首先,代码包含了头文件 data.hpp
,以确保类的声明可用。
构造函数 data::data()
初始化了 feature_vector
,为其分配了一个新的 std::vector<uint8_t>
对象。析构函数 data::~data()
则负责释放该内存,防止内存泄漏。
set_feature_vector
方法接受一个指向 std::vector<uint8_t>
的指针,并将其赋值给 feature_vector
。append_to_feature_vector
方法向 feature_vector
中追加一个 uint8_t
类型的值。
set_label
和 set_enum_label
方法分别设置 label
和 enum_label
的值。
get_feature_vector_size
方法返回 feature_vector
的大小。get_label
和 get_enumerated_label
方法分别返回 label
和 enum_label
的值。最后,get_feature_vector
方法返回 feature_vector
的指针。
总体来说,这段代码实现了 data
类的基本功能,使其能够管理和操作特征向量和标签。
2.处理数据
#ifndef __DATA_HANDLER_H
#define __DATA_HANDLER_H#include<fstream>
#include "stdint.h"
#include"data.hpp"
#include<vector>
#include<string>
#include<map>
#include<unordered_set>// 数据处理类
class data_handler
{std::vector<data *> *data_array; // 数据数组std::vector<data *> *training_data; // 训练数据std::vector<data *> *testing_data; // 测试数据std::vector<data *> *validation_data; // 验证数据int num_classes; // 类别数量int feature_vector_size; // 特征向量大小std::map<uint8_t, int> class_map; // 类别映射const double TRAIN_SET_PERCENTAGE = 0.75; // 训练集比例const double TEST_SET_PERCENTAGE = 0.20; // 测试集比例const double VALIDATION_SET_PERCENTAGE = 0.05; // 验证集比例public:data_handler(); // 构造函数~data_handler(); // 析构函数void read_feature_vector(std::string path); // 读取特征向量void read_label_vector(std::string path); // 读取标签向量void split_data(); // 分割数据void count_classes(); // 统计类别数量uint32_t convert_to_little_endian(const unsigned char* bytes); // 转换为小端序std::vector<data *> *get_training_data(); // 获取训练数据std::vector<data *> *get_testing_data(); // 获取测试数据std::vector<data *> *get_validation_data(); // 获取验证数据};#endif
这个类名为 data_handler
,用于处理数据集的读取、分割和分类等操作。以下是对该类的详细解释:
成员变量
-
std::vector<data *> *data_array
:- 指向一个
std::vector
容器的指针,该容器存储了所有的数据对象的指针。
- 指向一个
-
std::vector<data *> *training_data
:- 指向一个
std::vector
容器的指针,该容器存储了训练数据集的数据对象的指针。
- 指向一个
-
std::vector<data *> *testing_data
:- 指向一个
std::vector
容器的指针,该容器存储了测试数据集的数据对象的指针。
- 指向一个
-
std::vector<data *> *validation_data
:- 指向一个
std::vector
容器的指针,该容器存储了验证数据集的数据对象的指针。
- 指向一个
-
int num_classes
:- 存储数据集中类别的数量。
-
int feature_vector_size
:- 存储特征向量的大小。
-
std::map<uint8_t, int> class_map
:- 一个映射,用于将类别标签(
uint8_t
类型)映射到整数值。
- 一个映射,用于将类别标签(
-
const double TRAIN_SET_PERCENTAGE
:- 常量,表示训练数据集所占的比例,值为 0.75。
-
const double TEST_SET_PERCENTAGE
:- 常量,表示测试数据集所占的比例,值为 0.20。
-
const double VALIDATION_SET_PERCENTAGE
:- 常量,表示验证数据集所占的比例,值为 0.05。
构造函数和析构函数
-
data_handler()
:- 构造函数,用于初始化
data_handler
对象。
- 构造函数,用于初始化
-
~data_handler()
:- 析构函数,用于释放
data_handler
对象所占用的资源。
- 析构函数,用于释放
成员函数
-
void read_feature_vector(std::string path)
:- 从指定路径读取特征向量数据。
-
void read_label_vector(std::string path)
:- 从指定路径读取标签数据。
-
void split_data()
:- 将数据集分割为训练集、测试集和验证集。
-
void count_classes()
:- 统计数据集中各个类别的数量。
-
uint32_t convert_to_little_endian(const unsigned char* bytes)
:- 将字节数组转换为小端格式的
uint32_t
类型。
- 将字节数组转换为小端格式的
-
std::vector<data *> *get_training_data()
:- 返回指向训练数据集的指针。
-
std::vector<data *> *get_testing_data()
:- 返回指向测试数据集的指针。
-
std::vector<data *> *get_validation_data()
:- 返回指向验证数据集的指针。
总结
data_handler
类提供了一系列方法,用于读取数据、分割数据集、统计类别数量以及获取训练集、测试集和验证集。通过这些方法,可以方便地管理和处理数据集,适用于机器学习和数据分析等场景。