精华内容
下载资源
问答
  • 前言:dp/dip代表独立像素,dpi代表屏幕每英寸像素点的个数,px与dp的转换公式为: px = dp *(dpi / 160) 一:效果图 二:源代码 AnimationActivity: package com.example.duoyi.clientaidl; import android...

    前言:dp/dip代表独立像素,dpi代表屏幕每英寸像素点的个数,px与dp的转换公式为: px = dp *(dpi / 160)

    一:效果图

     

     二:源代码

     AnimationActivity:

    package com.example.duoyi.clientaidl;
    
    import android.animation.Animator;
    import android.animation.ObjectAnimator;
    import android.support.annotation.NonNull;
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.support.v7.widget.CardView;
    import android.support.v7.widget.LinearLayoutManager;
    import android.support.v7.widget.RecyclerView;
    import android.util.Log;
    import android.view.View;
    import android.widget.ImageView;
    
    import com.example.duoyi.AnimationAdapter;
    
    import java.util.ArrayList;
    import java.util.List;
    
    public class AnimationActivity extends AppCompatActivity {
    
        private static final int MAX_COUNT = 100;
        private static final String TAG = "AnimationActivity";
    
        RecyclerView rv;
        CardView cv;
        ImageView image;
        ObjectAnimator animator;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_animation);
    
            rv = findViewById(R.id.itemRv);
            cv = findViewById(R.id.expand);
            image = findViewById(R.id.insect);
    
            List<String> list = new ArrayList<>();
            for (int i = 0; i < MAX_COUNT; i++) {
                list.add("世界很美好,队形走起" + i);
            }
    
            LinearLayoutManager manager = new LinearLayoutManager(this);
            manager.setOrientation(RecyclerView.VERTICAL);
            AnimationAdapter adapter = new AnimationAdapter(list, this);
            rv.setLayoutManager(manager);
            rv.setAdapter(adapter);
            rv.scrollToPosition(list.size() - 1);
    
            image.setTranslationX(dp2px(50));
    
            //监听recyclerview的滑动事件
            rv.addOnScrollListener(new RecyclerView.OnScrollListener() {
                @Override
                public void onScrollStateChanged(RecyclerView recyclerView, int newState) {
                    super.onScrollStateChanged(recyclerView, newState);
                    Log.i(TAG, "current scroll state = " + newState);
                    image.setTranslationX(dp2px(-1));
                    if (newState == RecyclerView.SCROLL_STATE_IDLE) {
                        //第一种动画方式
    //                    image.animate()
    //                            .translationX(dp2px(50))
    //                            .setDuration(1500)
    //                            .start();
                        //第二种动画方式
                        animator = ObjectAnimator.ofFloat(image, "translationX",
                                dp2px(50));
                        animator.setDuration(1500);
                        animator.addListener(new Animator.AnimatorListener() {
                            @Override
                            public void onAnimationStart(Animator animation) {
    
                            }
    
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                //当图片发生点击时可以通过下面代码将图片复位到原来位置
                                //否则响应点击事件的图片可能会显示不全,不响应点击的忽略
                                //image.setTranslationX(dp2px(-1));
                            }
    
                            @Override
                            public void onAnimationCancel(Animator animation) {
    
                            }
    
                            @Override
                            public void onAnimationRepeat(Animator animation) {
    
                            }
                        });
                        animator.start();
                    }
                }
            });
    
            image.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    if (animator != null && animator.isRunning()) {
                        animator.cancel();
                    }
                    image.setImageResource(R.drawable.insect);
                }
            });
        }
    
        public int dp2px(int dip) {
            int dpi = getResources().getDisplayMetrics().densityDpi;
            return dip * (dpi / 160);
        }
    }
    

     activity_animator.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".AnimationActivity">
    
        <android.support.v7.widget.RecyclerView
            android:id="@+id/itemRv"
            android:layout_width="match_parent"
            android:layout_height="match_parent" />
    
        <android.support.v7.widget.CardView
            android:id="@+id/expand"
            android:layout_width="70dp"
            android:layout_height="30dp"
            android:layout_alignParentEnd="true"
            android:layout_marginTop="40dp"
            android:layout_marginEnd="30dp"
            app:cardBackgroundColor="#00000000"
            app:cardCornerRadius="15dp"
            app:cardElevation="0dp">
    
            <ImageView
                android:id="@+id/insect"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_gravity="end"
                android:scaleType="fitXY"
                android:src="@drawable/insect" />
    
        </android.support.v7.widget.CardView>
    
    
    </RelativeLayout>

    item_anim.xml:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="50dp"
        tools:context=".AnimationActivity">
    
        <TextView
            android:textSize="16sp"
            android:id="@+id/content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:text="hello World" />
    
    
    </RelativeLayout>

    AnimatorAdapter.java:

    package com.example.duoyi;
    
    import android.content.Context;
    import android.support.annotation.NonNull;
    import android.support.v7.widget.RecyclerView;
    import android.view.LayoutInflater;
    import android.view.View;
    import android.view.ViewGroup;
    import android.widget.TextView;
    
    import com.example.duoyi.clientaidl.AnimationActivity;
    import com.example.duoyi.clientaidl.R;
    
    import java.util.List;
    
    public class AnimationAdapter extends RecyclerView.Adapter<AnimationAdapter.AnimationViewHolder> {
    
        private List<String> list;
        private AnimationActivity context;
    
        public AnimationAdapter(List<String> list, AnimationActivity context) {
            this.list = list;
            this.context = context;
        }
    
        @Override
        public AnimationViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) {
            View view = LayoutInflater.from(context).inflate(R.layout.item_anim, viewGroup, false);
            return new AnimationViewHolder(view);
        }
    
        @Override
        public void onBindViewHolder(AnimationViewHolder holder, int position) {
            String content = list.get(position);
            holder.content.setText(content);
        }
    
        @Override
        public int getItemCount() {
            return list.size();
        }
    
        static class AnimationViewHolder extends RecyclerView.ViewHolder {
    
            TextView content;
    
            AnimationViewHolder(View view) {
                super(view);
                content = view.findViewById(R.id.content);
            }
        }
    }
    

    三:逻辑分析

    首先实现的效果是图片从做到右显示,那我们就使用平移动画,让图片从左到右移动消失,所以就在需要显示ImageView嵌套一层父容器,这样图片不断移出容器的范围内就会造成一种图片从左到右消失的效果 

     需求:父容器需设置为圆角显示

    如果需要实现ImageView的父容器为圆角布局的话,那就采用CardView,通过改变其属性

    app:cardCornerRadius="15dp"

    实现,不要使用其他诸如LinearLayout的父容器,设置其backgroud为一个圆角的drawable方式实现,这样的话内部的图片如果是矩形,即时你设置了父容器为圆角的,但是内部图片的显示还是会超出圆角的范围显示

    需求:图片消失的动画中响应点击事件,完整显示另一张图片

    这个实现我们首先需要在图片的点击事件中判断当前动画是否还是运行isRunning(),如果运行的话调用animator的cancel()方法取消动画,然后进行图片的位置的复位;如果我们不进行复位操作,此时ImageView的位置由于平移动画发生改变,当我们显示另一张图片可能会发生显示不全情况

    当动画终止(可能自然终止,也可能调用了动画的cance()方法),会响应其结束的监听方法,然后我们在该方法复位图片的位置即可:

    animator.addListener(new Animator.AnimatorListener() {
                            @Override
                            public void onAnimationStart(Animator animation) {
                            }
                            @Override
                            public void onAnimationEnd(Animator animation) {
                                //当图片发生点击时可以通过下面代码将图片复位到原来位置
                                //否则响应点击事件的图片可能会显示不全,不响应点击的忽略
                                //image.setTranslationX(dp2px(-1));
                            }
                            @Override
                            public void onAnimationCancel(Animator animation) {
                            }
                            @Override
                            public void onAnimationRepeat(Animator animation) {
                            }
                        });

    动画实现的两种方式:

    直接通过组件的animator()方式可以实现动画的链式调用,并且可以通过其withEndAction()或者withStartAction()方法在动画启动和结束的时候执行一些逻辑,该方式可以不需要调用其start()就能执行,因为其会在屏幕刷新的时候会自动执行 

                        //第一种动画方式
                        image.animate()
                                .translationX(dp2px(50))
                                .setDuration(1500)
                                .start();
    

    下面这种方式就是比较老实的方式,但是我们可以通过将其赋值给一个全局变量进行动画的操控(pause() cancel())

    animator = ObjectAnimator.ofFloat(image, "translationX",
                                dp2px(50));
    animator.setDuration(1500);
    animato.start();

     

     

     

     

     

     

     

     

     

    展开全文
  • 文本提示显示5秒后消失动画制作效果如上,配置如下: ...②旋转图标,代表生成中 ③添加元件的停留时间,与图标旋转时间相同 ④再次隐藏元件,逐渐消失消失的速度可以比显示的速度块 搞定整个动画 ...

     

    文本提示显示5秒后消失动画制作效果如上,配置如下:

    1、载入整个网页时,隐藏元件,元件名称“文件生成中tip”

    2、点击【导出CSV文件】按钮,添加鼠标点击时的动作显示-旋转-等待-隐藏动画

    ①显示元件,逐渐200ms

    ②旋转图标,代表生成中

    ③添加元件的停留时间,与图标旋转时间相同

    ④再次隐藏元件,逐渐消失,消失的速度可以比显示的速度块

    搞定整个动画

     

    展开全文
  • 本文分为三部分,第一部分主要直观的介绍深度学习中为什么使用梯度更新,第二部分主要介绍深度学习中梯度消失及爆炸的原因,第三部分对提出梯度消失及爆炸的解决方案。有基础的同鞋可以跳着阅读。 其中,梯度消失...

    前言

    本文主要深入介绍深度学习中的梯度消失和梯度爆炸的问题以及解决方案。本文分为三部分,第一部分主要直观的介绍深度学习中为什么使用梯度更新,第二部分主要介绍深度学习中梯度消失及爆炸的原因,第三部分对提出梯度消失及爆炸的解决方案。有基础的同鞋可以跳着阅读。
    其中,梯度消失爆炸的解决方案主要包括以下几个部分。

    - 预训练加微调
    - 梯度剪切、权重正则(针对梯度爆炸)
    - 使用不同的激活函数
    - 使用batchnorm
    - 使用残差结构
    - 使用LSTM网络
    

    第一部分:为什么要使用梯度更新规则


    在介绍梯度消失以及爆炸之前,先简单说一说梯度消失的根源—–深度神经网络和反向传播。目前深度学习方法中,深度神经网络的发展造就了我们可以构建更深层的网络完成更复杂的任务,深层网络比如深度卷积网络,LSTM等等,而且最终结果表明,在处理复杂任务上,深度网络比浅层的网络具有更好的效果。但是,目前优化神经网络的方法都是基于反向传播的思想,即根据损失函数计算的误差通过梯度反向传播的方式,指导深度网络权值的更新优化。这样做是有一定原因的,首先,深层网络由许多非线性层堆叠而来,每一层非线性层都可以视为是一个非线性函数 f(x)f(x)f(x)(非线性来自于非线性激活函数),因此整个深度网络可以视为是一个复合的非线性多元函数
    F(x)=fn(...f3(f2(f1(x)∗θ1+b)∗θ2+b)...)F(x) = {f_n}(...{f_3}({f_2}({f_1}(x)*{\theta _1} + b)*{\theta _2} + b)...)F(x)=fn(...f3(f2(f1(x)θ1+b)θ2+b)...) 我们最终的目的是希望这个多元函数可以很好的完成输入到输出之间的映射,假设不同的输入,输出的最优解是g(x)g(x)g(x) ,那么,优化深度网络就是为了寻找到合适的权值,满足Loss=L(g(x),F(x))Loss = L(g(x),F(x))Loss=L(g(x),F(x))取得极小值点,比如最简单的损失函数
    Loss=∣∣g(x)−f(x)∣∣22Loss = ||g(x)-f(x)||^2_2Loss=g(x)f(x)22,假设损失函数的数据空间是下图这样的,我们最优的权值就是为了寻找下图中的最小值点,对于这种数学寻找最小值问题,采用梯度下降的方法再适合不过了。
    这里写图片描述

    第二部分:梯度消失、爆炸

    梯度消失与梯度爆炸其实是一种情况,看接下来的文章就知道了。两种情况下梯度消失经常出现,一是在深层网络中,二是采用了不合适的损失函数,比如sigmoid。梯度爆炸一般出现在深层网络和权值初始化值太大的情况下,下面分别从这两个角度分析梯度消失和爆炸的原因。

    1.深层网络角度

    比较简单的深层网络如下:
    这里写图片描述
    图中是一个四层的全连接网络,假设每一层网络激活后的输出为fi(x)f_i(x)fi(x),其中iii为第iii层, xxx代表第iii层的输入,也就是第i−1i-1i1层的输出,fff是激活函数,那么,得出fi+1=f(fi∗wi+1+bi+1)f_{i+1}=f(f_i*w_{i+1}+b_{i+1})fi+1=f(fiwi+1+bi+1),简单记为fi+1=f(fi∗wi+1)f_{i+1}=f(f_i*w_{i+1})fi+1=f(fiwi+1)
    BP算法基于梯度下降策略,以目标的负梯度方向对参数进行调整,参数的更新为w←w+Δww \leftarrow w+\Delta www+Δw,给定学习率α\alphaα,得出Δw=−α∂Loss∂w\Delta w=-\alpha \frac{\partial Loss}{\partial w}Δw=αwLoss。如果要更新第二隐藏层的权值信息,根据链式求导法则,更新梯度信息:
    Δw2=∂Loss∂w2=∂Loss∂f4∂f4∂f3∂f3∂f2∂f2∂w2\Delta w_2=\frac{\partial Loss}{\partial w_2}=\frac{\partial Loss}{\partial f_4}\frac{\partial f_4}{\partial f_3}\frac{\partial f_3}{\partial f_2}\frac{\partial f_2}{\partial w_2}Δw2=w2Loss=f4Lossf3f4f2f3w2f2,很容易看出来∂f2∂w2=∂f∂(f1∗w2)f1\frac{\partial f_2}{\partial w_2}=\frac{\partial f}{\partial (f_1*w_2)}f_1w2f2=(f1w2)ff1,即第二隐藏层的输入。
    所以说,∂f4∂f3×w4\frac{\partial f_4}{\partial f_3} \times w4f3f4×w4就是对激活函数进行求导,如果此部分大于1,那么层数增多的时候,最终的求出的梯度更新将以指数形式增加,即发生梯度爆炸,如果此部分小于1,那么随着层数增多,求出的梯度更新信息将会以指数形式衰减,即发生了梯度消失。如果说从数学上看不够直观的话,下面几个图可以很直观的说明深层网络的梯度问题1^11(图片内容来自参考文献1):

    注:下图中的隐层标号和第一张全连接图隐层标号刚好相反。
    图中的曲线表示权值更新的速度,对于下图两个隐层的网络来说,已经可以发现隐藏层2的权值更新速度要比隐藏层1更新的速度慢

    这里写图片描述

    	那么对于四个隐层的网络来说,就更明显了,第四隐藏层比第一隐藏层的更新速度慢了两个数量级:
    

    这里写图片描述

    总结:从深层网络角度来讲,不同的层学习的速度差异很大,表现为网络中靠近输出的层学习的情况很好,靠近输入的层学习的很慢,有时甚至训练了很久,前几层的权值和刚开始随机初始化的值差不多。因此,梯度消失、爆炸,其根本原因在于反向传播训练法则,属于先天不足,另外多说一句,Hinton提出capsule的原因就是为了彻底抛弃反向传播,如果真能大范围普及,那真是一个革命。

    2.激活函数角度

    其实也注意到了,上文中提到计算权值更新信息的时候需要计算前层偏导信息,因此如果激活函数选择不合适,比如使用sigmoid,梯度消失就会很明显了,原因看下图,左图是sigmoid的损失函数图,右边是其导数的图像,如果使用sigmoid作为损失函数,其梯度是不可能超过0.25的,这样经过链式求导之后,很容易发生梯度消失,sigmoid函数数学表达式为:sigmoid(x)=11+e−xsigmoid(x)=\frac{1}{1+e^{-x}}sigmoid(x)=1+ex1
    sigmoid函数sigmoid函数导数

    同理,tanh作为激活函数,它的导数图如下,可以看出,tanh比sigmoid要好一些,但是它的导数仍然是小于1的。tanh数学表达为:
    

    tanh(x)=ex−e−xex+e−xtanh(x)=\frac{e^x-e^{-x}}{e^x+e^{-x}}tanh(x)=ex+exexex

    这里写图片描述

    第三部分:梯度消失、爆炸的解决方案


    2.1 方案1-预训练加微调

    此方法来自Hinton在2006年发表的一篇论文,Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。

    2.2 方案2-梯度剪切、正则

    梯度剪切这个方案主要是针对梯度爆炸提出的,其思想是设置一个梯度剪切阈值,然后更新梯度的时候,如果梯度超过这个阈值,那么就将其强制限制在这个范围之内。这可以防止梯度爆炸。

    注:在WGAN中也有梯度剪切限制操作,但是和这个是不一样的,WGAN限制梯度更新信息是为了保证lipchitz条件。
    

    另外一种解决梯度爆炸的手段是采用权重正则化(weithts regularization)比较常见的是l1l1l1正则,和l2l2l2正则,在各个深度框架中都有相应的API可以使用正则化,比如在tensorflowtensorflowtensorflow中,若搭建网络的时候已经设置了正则化参数,则调用以下代码可以直接计算出正则损失:

    regularization_loss = tf.add_n(tf.losses.get_regularization_losses(scope='my_resnet_50'))
    

    如果没有设置初始化参数,也可以使用以下代码计算l2l2l2正则损失:

        l2_loss = tf.add_n([tf.nn.l2_loss(var) for var in tf.trainable_variables() if 'weights' in var.name])
    
    

    正则化是通过对网络权重做正则限制过拟合,仔细看正则项在损失函数的形式:
    Loss=(y−WTx)2+α∣∣W∣∣2Loss=(y-W^Tx)^2+ \alpha ||W||^2Loss=(yWTx)2+αW2
    其中,α\alphaα是指正则项系数,因此,如果发生梯度爆炸,权值的范数就会变的非常大,通过正则化项,可以部分限制梯度爆炸的发生。

    注:事实上,在深度神经网络中,往往是梯度消失出现的更多一些。
    

    2.3 方案3-relu、leakrelu、elu等激活函数

    **Relu:**思想也很简单,如果激活函数的导数为1,那么就不存在梯度消失爆炸的问题了,每层的网络都可以得到相同的更新速度,relu就这样应运而生。先看一下relu的数学表达式:

    这里写图片描述

    其函数图像:

    这里写图片描述
    从上图中,我们可以很容易看出,relu函数的导数在正数部分是恒等于1的,因此在深层网络中使用relu激活函数就不会导致梯度消失和爆炸的问题。

    relu的主要贡献在于:

     -- 解决了梯度消失、爆炸的问题
     -- 计算方便,计算速度快
     -- 加速了网络的训练
    

    同时也存在一些缺点

    -- 由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决)
     -- 输出不是以0为中心的
    

    尽管relu也有缺点,但是仍然是目前使用最多的激活函数

    leakrelu
    leakrelu就是为了解决relu的0区间带来的影响,其数学表达为:leakrelu=max(k∗x,x)leakrelu=max(k*x,x)leakrelu=max(kx,x)其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来

    这里写图片描述

    leakrelu解决了0区间带来的影响,而且包含了relu的所有优点
    elu
    elu激活函数也是为了解决relu的0区间带来的影响,其数学表达为:这里写图片描述
    其函数及其导数数学形式为:

    这里写图片描述

    但是elu相对于leakrelu来说,计算要更耗时间一些

    2.4 解决方案4-batchnorm

    Batchnorm是深度学习发展以来提出的最重要的成果之一了,目前已经被广泛的应用到了各大网络中,具有加速网络收敛速度,提升训练稳定性的效果,Batchnorm本质上是解决反向传播过程中的梯度问题。batchnorm全名是batch normalization,简称BN,即批规范化,通过规范化操作将输出信号x规范化保证网络的稳定性。
    具体的batchnorm原理非常复杂,在这里不做详细展开,此部分大概讲一下batchnorm解决梯度的问题上。具体来说就是反向传播中,经过每一层的梯度会乘以该层的权重,举个简单例子:
    正向传播中f2=f1(wT∗x+b)f_2=f_1(w^T*x+b)f2=f1(wTx+b),那么反向传播中,∂f2∂w=∂f2∂f1x\frac {\partial f_2}{\partial w}=\frac{\partial f_2}{\partial f_1}xwf2=f1f2x,反向传播式子中有xxx的存在,所以xxx的大小影响了梯度的消失和爆炸,batchnorm就是通过对每一层的输出规范为均值和方差一致的方法,消除了xxx带来的放大缩小的影响,进而解决梯度消失和爆炸的问题,或者可以理解为BN将输出从饱和区拉倒了非饱和区。
    有关batch norm详细的内容可以参考我的另一篇博客:
    http://blog.csdn.net/qq_25737169/article/details/79048516

    2.5 解决方案5-残差结构

    残差结构说起残差的话,不得不提这篇论文了:Deep Residual Learning for Image Recognition,关于这篇论文的解读,可以参考知乎链接:https://zhuanlan.zhihu.com/p/31852747这里只简单介绍残差如何解决梯度的问题。
    事实上,就是残差网络的出现导致了image net比赛的终结,自从残差提出后,几乎所有的深度网络都离不开残差的身影,相比较之前的几层,几十层的深度网络,在残差网络面前都不值一提,残差可以很轻松的构建几百层,一千多层的网络而不用担心梯度消失过快的问题,原因就在于残差的捷径(shortcut)部分,其中残差单元如下图所示:
    这里写图片描述
    相比较于以前网络的直来直去结构,残差中有很多这样的跨层连接结构,这样的结构在反向传播中具有很大的好处,见下式:
    这里写图片描述
    式子的第一个因子 ∂loss∂xL\frac{\partial loss}{\partial {{x}_{L}}}xLloss 表示的损失函数到达 L 的梯度,小括号中的1表明短路机制可以无损地传播梯度,而另外一项残差梯度则需要经过带有weights的层,梯度不是直接传递过来的。残差梯度不会那么巧全为-1,而且就算其比较小,有1的存在也不会导致梯度消失。所以残差学习会更容易。

    注:上面的推导并不是严格的证明。
    

    2.6 解决方案6-LSTM

    LSTM全称是长短期记忆网络(long-short term memory networks),是不那么容易发生梯度消失的,主要原因在于LSTM内部复杂的“门”(gates),如下图,LSTM通过它内部的“门”可以接下来更新的时候“记住”前几次训练的”残留记忆“,因此,经常用于生成文本中。目前也有基于CNN的LSTM,感兴趣的可以尝试一下。

    这里写图片描述

    参考资料:

    1.《Neural networks and deep learning》
    2.《机器学习》周志华
    3. https://www.cnblogs.com/willnote/p/6912798.html
    4. https://www.zhihu.com/question/38102762
    5. http://www.jianshu.com/p/9dc9f41f0b29


    如果感兴趣,请关注微信公众号,还有更多精彩:
    这里写图片描述

    展开全文
  • 假设每一层网络激活后的输出为f_i(x), 其中i为第i层, x代表第iii层的输入,也就是第i-1层的输出,f是激活函数,那么可以得出: BP算法本身还是基于梯度下降策略,以目标的负梯度方向进行参数调整, 基于求导的链式...

    1、什么是梯度

    在微积分中,对多元函数的参数求∂偏导,把求得的各个参数的偏导数以向量形式写出来即为梯度。
    例如对于函数f(x,y),分别对x,y求偏导,求得的梯度向量就是 (∂f/∂x, ∂f/∂y)^T,简称 grad f(x,y),或者▽f(x,y)。相对于的,在点(x_0,y_0)处的梯度就是 (∂f/∂x_0, ∂f/∂y_0)^T, 或者记做 ▽f(x_0,y_0)。

    2、梯度的意义

    从几何的角度上讲,就是函数变化增加最快的方向。或者说,沿着梯度的方向更容易找到函数的最大值,反过来说沿着梯度相反的方向更容易找到函数的最小值,这就奠定了后面在求解损失函数的最小值时,可以使用梯度下架来求解参数。

    3、梯度下降法详解

    3.1、梯度下降的直观解释

    假设我么在一片山脉上,随机初始化一个坐标,那么沿着梯度的方向就是我们向最陡峭的方向前进一步,这个步长的大小由学习率控制。这样一步步的走下去,一直走到觉得我们已经到了山脚。当然这样走下去,有可能我们不能走到山脚,而是到了某一个局部的山峰低处。
    由此来看,使用梯度下降很有可能出现2种情况:

    • 跨步太小陷入局部最优无法自发
    • 跨步太大错过全局最优
      在这里插入图片描述

    3.2 这中间涉及到几个相关概念:

    • 步长(Learning rate):步长决定了在梯度下降迭代的过程中,每一步沿梯度负方向前进的长度。用上面下山的例子,步长就是在当前这一步所在位置沿着最陡峭最易下山的位置走的那一步的长度。
    • 特征(feature):指的是样本中输入部分,比如2个单特征的样本(𝑥(0),𝑦(0)),(𝑥(1),𝑦(1)),则第一个样本特征为𝑥(0),第一个样本输出为𝑦(0)。
    • 假设函数(hypothesis function):在监督学习中,为了拟合输入样本,而使用的假设函数,记为ℎ𝜃(𝑥)。比如对于单个特征的m个样本(𝑥(𝑖),𝑦(𝑖))(𝑖=1,2,…𝑚),可以采用拟合函数如下: ℎ𝜃(𝑥)=𝜃0+𝜃1𝑥。
    • 损失函数(loss function):为了评估模型拟合的好坏,通常用损失函数来度量拟合的程度。损失函数极小化,意味着拟合程度最好,对应的模型参数即为最优参数。在线性回归中,损失函数通常为样本输 出和假设函数的差取平方。比如对于m个样本(𝑥𝑖,𝑦𝑖)(𝑖=1,2,…𝑚),采用线性回归,损失函数为:𝐽(𝜃0,𝜃1)=∑𝑖=1𝑚(ℎ𝜃(𝑥𝑖)−𝑦𝑖)2 其中𝑥𝑖表示第i个样本特征,𝑦𝑖表示第i个样本对应的输出,ℎ𝜃(𝑥𝑖)为假设函数。

    4、梯度下降求解

    4.1、确定优化模型的假设函数和损失函数

    这里,我们以线性回归为例:假设函数表示为:ℎ𝜃(𝑥1,𝑥2,…𝑥𝑛)=𝜃0+𝜃1𝑥1+…+𝜃𝑛𝑥𝑛, 其中𝜃𝑖 (i = 0,1,2… n)为模型参数,𝑥𝑖 (i = 0,1,2… n)为每个样本的n个特征值。
    这个表示可以简化,我们增加一个特征𝑥0=1 ,这样ℎ𝜃(𝑥0,𝑥1,…𝑥𝑛)=∑_𝑖=0-𝑛(𝜃_i*𝑥_𝑖)。
    那么它对应的损失函数为:
    在这里插入图片描述

    4.2、相关参数初始化

    • 初始化参数矩阵 (𝜃0,𝜃1…,𝜃𝑛)
    • 算法终止距离𝜀
    • 步长𝛼
      在没有任何先验知识的时候,一般将所有的𝜃初始化为0, 将步长初始化为1。在调优的时候再优化。

    4.3、算法过程

    1. 确定当前位置的损失函数梯度,对于θ_j, 它当前的梯度表示为:
      在这里插入图片描述
    2. 用户步长乘以损失函数的梯度,得到当前位置的下降距离,即:
      在这里插入图片描述
    3. 确定是否所有的𝜃𝑖,梯度下降的距离都小于𝜀,如果小于𝜀则算法终止,当前所有的𝜃𝑖(i=0,1,…n)即为最终结果。否则进入步骤4…
    4. 更新所有的𝜃,对于𝜃𝑖,其更新表达式如下。更新完毕后继续转入步骤1.
      在这里插入图片描述

    5、梯度下降法调优:

    1. 步长(学习率)的选择。在前面的算法描述中,我提到取步长为1,但是实际上取值取决于数据样本,可以多取一些值,从大到小,分别运行算法,看看迭代效果,如果损失函数在变小,说明取值有效,否则要增大步长。前面说了。步长太大,会导致迭代过快,甚至有可能错过最优解。步长太小,迭代速度太慢,很长时间算法都不能结束。所以算法的步长需要多次运行后才能得到一个较为优的值。
    2. 参数初始化的选择。初始值不同,获得的最小值也有可能不同,因此梯度下降求得的只是局部最小值;当然如果损失函数是凸函数则一定是最优解。由于有局部最优解的风险,需要多次用不同初始值运行算法,关键损失函数的最小值,选择损失函数最小化的初值。
    3. 特征数据归一化。由于样本不同特征的取值范围不一样,可能导致迭代很慢,为了减少特征取值的影响,可以对特征数据归一化,也就是对于每个特征x,求出它的期望𝑥⎯⎯⎯和标准差std(x),然后转化为:
      在这里插入图片描述
      这样特征的新期望为0,新方差为1,迭代速度可以大大加快。

    6、梯度下降法的所有变种:

    1. 批量梯度下降法 Batch Gradient Descent
    2. 随机梯度下降法 Stochastic Gradient Descent
    3. 小批量梯度下降法 mini-batch Gradient Descent。他结合了上述2种方案的优点

    7、如何跳出局部极小值

    1. 使用SGD或者 MBGB
    2. 加入冲量 Momentum来冲出局部极小值。上一时刻的速度和当前时刻的梯度(加速度)共同作用的结果。
    3. 以多组不同的初始化参数值来初始化模型参数,按照标准方法训练完成后,取其中误差最小的解作为最终参数
    4. 目前绝大多数训练算法在碰到无论是鞍点或者局部最小值点的时候,它的学习率已经非常小了,所以会陷入非全局最优解。可在优化过程的末尾,放大学习率,让训练算法强行跳出当前的鞍点或者局部最小点

    8、梯度消失/梯度爆炸

    8.1、什么是梯度消失和梯度爆炸?它为什么会发生?

    在典型的BP中,基于求导的链式法则,需要对激活函数进行求导。而有些激活函数求导之后的最大值 < 1 或者 > 1,那么在多层的网络结构中导数值的连续相乘会导致求出的梯度更新以指数的形式减小或者增加(趋向于0和∞)。这属于BP的先天缺陷,

    8.1.1、从激活函数的角度而言,我们看看常用的激活函数图像和他们的导数图像:

    tanh和它的导数图像如下:偏导后的值都是 <=1
    在这里插入图片描述
    sigmod:
    在这里插入图片描述
    如果使用sigmoid作为损失函数,其梯度是不可能超过0.25的,这样经过链式求导之后,很容易发生梯度消失

    8.1.2、从实际的模型角度来看,我们以一个4层全连接层网络为例:

    在这里插入图片描述
    假设每一层网络激活后的输出为f_i(x), 其中i为第i层, x代表第iii层的输入,也就是第i-1层的输出,f是激活函数,那么可以得出:
    在这里插入图片描述
    BP算法本身还是基于梯度下降策略,以目标的负梯度方向进行参数调整, 基于求导的链式法则:
    在这里插入图片描述
    在公式中,∂f4/∂f3即时对激活函数求导,实际训练中网络层数远大于4层,如果此时的激活函数是 sigmod或者tanh,求导后的偏导值必 <=1, 所以本身 ▽w是无限趋近于0的,即“梯度消失”

    8.2、解决方案是什么?

    1. 预训练加微调,先逐层每次只训练一层隐节点,再利用BP进行全局训练:Hinton为了解决梯度的问题,提出采取无监督逐层训练方法,其基本思想是每次训练一层隐节点,训练时将上一层隐节点的输出作为输入,而本层隐节点的输出作为下一层隐节点的输入,此过程就是逐层“预训练”(pre-training);在预训练完成后,再对整个网络进行“微调”(fine-tunning)。Hinton在训练深度信念网络(Deep Belief Networks中,使用了这个方法,在各层预训练完成后,再利用BP算法对整个网络进行训练。此思想相当于是先寻找局部最优,然后整合起来寻找全局最优,此方法有一定的好处,但是目前应用的不是很多了。
    2. 梯度的剪切和正则,本身主要解决梯度爆炸问题。
      – 梯度剪切:为梯度设置一个剪切阈值,如果超过,那么将其强制限制再这个范围之内。
      – 权重正则化:最为常见的是L1正则和L2正则。正则化是通过对网络权重做正则限制过拟合,表现形式为:Loss=(y−W^T*x)^2+α∣∣W∣∣^2
    // 若搭建网络的时候已经设置了正则化参数,则调用以下代码可以直接计算出正则损失:
    regularization_loss = tf.add_n(tf.losses.get_regularization_losses(scope='my_resnet_50'))
    
    // 如果没有设置初始化参数,也可以使用以下代码计算L2正则损失:
    regularization_loss = tf.add_n([tf.nn.l2_loss(var) for var in tf.trainable_variables() if 'weights' in var.name])
    
    1. 使用relue、leakrelu、elu等激活函数
      在这里插入图片描述
      relu函数有一些问题:由于负数部分恒为0,会导致一些神经元无法激活(可通过设置小学习率部分解决)。这时候可以使用leakrelu函数来解决:
      在这里插入图片描述
      其数学表达为:leakrelu=max(k∗x,x) 其中k是leak系数,一般选择0.01或者0.02,或者通过学习而来

    elu函数也能解决relu的0区间问题:
    在这里插入图片描述
    在这里插入图片描述

    1. 使用BN算法,通过对每一层的输出规范为均值和方差一致的方法,消除了x带来的放大缩小的影响,进而解决梯度消失和爆炸的问题,或者可以理解为BN将输出从饱和区拉倒了非饱和区 (参考:http://note.youdao.com/noteshare?id=199931798c93f6c3e683f57c6716c505)
    2. 使用残差结构 , (残差详解:https://zhuanlan.zhihu.com/p/31852747)
      在这里插入图片描述
    3. 使用LSTM (long-short term memory network)。lstm不那么容易发生梯度消失,因为其内部具有复杂的“门结构”,如下图,LSTM通过它内部的“门”可以接下来更新的时候“记住”前几次训练的”残留记忆“,因此,经常用于生成文本中。目前也有基于CNN的LSTM。下面简介LSTM如何记住前几次训练的残留记忆:
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      最后一个单元产生输出:Ot是什么都没忘的结果 与新控制参数组合产生输出

    爸爸们赏点,交电费
    在这里插入图片描述

    附:

    1、三维图片生成代码

    # -*- coding:UTF-8 -*-
    
    """
    @Description: 
    @Author: zjf
    @Date: 2019/12/26 15:39
    """
    
    from mpl_toolkits.mplot3d import Axes3D
    import numpy as np
    from matplotlib import pyplot as plt
    
    fig = plt.figure()
    ax = Axes3D(fig)
    x = np.arange(-0.1 * np.pi, 2 * np.pi, 0.2)
    y = np.arange(-0.5 * np.pi, 2 * np.pi, 0.2)
    X, Y = np.meshgrid(x, y)  # 网格的创建,这个是关键
    Z = np.sin(X) * np.cos(Y)
    plt.xlabel('x')
    plt.ylabel('y')
    ax.plot_surface(X, Y, Z, rstride=1, cstride=1, cmap='rainbow')
    plt.show()
    

    参考:

    1、刘建平大佬总结 https://www.cnblogs.com/pinard/p/5970503.html
    2、https://blog.csdn.net/qq_25737169/article/details/78847691
    3、https://cloud.tencent.com/developer/article/1374163
    4、ResNet残差:https://zhuanlan.zhihu.com/p/31852747

    展开全文
  • 梯度消失和梯度爆炸情况详解

    万次阅读 2018-08-18 12:15:28
    本文分为三部分,第一部分主要直观的介绍深度学习中为什么使用梯度更新,第二部分主要介绍深度学习中梯度消失及爆炸的原因,第三部分对提出梯度消失及爆炸的解决方案。有基础的同鞋可以跳着阅读。  其中,梯度消失...
  • 我做了一个简单的fragment界面,主要是输入ID,然后向服务器查询内容后赋值回原来的界面上的textview,但是在运行的时候发生了一个奇怪的问题,一部分的textview消失了,具体很难描述,以下是整个过程的描述 ...
  • 手指触摸且有一定的滑动值,会显示线条九宫格,且线条跟随图片的大小动态改变,始终分割图片为9等分,如果手指触摸停止,线条消失,再次滑动,线条则再次出现; 那么图片缩放时,需要一个缩放中心点,也就是...
  • 安卓图片处理Picasso的解析使用

    千次阅读 2016-01-31 09:51:46
    Picasso其实是Android系统的图片下载和缓存类库,是Square开源的一个用于Android系统下载和缓存图片的项目。下面我们就来讲讲在Android开发中,Picasso有哪些特性及如何使用。简介: Picasso是Square公司开源的一...
  • openGL ES进阶教程(二)之全景图片

    千次阅读 2017-05-17 20:13:27
    全景又被称为3D实景,是一种新兴的富媒体技术,其与视频,声音,图片等传统的流媒体最大的区别是“可操作,可交互”。 全景分为虚拟现实和3D实景两种。虚拟现实是利用maya等软件,制作出来的模拟现实的场景,代表有...
  • [深度学习] 梯度消失与梯度爆炸的原因及解决方法

    万次阅读 多人点赞 2018-04-16 16:40:28
    前言本文主要深入介绍深度学习中的梯度消失和梯度爆炸的问题以及解决方案。本文分为三部分,第一部分主要直观的介绍深度学习中为什么使用梯度更新,第二部分主要介绍深度学习中梯度消失及爆炸的原因,第三部分对提出...
  • 欢迎加入学习交流QQ群:657341423 基础概念:图像通道、图像深度、RGB模式 ...# 参数cv2.IMREAD_GRAYSCALE 将图片生成灰度图像,将图像转化为单通道(8位灰度) # 参数cv2.IMREAD_ANYCOLOR 和...
  • 另外,代理转发成功并不代表可以跨域,需要给代理转发的返回数据写上返回头Access-Control-Allow-Origin: aaaa或者Access-Control-Allow-Origin: *。 注意你链接代码中的两个地方,首先是src = picurl.replace(“ ...
  • 那些正在消失的 Flash 网站

    千次阅读 2010-04-13 10:02:00
    灯箱,滚动新闻,富导航条,图片幻灯,这些效果曾经是 Flash 的专利,随着 Web 标准的推进,如今人们可以凭借几行 JavaScript 与 CSS 代码实现相同的效果,而 Web 标准的流行,使越来越多的 JavaScript 或 CSS ...
  • VS+opencv鼠标移动图片

    千次阅读 2016-07-15 10:55:04
    实现点击鼠标左键,可以拖动图片以显示感兴趣区域#include
  • 图片压缩

    千次阅读 2014-05-09 17:04:05
    这个字节的最高位用来表示透明度:0代表半透明,1代表不透明。那么全透明怎么表示呢?就用这个字节都是0来表示,因为全透明中RGB分量是没有意义的。这样的话会占用掉调色板的一个颜色,所以我的调色板最多只能允许...
  • 卷积神经网络进阶用法---残差网络如何解决梯度消失问题 前言 道路千万条,好用第一条 残差网络和跳跃连接 梯度消失问题 残差网络的原理 DenseNet网络 前言 我在三个月前写了关于卷积神经网络的系列文章,受到了...
  • 之前学的神经网络的原理、奇技淫巧什么的都忘的差不多了,正好这次有任务,顺道把之前的一些没理解透的问题重新理一理: 神经网络现在有很多类型了,每一种类型都是在之前...梯度消失的根源—–深度神经网络和反向...
  • 坦克大战图片

    千次阅读 2016-11-13 16:27:43
    坦克大战图片版本文转自:小易博客专栏。http://blog.csdn.NET/oldinaction坦克大战效果图: 注意事项: 1、ProperMrg类中props.load(ProperMgr.class.getClassLoader().getResourceAsStream(“config/tank....
  • 对象代表一个异步操作,有三种状态: Pending (进行中)、 Resolved (已完成,又称Fulfilled)和 Rejected (已失败)。只有异步操作的结果,可以决定当前是哪一种状态,任何其他操作都无法改变这个状态。这也是 ...
  • 苹果手机千般好,奈何数据消失掉。使用苹果手机时,你是不是也常遇到这种数据丢失的情况呢?今天小编就来分享一下【强力苹果恢复精灵】是如何将手机数据找回来的。 目录 一、软件介绍 二、功能特色 三、功能介绍 1、...
  • PHP Uploadify图片上传裁剪

    千次阅读 2013-12-09 10:59:59
    在网站中需要一个图片上传裁剪的功能,借鉴这篇文章 Ajax+PHP+jQuery图片截图上传 的指点,找到了jquery.imgAreaSelect这个不错插件,能对图片进行自定义区域选择并给出坐标,类似微博等同类网站上传头像要求按...
  • 查看方法:在安装过程中出现 dracut:/# 后,ls /dev ,可以看到有sda sdb等硬盘设备,sda通常有4个:sda1 sda2 sda3 sda4,对应Windows的四个分区,sdb有sdb和sdb4,sdb4 代表的就是U盘。 2.3、修改后,按Ctrl+x...
  • Java坦克大战 (七) 之图片

    千次阅读 2014-09-18 11:56:13
    //根据炮筒的方向,画直线代表炮筒 switch (ptDir) { case L: g.drawImage(imgs.get("L"), x, y, null); break; case LU: g.drawImage(imgs.get("LU"), x, y, null); break; case U: g.drawImage(imgs.get("U"), x,...
  • ps去除图片复杂的水印

    万次阅读 2018-02-17 14:38:41
    大多情况下,图片水印都是某网站的LOGO或网址之类的,我们是有可能得到的(如是ps教程论坛等论坛的水印,你只要上传一个大的透明背景的图片上论坛,就能简单获得他们的水印)。首先需要理解一下两个图层不透明度的混合...
  • 网页的背景图片代码

    万次阅读 2009-07-17 19:37:00
    网页背景图片代码1.(最普遍类)body{background-image:url(logo.gif);background-repeat:no-repeat;background-position:center}说明:以上代码为网页背景图片固定代码!网页背景图片固定代码,这样,当向下拉网页时,...
  • SpringBoot图片上传后页面无法显示,需要重启服务器

    千次阅读 热门讨论 2018-12-04 09:24:11
    标签无法显示图片,F12显示无法加载图片,请求地址为ip:port/static/img(楼主将图片保存到了static下),显示404无此资源。将项目重新启动之后,图片可以正常加载。 解决方法:需要配置虚拟文件...
  • 使用卷积神经网络进行图片分类 2

    千次阅读 2018-11-14 19:25:57
    使用卷积神经网络进行图片分类 2
  • Android多点触控实现图片缩放预览

    千次阅读 2017-09-08 21:33:31
    在我的博客 Android手势识别基础介绍 中介绍了 MotionEvent 的一些知识,看过的朋友或者对手势识别有了解的都应该...相信大家都经常在手机上浏览图片,大家的应用上也一定可以对图片进行放大或者缩小的处理,来让用户更
  • 深度残差网络(Deep Residual Network)是众多变种神经网络的一个代表,而且在某些领域确实效果不错,例如目标检测(Object Detection)。
  • vuforia6.2 在unity中图片识别教程

    千次阅读 2017-04-01 16:20:07
    vuforia6.2 在unity中图片识别模型流程(一) 最近公司将向AR转向,因此对vuforia进行了一些浅显的了解。未免遗忘,将vuforia的图片识别流程进行一个简单的整理。本人水平不高,若有遗落错处欢迎评论指正。(本文...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 29,371
精华内容 11,748
关键字:

代表消失的图片