Shark源码分析(三):数据预处理之正则化
在机器学习算法中,获取训练数据后首先要做的不是将输入投入训练方法中进行学习,而是应该对数据进行预处理。预处理过程输出数据的质量能够对之后算法的结果起着至关重要的作用。预处理过程含有非常多的操作,在我目前阅读代码的过程中只碰到了正则化这一过程。那我们就先来讨论正则化,如果之后再碰到了其他的方法再补充。
Shark将对输入数据进行正则化的模型也看作是一个线性模型。Shark给出了两种正则化的方法,分别是NormalizeComponentsUnitInterval, NormalizeComponentsUnitVariance。对于这两种不同的正则化方法有两个不同的trainer(联系上一篇博客的内容)进行训练。
第一种方法是将每一维度的特征都缩小到 [0,1] 范围内,这对于特征值是有界的情况来说是有效的。而第二种方法是将每一维度的方差都调整到1。对于『将均值变为0』这一操作来说是可选的。如果不包含这一操作,那么这一方法对于高维度的稀疏特征向量来说是有效的。
Normalizer类
该类定义在<include/shark/Models/Normalizer.h>
文件中。
其与普通线性模型的不同之处在于:
- 输入与输出的维度必须是相同的
- 对于每一维度需要单独进行计算
template <class DataType = RealVector>
class Normalizer : public AbstractModel<DataType, DataType>
{
protected:
RealVector m_A; //权值向量
RealVector m_b; //偏置向量 bool m_hasOffset; //表示是否需要偏置向量
public:
typedef AbstractModel<DataType, DataType> base_type;
typedef Normalizer<DataType> self_type;
typedef typename base_type::BatchInputType BatchInputType;
typedef typename base_type::BatchOutputType BatchOutputType;
Normalizer()
{ }
Normalizer(const self_type& model)
: m_A(model.m_A)
, m_b(model.m_b)
, m_hasOffset(model.m_hasOffset)
{ }
Normalizer(std::size_t dimension, bool hasOffset = false)
: m_A(dimension, dimension)
, m_b(dimension)
, m_hasOffset(hasOffset)
{ }
Normalizer(RealVector diagonal)
: m_A(diagonal)
, m_hasOffset(false)
{ }
Normalizer(RealVector diagonal, RealVector vector)
: m_A(diagonal)
, m_b(vector)
, m_hasOffset(true)
{ }
std::string name() const
{ return "Normalizer"; }
friend void swap(const Normalizer& model1, const Normalizer& model2)
{
std::swap(model1.m_A, model2.m_A);
std::swap(model1.m_b, model2.m_b);
std::swap(model1.m_hasOffset, model2.m_hasOffset);
}
const self_type operator = (const self_type& model)
{
m_A = model.m_A;
m_b = model.m_b;
m_hasOffset = model.m_hasOffset;
}
boost::shared_ptr<State> createState() const
{
return boost::shared_ptr<State>(new EmptyState());
}
//判断模型是否有被正确地初始化
bool isValid() const
{
return (m_A.size() != 0);
}
bool hasOffset() const
{
return m_hasOffset;
}
//返回权值向量
RealVector const& diagonal() const
{
SHARK_CHECK(isValid(), "[Normalizer::matrix] model is not initialized");
return m_A;
}
//返回偏置向量
RealVector const& offset() const
{
SHARK_CHECK(isValid(), "[Normalizer::vector] model is not initialized");
return m_b;
}