精华内容
下载资源
问答
  • 几乎所有的机器学习算法最后都归结为求解最优化问题,以达到我们想让算法达到...如何构造出一个合理的目标函数,是建立机器学习算法的关键,一旦目标函数确定,接下来就是求解最优化问题,这在数学上一般有现成的方案。
  • SVM如何通过点到超平面距离获得目标函数和约束函数?① 假设L1是其中一条过 +1 类支持向量且平行于 WX+b=0 的直线,L2 是过 -1 类支持向量且平行于 WX+b=0 的直线,L1 和 L2 就确定了这条马路的边边,L 是马路中线。...

    SVM如何通过点到超平面距离获得目标函数和约束函数?

    ① 假设L1是其中一条过 +1 类支持向量且平行于 WX+b=0 的直线,L2 是过 -1 类支持向量且平行于 WX+b=0 的直线,L1 和 L2 就确定了这条马路的边边,L 是马路中线。

    ② L 的形式是 WX+b=0,又因为 L1、L2 距离 L 是相等的,所有定义 L1 为 WX+b=1,L2 为 WX+b=-1。

    注:这两条平行线的方程右边既可以是 1 和 -1,也可以是 2 和 -2,或者任意非零常数 C 和 -C。规定 1 和 -1 只是为了方便,例如 2x+3y+1=0 和 4x+6y+2=0 是等价的,方程同乘一个常数后并不会改变。

    b5ab0716fdbc6891a730a617c6cbf3dc.png

    ③ 2d 是 L1 和 L2 这两条平行线之间的距离:

    ④ 目标是最大化几何间隔d,由于

    ,问题又转化成了最小化||W||。

    ⑤ 对于求 min||W||,通常会转化为求

    ,这里用平方后除以 2 这个形式是为了后面求解方便。

    ⑥ ||W|| 不可能无限小,因为还有限制条件:超平面正确分类,意味着点 i 到超平面的距离恒大于等于 d,即:

    ⑦ 两边同乘||W||,简化为:

    注:

    是因为 y 只有两个值,+1和-1。
    1. 如果第 i 个样本属于 +1 类别,则
      ,并且
      ,故两者相乘是大于0的。
    2. 如果第 i 个样本属于 -1 类别,则
      ,并且
      ,故两者相乘是大于0的。

    注:这意味着

    恒大于0,y 起到的作用就和绝对值一样。

    注:用 y 替换绝对值,是因为 y 是已知样本数据,也方便后面的公式求解。

    ⑧ 我们获得目标函数:

    65d7cb330208c9c212285bc2f9bac61c.png

    ⑨ 我们获得约束条件:

    94be2011eae5f36c7a5f3e4fc2437eeb.png

    Python基础积累(numpy)

    numpy生成随机数

    import numpy as np
    np.random.rand(3, 3)

    运行结果:

    array([[0.68537219, 0.54168828, 0.31736894],
    [0.74666141, 0.48711075, 0.03362492],
    [0.70282142, 0.0422297 , 0.25828402]])

    注:随机生成一个二维数组。

    np.random.rand(2, 3, 3)

    运行结果:

    array([[[0.06007194, 0.4339849 , 0.13609465],
    [0.37893364, 0.04192778, 0.68935534],
    [0.84097557, 0.69990864, 0.34211253]],
    [[0.00239661, 0.46886934, 0.65149633],
    [0.81336026, 0.89658351, 0.55632714],
    [0.45345776, 0.28813519, 0.65834964]]])

    注:随机生成一个三维数组。

    import numpy as np
    np.random.seed(0)   
    np.random.rand(5)

    运行结果:

    array([0.5488135 , 0.71518937, 0.60276338, 0.54488318, 0.4236548 ])

    注:seed()函数用于指定随机数生成时所用算法开始的整数值。

    注:如果使用相同的seed( )值,则每次生成的随即数都相同。如果不设置这个值,则系统根据时间来自己选择这个值,此时每次生成的随机数因时间差异而不同。

    注:np.random.rand(5)随机生成包含5个元素的浮点数组。

    np.random.seed(8)
    np.random.rand(5)

    运行结果:

    array([0.8734294 , 0.96854066, 0.86919454, 0.53085569, 0.23272833])

    注:设置的seed()值仅一次有效。

    "♥每天积累一点点♥"

    展开全文
  • 基于多目标函数的电网项目投资组合研究,杨海峰,崔莹莹,电网企业是国民经济的支柱型企业,国家对电网企业的投资也越来越大。面对国家的大力投资,如何确定电网项目的投资策略是关系企业
  • hook(钩子函数

    万次阅读 2019-06-10 09:52:41
    hook钩子: ...2)如何确定目标函数的地址及替换。 要素: 1)现有功能; 2)目标功能; 3)替换技术。 8.1 什么是Hook技术 还没有接触过Hook技术读者一定会对Hook一词感觉到特别的陌...

    hook钩子:

    使用技术手段在运行时动态的将额外代码依附现进程,从而实现替换现有处理逻辑或插入额外功能的目的。

    它的技术实现要点有两个:

    1)如何注入代码(如何将额外代码依附于现有代码中)。

    2)如何确定目标函数的地址及替换。

     

    要素:

    1)现有功能;

    2)目标功能;

    3)替换技术。

    8.1 什么是Hook技术

    还没有接触过Hook技术读者一定会对Hook一词感觉到特别的陌生,Hook英文翻译过来就是“钩子”的意思,那我们在什么时候使用这个“钩子”呢?我们知道,在Android操作系统中系统维护着自己的一套事件分发机制。应用程序,包括应用触发事件和后台逻辑处理,也是根据事件流程一步步地向下执行。而“钩子”的意思,就是在事件传送到终点前截获并监控事件的传输,像个钩子钩上事件一样,并且能够在钩上事件时,处理一些自己特定的事件。较为形象的流程如图8-1所示。

    Hook的这个本领,使它能够将自身的代码“融入”被勾住(Hook)的程序的进程中,成为目标进程的一个部分。我们也知道,在Android系统中使用了沙箱机制,普通用户程序的进程空间都是独立的,程序的运行彼此间都不受干扰。这就使我们希望通过一个程序改变其他程序的某些行为的想法不能直接实现,但是Hook的出现给我们开拓了解决此类问题的道路。当然,根据Hook对象与Hook后处理的事件方式不同,Hook还分为不同的种类,如消息Hook、API Hook等。

    8.1.1 Hook原理

    Hook技术无论对安全软件还是恶意软件都是十分关键的一项技术,其本质就是劫持函数调用。但是由于处于Linux用户态,每个进程都有自己独立的进程空间,所以必须先注入到所要Hook的进程空间,修改其内存中的进程代码,替换其过程表的符号地址。在Android中一般是通过ptrace函数附加进程,然后向远程进程注入so库,从而达到监控以及远程进程关键函数挂钩。

    Hook技术的难点,并不在于Hook技术,初学者借助于资料“照葫芦画瓢”能够很容易就掌握Hook的基本使用方法。如何找到函数的入口点、替换函数,这就涉及了理解函数的连接与加载机制。

    从Android的开发来说,Android系统本身就提供给了我们两种开发模式,基于Android SDK的Java语言开发,基于AndroidNDK的Native C/C++语言开发。所以,我们在讨论Hook的时候就必须在两个层面上来讨论。对于Native层来说Hook的难点其实是在理解ELF文件与学习ELF文件上,特别是对ELF文件不太了解的读者来说;对于Java层来说,Hook就需要了解虚拟机的特性与Java上反射的使用。

    8.1.1.1 Hook工作流程

    之前我们介绍过Hook的原理就是改变目标函数的指向,原理看起来并不复杂,但是实现起来却不是那么的简单。这里我们将问题细分为两个,一个是如何注入代码,另一个是如何注入动态链接库。

    注入代码我们就需要解决两个问题。

    • 需要注入的代码我们存放在哪里?
    • 如何注入代码?

    注入动态共享库我们也需要解决两个问题:

    • 我们不能只在自己的进程载入动态链接库,如何使进程附着上目标进程?
    • 如何让目标进程调用我们的动态链接库函数?

    这里我也不卖关子了,说一下目前对上述问题的解决方案吧。对于进程附着,Android的内核中有一个函数叫ptrace,它能够动态地attach(跟踪一个目标进程)、detach(结束跟踪一个目标进程)、peektext(获取内存字节)、poketext(向内存写入地址)等,它能够满足我们的需求。而Android中的另一个内核函数dlopen,能够以指定模式打开指定的动态链接库文件。对于程序的指向流程,我们可以调用ptrace让PC指向LR堆栈。最后调用,对目标进程调用dlopen则能够将我们希望注入的动态库注入至目标进程中。

    展开全文
  • Shark源码分析(四):目标函数及其优化我们之前反反复复地强调过,Shark的设计策略是:方法 = 模型 + 策略 + 算法。...在确定目标函数之后,我们还需要考虑的就是如何对其进行优化。在Shark中,将定义目标

    Shark源码分析(四):目标函数及其优化

    我们之前反反复复地强调过,Shark的设计策略是:方法 = 模型 + 策略 + 算法。这里的策略指的就是目标函数。我们的目标是从假设空间中选取最优的模型,需要考虑的是按照什么样的准则学习或选择最优的模型。选择一个好的目标函数形式,也是算法最终取得好的效果的一个重要组成部分。

    在确定了目标函数之后,我们还需要考虑的就是如何对其进行优化。在Shark中,将定义目标函数与对目标函数优化区分开来,分别定义了两个基类构成了两套继承体系。

    AbstractObjectiveFunction类

    该类是所有优化以及学习问题的目标函数的基类。对于那些需要有目标函数的算法都可以使用该类。因为一个目标函数不可能满足所有的需求,所以该类针对不同的优化方法提供了丰富的接口。该类定义在<include/Shark/ObjectiveFunctions/AbstractObjectiveFunction.h>

    template <typename PointType, typename ResultT>
    class AbstractObjectiveFunction :  public INameable{
    public:
        typedef PointType SearchPointType;
        typedef ResultT ResultType;
    
        typedef SearchPointType FirstOrderDerivative;
        struct SecondOrderDerivative {
            RealVector gradient;
            RealMatrix hessian;
        };
    
        /// \brief List of features that are supported by an implementation.
        enum Feature {
            HAS_VALUE                        =  1, 
            HAS_FIRST_DERIVATIVE             =  2, //是否能求一阶导数
            HAS_SECOND_DERIVATIVE            =  4, //是否能求二阶导数
            CAN_PROPOSE_STARTING_POINT       = 8, //函数能否提供搜索的起点
            IS_CONSTRAINED_FEATURE           =  16, //是否是一个带约束的优化问题
            HAS_CONSTRAINT_HANDLER           =  32, //能否提供可行域的信息
            CAN_PROVIDE_CLOSEST_FEASIBLE     = 64,
            IS_THREAD_SAFE     = 128    //能否在多线程环境下使用
        };
    
        SHARK_FEATURE_INTERFACE;
    
        //以下函数都是用于返回目标函数特征信息的
        bool hasValue()const{
            return m_features & HAS_VALUE;
        }
    
        bool hasFirstDerivative()const{
            return m_features & HAS_FIRST_DERIVATIVE;
        }
    
        bool hasSecondDerivative()const{
            return m_features & HAS_SECOND_DERIVATIVE;
        }
    
        bool canProposeStartingPoint()const{
            return m_features & CAN_PROPOSE_STARTING_POINT;
        }
    
        bool isConstrained()const{
            return m_features & IS_CONSTRAINED_FEATURE;
        }
    
        bool hasConstraintHandler()const{
            return m_features & HAS_CONSTRAINT_HANDLER;
        }
    
        bool canProvideClosestFeasible()const{
            return m_features & CAN_PROVIDE_CLOSEST_FEASIBLE;
        }
    
        bool isThreadSafe()const{
            return m_features & IS_THREAD_SAFE;
        }
    
        AbstractObjectiveFunction():m_evaluationCounter(0) {
            m_features |=HAS_VALUE;
        }
    
        virtual ~AbstractObjectiveFunction() {}
    
        virtual void init() {
            m_evaluationCounter=0;
        }
    
        virtual std::size_t numberOfVariables() const=0;
    
        virtual bool hasScalableDimensionality()const{
            return false;
        }
    
        /// \brief Adjusts the number of variables if the function is scalable.
        virtual void setNumberOfVariables( std::size_t numberOfVariables ){
            throw SHARKEXCEPTION("dimensionality of function is not scalable");
        }
    
        virtual std::size_t numberOfObjectives() const{
            return 1;
        }
        virtual bool hasScalableObjectives()const{
            return false;
        }
    
        /// \brief Adjusts the number of objectives if the function is scalable.
        virtual void setNumberOfObjectives( std::size_t numberOfObjectives ){
            throw SHARKEXCEPTION("dimensionality of function is not scaleable");
        }
    
        std::size_t evaluationCounter() const {
            return m_evaluationCounter;
        }
    
        AbstractConstraintHandler<SearchPointType> const& getConstraintHandler()const{
            if(m_constraintHandler == NULL)
                throw SHARKEXCEPTION("Objective Function does not have an constraint handler!");
            return *m_constraintHandler;
        }
    
        //判断一个搜索空间中的点是否是可行的
        virtual bool isFeasible( const SearchPointType & input) const {
            if(hasConstraintHandler()) return getConstraintHandler().isFeasible(input);
            if(isConstrained())
                throw SHARKEXCEPTION("[AbstractObjectiveFunction::isFasible] not overwritten, even though function is constrained");
            return true;
        }
    
        /// \brief If supported, the supplied point is repaired such that it satisfies all of the function's constraints.
        virtual void closestFeasible( SearchPointType & input ) const {
            if(!isConstrained()) return;
            if(hasConstraintHandler()) return getConstraintHandler().closestFeasible(input);
            SHARK_FEATURE_EXCEPTION(CAN_PROVIDE_CLOSEST_FEASIBLE);
        }
    
        virtual SearchPointType proposeStartingPoint()const {
            if(hasConstraintHandler()&& getConstraintHandler().canGenerateRandomPoint()){
                SearchPointType startingPoint;
                getConstraintHandler().generateRandomPoint(startingPoint);
                return startingPoint;
            }
            else{
                SHARK_FEATURE_EXCEPTION(CAN_PROPOSE_STARTING_POINT);
            }
        }
    
        //计算目标函数的输出
        virtual ResultType eval( const SearchPointType & input )const {
            SHARK_FEATURE_EXCEPTION(HAS_VALUE);
        }
    
        //注意到该类也同样是重载了括号运算符
        ResultType operator()( const SearchPointType & input ) const {
            return eval(input);
        }
    
        //计算目标函数的一阶或是二阶导数
        virtual ResultType evalDerivative( const SearchPointType & input, FirstOrderDerivative & derivative )const {
            SHARK_FEATURE_EXCEPTION(HAS_FIRST_DERIVATIVE);
        }
    
        virtual ResultType evalDerivative( const SearchPointType & input, SecondOrderDerivative & derivative )const {
            SHARK_FEATURE_EXCEPTION(HAS_SECOND_DERIVATIVE);
        }
    
    protected:
        mutable std::size_t m_evaluationCounter; //不太明白这个变量是干啥的
        AbstractConstraintHandler<SearchPointType> const* m_constraintHandler;//这个类之后会介绍
    
        /// This function quries the propabilities of the handler and sts up the flags accordingly
        void announceConstraintHandler(AbstractConstraintHandler<SearchPointType> const* handler){
            SHARK_CHECK(handler != NULL, "[AbstractObjectiveFunction::AnnounceConstraintHandler] Handler is not allowed to be NULL");
            m_constraintHandler = handler;
            m_features |= IS_CONSTRAINED_FEATURE;
            m_features |= HAS_CONSTRAINT_HANDLER;
            if(handler->canGenerateRandomPoint())
                m_features |=CAN_PROPOSE_STARTING_POINT;
            if(handler->canProvideClosestFeasible())
                m_features |= CAN_PROVIDE_CLOSEST_FEASIBLE;
        }
    };
    
    //针对单输出和多输出的目标函数进行了特化
    typedef AbstractObjectiveFunction< RealVector, double > SingleObjectiveFunction;
    typedef AbstractObjectiveFunction< RealVector, RealVector > MultiObjectiveFunction;

    AbstractConstraintHandler类

    注意到之前在目标函数的特征中有IS_CONSTRAINED_FEATURE这样一个特征,表示该目标函数是不是一个带约束的函数。而Constraint Handler 就是一个对带约束的优化问题提供可行域信息的类。至少它能够判断出一个数据点是否是一个可行解,或者下一个可行解是什么。该类定义在<include/Shark/ObjectiveFunctions/AbstractConstraintHandler.h>

    template<class SearchPointType>
    class AbstractConstraintHandler{
    public:
        enum Feature {
            CAN_PROVIDE_CLOSEST_FEASIBLE     = 1,
            IS_BOX_CONSTRAINED = 2,  //是否是BoxConstraintHandler的实例
            CAN_GENERATE_RANDOM_POINT = 4  //是否可以在可行域中产生一个随机点
        };
        SHARK_FEATURE_INTERFACE;
    
        virtual ~AbstractConstraintHandler(){}
    
        bool canProvideClosestFeasible()const{
            return m_features & CAN_PROVIDE_CLOSEST_FEASIBLE;
        }
    
        bool isBoxConstrained()const{
            return m_features &IS_BOX_CONSTRAINED;
        }
    
        bool canGenerateRandomPoint()const{
            return m_features & CAN_GENERATE_RANDOM_POINT;
        }
    
        virtual void generateRandomPoint( SearchPointType & startingPoint )const {
            SHARK_FEATURE_EXCEPTION(CAN_GENERATE_RANDOM_POINT);
        }
    
        /// \brief Returns true if the point is in the feasible Region.
        virtual bool isFeasible(SearchPointType const&)const = 0;
        virtual void closestFeasible(SearchPointType& )const{
            SHARK_FEATURE_EXCEPTION(CAN_PROVIDE_CLOSEST_FEASIBLE );
        }
    
    };

    ErrorFunction类

    这是定义真正目标函数的类。定义在<include/Shark/ObjectiveFunctions/ErrorFunction.h>中,具体的实现在<include/Shark/ObjectiveFunctions/Impl/ErrorFunction.ini>中。

    //注意到该类是单输出目标函数的版本
    class ErrorFunction : public SingleObjectiveFunction
    {
    public:
        //注意到这个构造函数的参数类型
        //AbstractLoss类其实是定义了目标函数的具体形式
        //这个类其实是将训练数据集、具体的模型、目标函数三者综合起来的类
        template<class InputType, class LabelType, class OutputType>
        ErrorFunction(
            LabeledData<InputType, LabelType> const& dataset,
            AbstractModel<InputType,OutputType>* model, 
            AbstractLoss<LabelType, OutputType>* loss   
        ){
            m_regularizer = 0;
            //non sequential models can be parallelized
            if(model->isSequential() || SHARK_NUM_THREADS == 1)
                mp_wrapper.reset(new detail::ErrorFunctionImpl<InputType,LabelType,OutputType>(dataset,model,loss));
            else
                mp_wrapper.reset(new detail::ParallelErrorFunctionImpl<InputType,LabelType,OutputType>(dataset,model,loss));
    
            this -> m_features = mp_wrapper -> features();
        }
    
        ErrorFunction(const ErrorFunction& op):mp_wrapper(op.mp_wrapper->clone()){
            this -> m_features = mp_wrapper -> features();
        }
    
        ErrorFunction& operator=(const ErrorFunction& op){
            ErrorFunction copy(op);
            swap(copy.mp_wrapper,mp_wrapper);
            return *this;
        }
    
        std::string name() const
        { return "ErrorFunction"; }
    
        void setRegularizer(double factor, SingleObjectiveFunction* regularizer){
            m_regularizer = regularizer;
            m_regularizationStrength = factor;
        }
    
        SearchPointType proposeStartingPoint()const {
            return mp_wrapper -> proposeStartingPoint();
        }
        std::size_t numberOfVariables()const{
            return mp_wrapper -> numberOfVariables();
        }
    
        double eval(RealVector const& input) const{
            ++m_evaluationCounter;
            double value = mp_wrapper -> eval(input);
            if(m_regularizer)
                value += m_regularizationStrength * m_regularizer->eval(input);
            return value;
        }
    
        ResultType evalDerivative( const SearchPointType & input, FirstOrderDerivative & derivative ) const{
            ++m_evaluationCounter;
            double value = mp_wrapper -> evalDerivative(input,derivative);
            if(m_regularizer){
                FirstOrderDerivative regularizerDerivative;
                value += m_regularizationStrength * m_regularizer->evalDerivative(input,regularizerDerivative);
                noalias(derivative) += m_regularizationStrength*regularizerDerivative;
            }
            return value;
        }
    
        friend void swap(ErrorFunction& op1, ErrorFunction& op2){
            using std::swap;
            swap(op1.mp_wrapper,op2.mp_wrapper);
            swap(op1.m_features,op2.m_features);
        }
    
    private:
        boost::scoped_ptr<detail::FunctionWrapperBase > mp_wrapper;//FunctionWrapperBase类之后会介绍
        SingleObjectiveFunction* m_regularizer; //目标函数可能拥有的一个正则化项
        double m_regularizationStrength; //正则化项之前的权值
    };

    ErrorFunctionImpl类

    在ErrorFunction类中,你可能会发现,在函数实际计算的时候,都是通过调用mp_wrapper这个成员变量来实现的。那我们就有必要来探究下这个类了。

    FunctionWrapperBase类定义在<include/Shark/ObjectiveFunctions/Impl/FunctionWrapperBase.h>中。

    class FunctionWrapperBase: public SingleObjectiveFunction{
    public:
        virtual FunctionWrapperBase* clone()const = 0;
    };

    可以看到这个类真的是非常的简单,只包含有一个纯虚函数。那我们就只有去寻找其子类来看看具体的实现了。它有一个子类ErrorFunctionImpl,其定义在<include/Shark/ObjectiveFunctions/Impl/ErrorFunction.ini>,与ErrorFunction类的实现在同一个文件中,那么这个类的含义就显而易见了。

    template<class InputType, class LabelType,class OutputType>
    class ErrorFunctionImpl:public FunctionWrapperBase{
    public:
        ErrorFunctionImpl(
            LabeledData<InputType, LabelType> const& dataset,
            AbstractModel<InputType,OutputType>* model, 
            AbstractLoss<LabelType, OutputType>* loss
        ):mep_model(model),mep_loss(loss),m_dataset(dataset){
            SHARK_ASSERT(model!=NULL);
            SHARK_ASSERT(loss!=NULL);
    
            if(mep_model->hasFirstParameterDerivative() && mep_loss->hasFirstDerivative())
                m_features|=HAS_FIRST_DERIVATIVE;
            m_features|=CAN_PROPOSE_STARTING_POINT;
        }
    
        std::string name() const
        { return ""; }
    
        //由于是要对模型的参数进行求解,这里的起始点自然就是模型的参数
        //返回的是模型的参数向量
        SearchPointType proposeStartingPoint() const{
            return mep_model->parameterVector();
        }
    
        std::size_t numberOfVariables() const{
            return mep_model->numberOfParameters();
        }
    
        FunctionWrapperBase* clone()const{
            return new ErrorFunctionImpl<InputType,LabelType,OutputType>(*this);
        }
    
        //对于模型来说,eval是计算模型对于输入数据的输出值
        //这里需要计算目标函数的输出值
        double eval(RealVector const& input) const {
            //首先需要将已经计算好的模型参数重新赋到模型中去
            mep_model->setParameterVector(input);
    
            return evalPointSet();
        }
    
        double evalPointSet() const {
            std::size_t dataSize = m_dataset.numberOfElements();
            typedef typename LabeledData<InputType,LabelType>::const_batch_reference const_reference;
    
            typename Batch<OutputType>::type prediction;
            double error = 0.0;
            BOOST_FOREACH(const_reference batch,m_dataset.batches()){
                mep_model->eval(batch.input, prediction);
                error += mep_loss->eval(batch.label, prediction);
            }
            //这里返回的是平均误差
            return error/dataSize;
        }
    
        //该函数不仅会计算目标函数的梯度,还要根据目标函数的梯度计算模型本身中定义的梯度,后一点才是主要的,因为需要根据它来进行模型参数的调整
        ResultType evalDerivative( const SearchPointType & point, FirstOrderDerivative & derivative ) const {
            //同样是需要将新的参数传递到模型中去
            mep_model->setParameterVector(point);
            return evalDerivativePointSet(derivative);
        }
    
        ResultType evalDerivativePointSet( FirstOrderDerivative & derivative ) const {
            typedef typename LabeledData<InputType,LabelType>::const_batch_reference const_reference;
            std::size_t dataSize = m_dataset.numberOfElements();
            derivative.resize(mep_model->numberOfParameters());
            derivative.clear();
    
            typename Batch<OutputType>::type prediction;
            RealVector dataGradient(mep_model->numberOfParameters());
            typename Batch<OutputType>::type errorDerivative;
    
            double error=0.0;
            boost::shared_ptr<State> state = mep_model->createState();
            BOOST_FOREACH(const_reference batch,m_dataset.batches()){
                // calculate model output for the batch as well as the derivative
                mep_model->eval(batch.input, prediction,*state);
    
                // calculate error derivative of the loss function
                error += mep_loss->evalDerivative(batch.label, prediction,errorDerivative);
    
                //calculate the gradient using the chain rule
                mep_model->weightedParameterDerivative(batch.input,errorDerivative,*state,dataGradient);
                derivative+=dataGradient;
            }
            error /= dataSize;
            derivative /= double(dataSize);
            return error;
        }
    
    private:
        //这三个变量与ErrorFunction构造函数中的三个参数是对应的
        AbstractModel<InputType, OutputType>* mep_model;
        AbstractLoss<LabelType, OutputType>* mep_loss;
        LabeledData<InputType, LabelType> m_dataset;
    };

    还有一个与之同级的类ParallelErrorFunctionImpl,它们的实现大致是一样的,只不过Parallel这个类是利用了多线程来加速对梯度的计算。可以通过判断模型是否是序列化的,来决定调用这两个类中的哪一个。

    AbstractOptimizer类

    对于一个已经定义好的目标函数,需要有一个方法来求解该优化问题。AbstractOptimizer类就是这一类方法的基类。该类定义在<include/Shark/Algorithms/AbstractOptimizer.h>中。

    template <typename PointType, typename ResultT, typename SolutionTypeT>
    class AbstractOptimizer : public INameable, public ISerializable {
    public:
        typedef PointType SearchPointType;
        typedef ResultT ResultType;
        typedef SolutionTypeT SolutionType;
        typedef AbstractObjectiveFunction<PointType,ResultType> ObjectiveFunctionType;
    
        //根据目标函数的一些特征来得到该类的一些特征
        enum Feature {
            REQUIRES_VALUE              =  1, //是否能用该类进行求值,目标函数中的HAS_VALUE标志必须被设置
            REQUIRES_FIRST_DERIVATIVE   =  2, //是否需要计算一阶导数,目标函数中的HAS_FIRST_DERIVATIVE必须被设置
            REQUIRES_SECOND_DERIVATIVE  =  4, //与上一条一样
            CAN_SOLVE_CONSTRAINED           =  8, //可以解决有约束的目标函数,目标函数中的IS_CONSTRAINED_FEATURE需要被设置
            REQUIRES_CLOSEST_FEASIBLE       = 16 //如果目标函数是有约束的,那么它必须提供一种方法来构造出一个近似的解,目标函数中的CAN_PROVIDE_CLOSEST_FEASIBLE要被设置
        };
    
        SHARK_FEATURE_INTERFACE;
    
        bool requiresValue()const{
            return features()& REQUIRES_VALUE;
        }
    
        bool requiresFirstDerivative()const{
            return features()& REQUIRES_FIRST_DERIVATIVE;
        }
        bool requiresSecondDerivative()const{
            return features()& REQUIRES_SECOND_DERIVATIVE;
        }
        bool canSolveConstrained()const{
            return features()& CAN_SOLVE_CONSTRAINED;
        }
        bool requiresClosestFeasible()const{
            return features()& REQUIRES_CLOSEST_FEASIBLE;
        }
    
        virtual ~AbstractOptimizer() {}
    
        //给定一个目标函数来进行初始化
        virtual void init( ObjectiveFunctionType& function ) = 0;
    
        //进行一步迭代来优化目标函数
        virtual void step( ObjectiveFunctionType const& function ) = 0;
    
        //返回当前的最优解
        virtual SolutionType const& solution() const = 0; 
    
    protected:
        void checkFeatures (ObjectiveFunctionType const& objectiveFunction){
            //test first derivative
            if( (m_features & REQUIRES_FIRST_DERIVATIVE) &
                !(objectiveFunction.features() & ObjectiveFunctionType::HAS_FIRST_DERIVATIVE)
            )throw SHARKEXCEPTION("[ "+name()+" ] requires first derivative");
            //test second derivative
            if( (m_features & REQUIRES_SECOND_DERIVATIVE) &
                !(objectiveFunction.features() & ObjectiveFunctionType::HAS_SECOND_DERIVATIVE)
            )throw SHARKEXCEPTION("[ "+name()+" ] requires second derivative");
    
            //test whether the function can be evaluated
            if( (m_features & REQUIRES_VALUE) &
                !(objectiveFunction.features() & ObjectiveFunctionType::HAS_VALUE)
            )throw SHARKEXCEPTION("[ "+name()+" ] requires the value of the function");
    
            //test for constrains
            if( !(m_features & CAN_SOLVE_CONSTRAINED) &
                (objectiveFunction.features() & ObjectiveFunctionType::IS_CONSTRAINED_FEATURE)
            )throw SHARKEXCEPTION("[ "+name()+" ] can not solve constrained functions");
    
            //test for closest feasible in constrained functions
            if( (objectiveFunction.features() & ObjectiveFunctionType::IS_CONSTRAINED_FEATURE) &
                !(objectiveFunction.features() & ObjectiveFunctionType::CAN_PROVIDE_CLOSEST_FEASIBLE) &
                (m_features & REQUIRES_CLOSEST_FEASIBLE)
            )throw SHARKEXCEPTION("[ "+name()+" ] requires closest feasible for constrained functions");
        }
    };

    对于不同的目标函数形式,可能需要不同的优化方法。主要还是重写step函数,来完成主要的优化工作。

    类中返回的最优化的结果由SolutionType类进行封装。该类定义在<include/Shark/Core/ResultSets.h>中。

    template<class SearchPointT, class ResultT>
    struct ResultSet{
        typedef SearchPointT SearchPointType; 
        typedef ResultT ResultType; 
        ResultSet(){}
        ResultSet(ResultType const& value, SearchPointType const& point)
        :point(point),value(value){}
    
        SearchPointType point;//表示当前模型的参数值
        ResultType value;//表示当前目标函数的输出值
    
        template<typename Archive>
        void serialize( Archive & archive, const unsigned int /*version*/ ) {
            archive & point;
            archive & value;
        }
    
        friend void swap(ResultSet& set1, ResultSet& set2){
            using std::swap;
            swap(set1.point,set2.point);
            swap(set1.value,set2.value);
        }
    };

    对于单输出的目标函数,对其SolutionType还做出了特化。

    template<class SearchPointTypeT>
    struct SingleObjectiveResultSet: public ResultSet<SearchPointTypeT,double>{
        typedef SearchPointTypeT SearchPointType;
        typedef double ResultType;
    
        SingleObjectiveResultSet(){}
        SingleObjectiveResultSet(double value, SearchPointType const& point)
        :ResultSet<SearchPointTypeT,double>(value, point){}
    
        friend bool operator<(SingleObjectiveResultSet const& op1, SingleObjectiveResultSet const& op2){
            return op1.value < op2.value;
        }
    };

    对于单输出目标函数的优化类也做出了特化。

    template<class PointType>
        class AbstractSingleObjectiveOptimizer: public AbstractOptimizer<PointType,double,SingleObjectiveResultSet<PointType> >{
        private:
            typedef AbstractOptimizer<PointType,double,SingleObjectiveResultSet<PointType> > base_type;
        public:
            typedef typename base_type::SearchPointType SearchPointType;
            typedef typename base_type::SolutionType SolutionType;
            typedef typename base_type::ResultType ResultType;
            typedef typename base_type::ObjectiveFunctionType ObjectiveFunctionType;
    
            //提供有两个版本的init函数,针对的是目标函数类能否给出一个起始的搜索点,如果不能,则可以手动指定
            virtual void init(ObjectiveFunctionType& function ){
                if(!(function.features() & ObjectiveFunctionType::CAN_PROPOSE_STARTING_POINT))
                    throw SHARKEXCEPTION( "[AbstractSingleObjectiveOptimizer::init] Objective function does not propose a starting point");
                init(function,function.proposeStartingPoint());
            }
    
            virtual void init(ObjectiveFunctionType& function, SearchPointType const& startingPoint)=0;
    
            ///returns the current solution of the optimizer
            virtual const SolutionType& solution() const{
                return m_best;
            }
    
        protected:
            ///current solution of the optimizer
            SolutionType m_best;
    };
    展开全文
  • 如何编写回调函数

    2015-03-11 04:54:40
    如何编写回调函数? 回调函数其实就是将某个特定接口的实现作为参数传入目标对象,让目标对象在适当的时候对齐进行调用。 Response接口包含了两个方法:success和fail,分别需要在请求成功和失败时调用,但是具体...
        

    如何编写回调函数?

    回调函数其实就是将某个特定接口的实现作为参数传入目标对象,让目标对象在适当的时候对齐进行调用。

    Response接口包含了两个方法:successfail,分别需要在请求成功和失败时调用,但是具体这两个方法需要做写什么事情,这在接口的定义中是无从知道的,因为这是根据每个发送请求的主体的具体情况而确定的。

    Request是发送请求类,是执行人物的主体,在其send(Response response)方法中,会接受一个Response接口的实现,并在请求完成后,根据请求的结果调用Response中相应的方法。

    CallbackSample是测试的主体,在main函数中,产生一个Request对象,然后调用其send方法,同时传入一个匿名类实现了Response接口。

    java/**
     * Created by findingsea on 3/11/15.
     */
    public interface Response {
    
        void success();
    
        void fail();
    }
    
    
    java/**
     * Created by findingsea on 3/11/15.
     */
    public class Request {
    
        public void send(Response response) {
            System.out.println("Send Request");
    
            response.fail();
        }
    }
    
    
    java/**
     * Created by findingsea on 3/11/15.
     */
    public class CallbackSample {
    
        public static void main(String[] args) {
            Request request = new Request();
            request.send(new Response() {
                @Override
                public void success() {
                    System.out.println("Request Success");
                }
    
                @Override
                public void fail() {
                    System.out.println("Request Fail");
                }
            });
        }
    }
    
    

    以下是输出:

    javaSend Request
    Request Fail
    
    展开全文
  • 我的目标:让中国的大学生走出校门的那一刻就已经具备这些office技能,让职场人士能高效使用office为其...但有时,我们需要自定义的函数中参数的个数是不确定的那该怎么办?看下图中,我们经常使用的sum函数,它的...
  • (条款m26里说明了如何把这种方法封装起来以便很容易地添加到任何类中,“my article on counting objects”提供了对这个技术的另外一些改进)设想在一个军事应用程序里,有一个表示敌人目标的类: 代码 ...
  • 这个成员被初始化为0,在构造函数里加1,析构函数里减1。(条款m26里说明了如何把这种方法封装起来以便很容易地添加到任何类中,“my article on counting objects”提供了对这个技术的另外一些改进)  设想在一个...
  • (条款m26里说明了如何把这种方法封装起来以便很容易地添加到任何类中,“my article on counting objects”提供了对这个技术的另外一些改进)设想在一个军事应用程序里,有一个表示敌人目标的类:class enemyt
  • 这个成员被初始化为0,在构造函数里加1,析构函数里减1。(条款M26里说明了如何把这种方法封装起来以便很容易地添加到任何类中,“my article on counting objects”提供了对这个技术的另外一些改进) 设想在一个...
  • 1.在吴恩达的CS229的讲义的第四页直接给出参数迭代公式 2.在UFLDL中反向传导算法一节也是直接给出的公式 为什么损失函数沿着梯度下降体现成参数更新的时候是这样...设想下有个函数,你的目标是:找到一个参数 使得...
  • 这个成员被初始化为0,在构造函数里加1,析构函数里减1。(条款m26里说明了如何把这种方法封装起来以便很容易地添加到任何类中,“my article on counting objects”提供了对这个技术的另外一些改进) 设想在一个...
  • 目标图片如下: %生成解析式,第一幅图 x = linspace(0,6,25); y1 = sin(x/3); y2 = sin(x-pi/4); y3=sin(x); %画图 figure subplot(121);%产生两幅图像容纳空间; plot(x,y1,’–go’,x,y2,’:r*’,x,y3,’-.bs’)%...
  • 前言 ​ 本菜鸡开始了学习C语言的旅途。用这个来记录一下上课所学到的一些东西。仅作为自己的一个学习笔记。里面的内容也只是我对学到的东西的一些...确定函数功能,要完成的目标确定函数名 如:求一个数组的最大
  • 我用指针实现了一个可以生成不确定数目的Point点集的构造函数(C++实现),现在需要在另一个类中用到随机数目的点集作为Data类成员变量(点集用来记录坐标),Data类是用来存储目标轨迹,点集用来记录目标的轨迹...
  • 图象从纹理图象空间映射到帧缓冲图象空间(映射需要重新构造纹理图像,这样就会造成应用到多边形上的图像失真),这时就可用glTexParmeteri()函数确定如何把纹理象素映射成像素. glTexParameteri(int target, int ...
  • Hook技术

    2019-10-03 14:38:09
    hook钩子: 使用技术手段在运行时动态的将额外代码依附现进程,从而...2)如何确定目标函数的地址及替换。 要素: 1)现有功能; 2)目标功能; 3)替换技术。 http://www.epubit.com.cn/book/onlinech...
  • matlab中linprog函数解线性规划方程

    千次阅读 2019-04-24 20:15:55
    三、构建目标函数 四、确定约束条件 建立好线性规划方程之后,紧接着而来的就是如何解方程,我们使用 matlab中的 linprog函数来求解: x=linprog(c,A,b,Aeq,beq,lb,ub) 而在matlab中使用matlab 标准的格式 ...
  • 机器学习中,一般都是找到适合的代价函数来构建目标函数,然后用优化算法进行代价函数的最小化。这就涉及到一个关键的内容,如何确定适合的代价函数,不仅要考虑求解,还要考虑对问题的适用性。 本次只列出分类学习...
  • JavaScript函数柯里化

    2020-12-08 23:27:03
    我们如何来实现一个自动的柯里化的函数呢? <pre><code>javascript var currying = function(fn) { var args = []; return function() { if (arguments.length === 0) { return fn....
  • 1 row in set, 1 warning ...2. found_rows() 函数是语句级别的存储,有很大的不确定性,所以在 MySQL 主从架构里,语句级别的行级格式下,从机数据可能会不准确。不过行记录格式改为 ROW 就 OK。所以最大的缺点...
  • 深度学习目标检测

    2020-12-30 19:29:14
    怎么选择每层的激活函数、怎么初始化权重矩阵、怎么选择损失函数、怎么确定最小化的目标函数(就是损失函数) 如何选择分类器,如何选择正则化项 生成模型 P?X” 和判别模型 P?YjX” 将传统的检测方法中的多步骤,...
  • 简介和目标 导致.NET代码性能下降的重要因素之一是内存消耗。许多开发人员只是主要用执行时间来确定.NET应用程序的性能瓶颈。只测量执行时间并不清楚知道性能问题之所在。好,要说的和要做的一个最大任务就是知道...
  • .net 最佳实践一:监测.net代码中的高内存消耗函数 .net 最佳实践一:监测.net代码中的高内存消耗函数 <br />简介和目标 导致.NET 代码性能下降的重要因素之一是内存消耗。许多开发人员只是主要用...

空空如也

空空如也

1 2 3 4 5 ... 17
收藏数 323
精华内容 129
关键字:

如何确定目标函数