精华内容
下载资源
问答
  • 从零搭建交叉编译链

    编译环境

    主机硬件环境:

        $ uname -a
        Linux PC 4.4.0-42-generic #62-Ubuntu SMP Fri Oct 7 23:11:45 UTC 2016 x86_64 x86_64 x86_64 GNU/Linux

    主机软件环境:

        $ cat /etc/issue
        Ubuntu 16.04.1 LTS

    需要安装的工具:

        sudo apt-get install libncurses5-dev
        sudo apt-get install gperf
        sudo apt-get install bison
        sudo apt-get install flex
        sudo apt-get install texinfo
        sudo apt-get install help2man
        sudo apt-get install gawk
        sudo apt-get install libtool
        sudo apt-get install libtool-bin
        sudo apt-get install automake

    libncurses5-dev: developer’s libraries for ncurses(执行 make menuconfig 时需要)

    gperf: 一个完美的hash函数生成器。例子可以看这个帖子:
    gperf 使用实例

    bison: 一个语法分析器生成器。Bison 把一个关于“向前查看 从左到右 最右”(LALR) 上下文无关文法的描述转化成可以分析该文法的 C 或 C++ 程序。它也可以为二义文法生成 “通用的 从左到右 最右” (GLR)语法分析器

    flex: 词法分析器

    texinfo: 是Linux系统提供的另外一种格式的帮助信息。和man相比,textinfo具有更好交互功能。它支持链接跳转功能,通常使用info和pinfo命令来阅读textinfo文档

    help2man: 一个可以自动为我们的程序生成man手册的工具

    gawk: linux下用于查找替换的文本工具

    libtool / libtool-bin: Generic library support script

    automake: Tool for generating GNU Standards-compliant Makefiles

    备注:

    • 不同的环境需要安装的工具不完全一致,出错时可以根据错误提示来排查
    • 各种工具的描述可以使用 apt-cache search XXX 命令去查询

    配置全局变量

        export PRJROOT=/home/user/tool_prj1         # 修改为自己的工程所在的目录
        export TARGET=arm-none-linux-gnueabi
        export PREFIX=${PRJROOT}/tool-chain
        export TARGET_PREFIX=${PREFIX}/${TARGET}
        export PATH=${PREFIX}/bin:${PATH}
        export ARCH=arm
        export BINUTILS_VERSION=binutils-2.27
        export GCC_VERSION=gcc-5.4.0
        export GLIBC_VERSION=glibc-2.23
        export KERNEL_VERSION=linux-4.4.25

    目录结构

        $ tree -L 2
        tool_prj1
        ├── build                       # src的编译目录
        ├── script                      # 脚本工具目录
        │   ├── toolchain_build.sh        # 自己写的自动化编译脚本,后续的命令都集成在了这个脚本中
        │   └── toolchain_config.lst      # 用于配置全局变量
        ├── setup                       # 保存下载的源码包
        │   ├── binutils-2.27.tar.bz2
        │   ├── gcc-5.4.0.tar.bz2
        │   ├── glibc-2.23.tar.bz2
        │   └── linux-4.4.25.tar.xz
        ├── src                         # 解压后的源码文件
        └── tool-chain                  # 工具链安装位置

    源码包下载

        cd setup
        wget http://ftp.gnu.org/gnu/binutils/$BINUTILS_VERSION.tar.bz2
        wget http://ftp.gnu.org/gnu/gcc/$GCC_VERSION/$GCC_VERSION.tar.bz2
        wget ftp://ftp.gnu.org/gnu/glibc/$GLIBC_VERSION.tar.bz2
        wget https://www.kernel.org/pub/linux/kernel/v4.x/$KERNEL_VERSION.tar.xz

    binutils

    编译流程

        cd src/
        tar -jxf ../setup/$BINUTILS_VERSION.tar.bz2
        mkdir ../build/$BINUTILS_VERSION
        cd ../build/$BINUTILS_VERSION
        sh ../../src/$BINUTILS_VERSION/configure --target=$TARGET --prefix=$PREFIX --disable-nls --enable-shared
        make
        make install

    选项详解

    –target=${TARGET}

    编译好的程序能够处理的平台

    注:build/host/target是一组相关参数,各项描述如下:

    • build 当前编译使用的机器
    • host 编译好的程序能够运行的平台
    • target 编译好的程序能够处理的平台

    比如我们需要在i386机器上为arm开发板编译一个可以处理mips程序的gcc,那么相关参数如下:

    • build=i386-linux
    • host=arm-linux
    • target=mips-linux

    –prefix=${RESULT_DIR}

    告诉配置脚本当运行 make install 时,把编译好的东西安装在RESULT_DIR目录

    –disable-nls

    这里nls的意思是本地语言支持(Native Language Support)

    –enable-shared

    编译出共享链接库

    检查编译结果

        $ ls ../../tool-chain/bin/
        arm-none-linux-gnueabi-addr2line  arm-none-linux-gnueabi-c++filt  arm-none-linux-gnueabi-ld      arm-none-linux-gnueabi-objcopy  arm-none-linux-gnueabi-readelf  arm-none-linux-gnueabi-strip
        arm-none-linux-gnueabi-ar         arm-none-linux-gnueabi-elfedit  arm-none-linux-gnueabi-ld.bfd  arm-none-linux-gnueabi-objdump  arm-none-linux-gnueabi-size
        arm-none-linux-gnueabi-as         arm-none-linux-gnueabi-gprof    arm-none-linux-gnueabi-nm      arm-none-linux-gnueabi-ranlib   arm-none-linux-gnueabi-strings

    制作Linux内核头文件

    编译流程

        cd src
        tar -xf ../setup/$KERNEL_VERSION.tar.xz
        cd $KERNEL_VERSION
        make ARCH=$ARCH CROSS_COMPILE=$TARGET- INSTALL_HDR_PATH=$PREFIX/$TARGET headers_install

    这一步是为了导出内核的头文件,后面编译GLIBC时需要

    选项详解

    ARCH

    目标处理器的架构是arm处理器

    CROSS_COMPILE

    编译程序所用的交叉工具链的名称

    INSTALL_HDR_PATH

    头文件需要安装的位置

    headers_install

    make的执行动作为安装头文件

    检查结果

        $ ls $PREFIX/$TARGET
        bin  include  lib

    可以看见 include 文件夹

    建立初始化GCC编译器

    功能介绍

    这一步主要是建立arm-linux-gcc工具,注意这个gcc没有glibc库的支持,所以只能用于编译内核、BootLoader等不需要C库支持的程序,后面创建C库也要用到这个编译器。如果只想编译内核和BootLoader,那么安装完这个就可以到此结束

    编译流程

        cd src
        tar -jxf ../setup/$GCC_VERSION.tar.bz2
        cd $GCC_VERSION
        ./contrib/download_prerequisites    # 下载mpfr/gmp/mpc/isl
        mkdir ../../build/$GCC_VERSION
        cd ../../build/$GCC_VERSION
        sh ../../src/$GCC_VERSION/configure --target=$TARGET --prefix=$PREFIX --disable-shared --disable-threads --without-headers --disable-libmudflap --enable-languages=c,c++ --disable-nls
        make all-gcc
        make install-gcc
        make all-target-libgcc
        make install-target-libgcc

    注意:GCC需要四个库 mpfr/gmp/mpc/isl,当前的GCC可以使用./contrib/download_prerequisites脚本直接下载

    • mpfr
    • gmp
    • mpc
    • isl

    选项详解

    –disable-shared

    不使用共享库

    –disable-threads

    不使用线程功能

    –without-headers

    不使用目标对象的头文件

    –disable-libmudflap

    暂时不清楚这个配置是什么意思

    –enable-languages=c,c++

    支持C/C++语言

    其它详细的参数介绍可以参考文档:gcc/doc/gccinstall.info

    检查结果

        $ ls tool-chain/bin/arm-none-linux-gnueabi-gcc*
        tool-chain/bin/arm-none-linux-gnueabi-gcc        tool-chain/bin/arm-none-linux-gnueabi-gcc-ar  tool-chain/bin/arm-none-linux-gnueabi-gcc-ranlib
        tool-chain/bin/arm-none-linux-gnueabi-gcc-5.4.0  tool-chain/bin/arm-none-linux-gnueabi-gcc-nm 

    可以看见GCC已经存在

    GLibc

    编译流程

        cd src
        tar -jxf ../setup/$GLIBC_VERSION.tar.bz2
        mkdir ../build/$GLIBC_VERSION
        cd ../build/$GLIBC_VERSION
        sh ../../src/$GLIBC_VERSION/configure --host=$TARGET --prefix=$PREFIX/$TARGET --with-tls --disable-profile --enable-add-ons --with-headers=$PREFIX/$TARGET/include libc_cv_forced_unwind=yes libc_cv_c_cleanup=yes libc_cv_arm_tls=yes --disable-nls
        make CC=$TARGET-gcc AR=$TARGET-ar RANLIB=$TARGET-ranlib
        make install

    选项详解

    –with-headers=@var{directory}

    Look for kernel header files in @var{directory}

    –with-tls

    This tells Glibc to use Thread Local Storage

    –disable-profile

    Don’t build libraries with profiling information

    –enable-add-ons

    Specify add-on packages to include in the build

    libc_cv_forced_unwind=yes

    libc_cv_c_cleanup=yes

    libc_cv_arm_tls=yes

    不清楚这三个参数的配置意义

    其它详细的参数介绍可以参考文档:manual/install.texi

    检查结果

        $ ls tool-chain/arm-none-linux-gnueabi/lib
        audit          libanl-2.23.so           libc.a            libc.so        libm.a          libnss_compat-2.23.so  libnss_files-2.23.so    libnss_nisplus.so.2     libresolv-2.23.so  libSegFault.so       Scrt1.o
        crt1.o         libanl.a                 libcidn-2.23.so   libc.so.6      libmcheck.a     libnss_compat.so       libnss_files.so         libnss_nis.so           libresolv.a        libthread_db-1.0.so
        crti.o         libanl.so                libcidn.so        libdl-2.23.so  libmemusage.so  libnss_compat.so.2     libnss_files.so.2       libnss_nis.so.2         libresolv.so       libthread_db.so
        crtn.o         libanl.so.1              libcidn.so.1      libdl.a        libm.so         libnss_db-2.23.so      libnss_hesiod-2.23.so   libpcprofile.so         libresolv.so.2     libthread_db.so.1
        gconv          libBrokenLocale-2.23.so  libc_nonshared.a  libdl.so       libm.so.6       libnss_db.so           libnss_hesiod.so        libpthread-2.23.so      librpcsvc.a        libutil-2.23.so
        gcrt1.o        libBrokenLocale.a        libcrypt-2.23.so  libdl.so.2     libnsl-2.23.so  libnss_db.so.2         libnss_hesiod.so.2      libpthread.a            librt-2.23.so      libutil.a
        ld-2.23.so     libBrokenLocale.so       libcrypt.a        libg.a         libnsl.a        libnss_dns-2.23.so     libnss_nis-2.23.so      libpthread_nonshared.a  librt.a            libutil.so
        ld-linux.so.3  libBrokenLocale.so.1     libcrypt.so       libieee.a      libnsl.so       libnss_dns.so          libnss_nisplus-2.23.so  libpthread.so           librt.so           libutil.so.1
        ldscripts      libc-2.23.so             libcrypt.so.1     libm-2.23.so   libnsl.so.1     libnss_dns.so.2        libnss_nisplus.so       libpthread.so.0         librt.so.1         Mcrt1.o                        

    建立完整GCC编译器

    编译流程

        cd build/$GCC_VERSION
        rm -rf *                        # 删除以前的配置
        sh ../../src/$GCC_VERSION/configure --target=$TARGET --prefix=$PREFIX --enable-languages=c,c++ --enable-shared --disable-nls
        make
        make install

    验证完整编译链

    动态编译

        $ arm-none-linux-gnueabi-gcc -o hello hello.c
        $ arm-none-linux-gnueabi-strip hello
        $ file hello
        hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.3, for GNU/Linux 2.6.32, stripped

    静态编译

        $ arm-none-linux-gnueabi-gcc -o hello hello.c -static
        $ arm-none-linux-gnueabi-strip hello
        $ file hello
        hello: ELF 32-bit LSB executable, ARM, EABI5 version 1 (SYSV), statically linked, for GNU/Linux 2.6.32, stripped
    展开全文
  • 交叉编译器

    千次阅读 2013-08-16 14:05:08
    交叉编译器 百科名片 编译器就是将“高级语言”翻译为“机器语言(低级语言)”的程序。一个现代编译器的主要工作流程:源代码 (source code) → 预处理器 (preprocessor) → 编译器 (compiler) ...

    交叉编译器

    百科名片

    编译器就是将“高级语言”翻译为“ 机器语言(低级语言)”的程序。一个现代 编译器的主要工作流程: 源代码 (source code) →  预处理器 (preprocessor) → 编译器 (compiler) →  汇编程序 (assembler) →  目标代码 (object code) →  链接器 (Linker) → 可执行程序 (executables)

    编辑本段基本简介

    高级 计算机语言便于人编写,阅读,维护。低阶 机器语言是计算机能直接解读、运行的。 编译器源程序(Source program)作为输入,翻译产生使用目标语言(Target language)的等价程序。 源代码一般为高级语言 (High-level language), 如 Pascal、C、C++、C#、Java等,而目标语言则是汇编语言或目标机器的 目标代码(Object code),有时也称作机器代码(Machine code)。

    编辑本段工作原理

    编译是从 源代码(通常为高阶语言)到能直接被计算机或 虚拟机执行的 目标代码(通常为低阶语言或 机器语言)的翻译过程。然而,也存在从低阶语言到高阶语言的 编译器,这类编译器中用来从由高阶语言生成的低阶语言代码重新生成高阶语言代码的又被叫做反编译器。也有从一种高阶语言生成另一种高阶语言的 编译器,或者生成一种需要进一步处理的的 中间代码的编译器(又叫级联)。
    典型的 编译器输出是由包含 入口点的名字和地址, 以及外部调用(到不在这个 目标文件中的 函数调用)的机器代码所组成的目标文件。一组 目标文件,不必是同一 编译器产生,但使用的编译器必需采用同样的输出格式,可以链接在一起并生成可以由用户直接执行的可执行程序。

    编辑本段分类说明

    编译器可以生成用来在与编译器本身所在的计算机和操作系统(平台)相同的环境下运行的 目标代码,这种编译器又叫做“本地”编译器。另外, 编译器也可以生成用来在其它平台上运行的 目标代码,这种编译器又叫做 交叉编译器。 交叉编译器在生成新的硬件平台时非常有用。“源码到源码 编译器”是指用一种高阶语言作为输入,输出也是高阶语言的编译器。例如: 自动并行化 编译器经常采用一种高阶语言作为输入,转换其中的代码,并用并行代码注释对它进行注释(如OpenMP)或者用语言构造进行注释(如FORTRAN的DOALL指令)。
    预处理器(preprocessor)
    作用是通过代入预定义等 程序段源程序补充完整。
    编译器前端(frontend)
    前端主要负责解析(parse)输入的 源代码,由 语法分析器和语意分析器 协同工作语法分析器负责把 源代码中的‘单词’(Token)找出来,语意分析器把这些分散的单词按预先定义好的语法组装成有意义的 表达式,语句 ,函数等等。 例如“a = b + c;”前端 语法分析器看到的是“a, =, b , +, c;”,语意分析器按定义的语法,先把他们组装成 表达式“b + c”,再组装成“a = b + c”的语句。 前端还负责语义(semantic checking)的检查,例如检测参与运算的 变量是否是同一类型的,简单的错误处理。最终的结果常常是一个抽象的语法树(abstract syntax tree,或 AST),这样后端可以在此基础上进一步优化,处理。
    编译器后端(backend)
    编译器后端主要负责分析,优化 中间代码(Intermediate representation)以及生成机器代码(Code Generation)。
    一般说来所有的 编译器分析,优化,变型都可以分成两大类: 函数内(intraprocedural)还是函数之间(interprocedural)进行。很明显,函数间的分析,优化更准确,但需要更长的时间来完成。

    编辑本段代码分析

    编译器分析(compiler analysis)的对象是前端生成并传递过来的中间代码,现代的优化型编译器(optimizing compiler)常常用好几种层次的中间代码来表示程序,高层的中间代码(high levelIR)接近输入的 源程序的格式,与输入语言相关(language dependent),包含更多的全局性的信息,和源程序的结构;中层的中间代码(middle level IR)与输入语言无关,低层的中间代码(Low level IR)与机器语言类似。 不同的分析,优化发生在最适合的那一层中间代码上。
    常见的编译分析有函数调用树(call tree),控制流程图(Control flow graph),以及在此基础上的 变量定义-使用,使用-定义链(define-use/use-define or u-d/d-u chain),变量别名分析(alias analysis),指针分析(pointer analysis),数据依赖分析(data dependenceanalysis)等。
    程序分析结果是编译器优化(compileroptimization)和程序变形(compiler transformation)的前提条件。常见的优化和变形有:函数内嵌(inlining),无用代码删除(Dead code elimination),标准化循环结构(loop normalization),循环体展开(loop unrolling),循环体合并,分裂(loop fusion,loop fission),数组填充(array padding),等等。 优化和变形的目的是减少代码的长度,提高内存(memory),缓存(cache)的使用率,减少读写磁盘,访问网络数据的频率。更高级的优化甚至可以把序列化的代码(serial code)变成并行运算,多线程的代码(parallelized,multi-threaded code)。
    机器代码的生成是优化变型后的中间代码转换成机器指令的过程。现代编译器主要采用生成汇编代码(assembly code)的策略,而不直接生成二进制的目标代码(binary object code)。即使在代码生成阶段,高级编译器仍然要做很多分析,优化,变形的工作。例如如何分配寄存器(register allocatioin),如何选择合适的机器指令(instruction selection),如何合并几句代码成一句等等。

    编辑本段工作方法

    首先 编译器进行 语法分析,也就是要把那些字符串分离出来。
    然后进行 语义分析,就是把各个由 语法分析分析出的语法单元的意义搞清楚。
    最后生成的是目标文件,也称为obj文件。
    再经过 链接器的链接就可以生成最后的 可执行代码了。
    有些时候需要把多个文件产生的 目标文件进行链接,产生最后的代码。这一过程称为交叉链接。

    编辑本段语言对比

    许多人将高阶程序语言分为两类: 编译型语言和 直译型语言 。然而,实际上,这些语言中的大多数既可用编译型实现也可用直译型实现,分类实际上反映的是那种语言常见的实现方式。(但是,某些直译型语言,很难用编译型实现。比如那些允许 在线代码更改 的直译型语言。)

    编辑本段发展历史

    20世纪50年代,IBM的John Backus带领一个研究小组对FORTRAN语言及其 编译器进行开发。但由于当时人们对编译理论了解不多,开发工作变得既复杂又艰苦。与此同时,Noam Chomsky开始了他对自然语言结构的研究。他的发现最终使得 编译器的结构异常简单,甚至还带有了一些自动化。Chomsky的研究导致了根据语言文法的难易程度以及识别它们所需要的算法来对语言分类。正如所称的Chomsky架构(Chomsky Hierarchy),它包括了文法的四个层次:0型文法、1型文法、2型文法和3型文法,且其中的每一个都是其前者的特殊情况。2型文法(或上下文无关文法)被证明是 程序设计语言中最有用的,而且今天它已代表着程序设计语言结构的标准方式。分析问题(parsing problem,用于上下文无关文法识别的有效算法)的研究是在60年代和70年代,它相当完善的解决了这个问题。它已是 编译原理中的一个标准部分。
    有限状态自动机(Finite Automation)和 正则表达式(Regular Expression)同上下文无关文法紧密相关,它们与Chomsky的3型文法相对应。对它们的研究与Chomsky的研究几乎同时开始,并且引出了表示 程序设计语言的单词的符号方式。
    人们接着又深化了生成有效 目标代码的方法,这就是最初的 编译器,它们被一直使用至今。人们通常将其称为优化技术(Optimization Technique),但因其从未真正地得到过被优化了的 目标代码而仅仅改进了它的有效性,因此实际上应称作代码改进技术(Code Improvement Technique)。
    当分析问题变得好懂起来时,人们就在开发程序上花费了很大的功夫来研究这一部分的 编译器自动构造。这些程序最初被称为 编译器的编译器(Compiler-compiler),但更确切地应称为分析程序生成器(Parser Generator),这是因为它们仅仅能够自动处理编译的一部分。这些程序中最著名的是Yacc(Yet Another Compiler-compiler),它是由Steve Johnson在1975年为Unix系统编写的。类似的,有限状态自动机的研究也发展了一种称为扫描程序生成器(Scanner Generator)的工具,Lex(与Yacc同时,由Mike Lesk为Unix系统开发)是这其中的佼佼者。
    在20世纪70年代后期和80年代早期,大量的项目都贯注于 编译器其它部分的生成自动化,这其中就包括了 代码生成。这些尝试并未取得多少成功,这大概是因为操作太复杂而人们又对其不甚了解。
    编译器设计最近的发展包括:首先,编译器包括了更加复杂算法的应用程序它用于推断或简化程序中的信息;这又与更为复杂的 程序设计语言的发展结合在一起。其中典型的有用于函数语言编译的Hindley-Milner类型检查的统一算法。其次, 编译器已越来越成为基于窗口的交互开发环境(Interactive Development Environment,IDE)的一部分,它包括了编辑器、 连接程序调试程序以及项目管理程序。这样的IDE标准并没有多少,但是对标准的窗口环境进行开发已成为方向。另一方面,尽管在 编译原理领域进行了大量的研究,但是基本的 编译器设计原理在近20年中都没有多大的改变,它正迅速地成为计算机科学课程中的中心环节。
    在20世纪90年代,作为GNU项目或其它开放源代码项目标一部分,许多免费 编译器和编译器开发工具被开发出来。这些工具可用来编译所有的计算机程序语言。它们中的一些项目被认为是高质量的,而且对现代编译理论感兴趣的人可以很容易的得到它们的免费源代码。
    大约在1999年,SGI公布了他们的一个工业化的并行化优化 编译器Pro64的 源代码,后被全世界多个编译器研究小组用来做研究平台,并命名为 Open64Open64的设计结构好,分析优化全面,是 编译器高级研究的理想平台。

    编辑本段交叉编译

    在一种计算机环境中运行的 编译程序,能编译出在另外一种环境下运行的代码,我们就称这种 编译器支持 交叉编译。这个编译过程就叫 交叉编译。简单地说,就是在一个平台上生成另一个平台上的 可执行代码。这里需要注意的是所谓平台,实际上包含两个概念: 体系结构(Architecture)、操作系统(Operating System)。同一个 体系结构可以运行不同的操作系统;同样,同一个操作系统也可以在不同的体系结构上运行。举例来说,我们常说的x86 Linux平台实际上是Intel x86 体系结构和Linux for x86操作系统的统称;而x86 WinNT平台实际上是Intel x86体系结构和Windows NT for x86操作系统的简称。
    有时是因为目的平台上不允许或不能够安装我们所需要的 编译器,而我们又需要这个编译器的某些特征;有时是因为目的平台上的资源贫乏,无法运行我们所需要编译器;有时又是因为目的平台还没有建立,连操作系统都没有,根本谈不上运行什么编译器。
    交叉编译这个概念的出现和流行是和 嵌入式系统的广泛发展同步的。我们常用的 计算机软件,都需要通过编译的方式,把使用高级 计算机语言编写的代码(比如C代码)编译(compile)成计算机可以识别和执行的 二进制代码。比如,我们在Windows平台上,可使用Visual C++ 开发环境,编写程序并编译成可执行程序。这种方式下,我们使用PC平台上的Windows工具开发针对Windows本身的可执行程序,这种编译过程称为native compilation,中文可理解为本机编译。然而,在进行 嵌入式系统的开发时,运行程序的目标平台通常具有有限的 存储空间和运算能力,比如常见的 ARM 平台,其一般的 静态存储空间大概是16到32MB,而CPU的主频大概在100MHz到500MHz之间。这种情况下,在ARM平台上进行本机编译就不太可能了,这是因为一般的编译工具链(compilation tool chain)需要很大的 存储空间,并需要很强的CPU运算能力。为了解决这个问题, 交叉编译工具就应运而生了。通过 交叉编译工具,我们就可以在CPU能力很强、 存储空间足够的主机平台上(比如PC上)编译出针对其他平台的可执行程序。
    要进行 交叉编译,我们需要在主机平台上安装对应的交叉编译工具链(cross compilation tool chain),然后用这个交叉编译工具链编译我们的 源代码,最终生成可在目标平台上运行的代码。

    编辑本段常见例子

    交叉编译
    1、在Windows PC上,利用ADS(ARM 开发环境),使用armcc 编译器,则可编译出针对ARM CPU的 可执行代码
    2、在Linux PC上,利用arm-linux-gcc 编译器,可编译出针对Linux ARM平台的 可执行代码
    3、在Windows PC上,利用cygwin环境,运行arm-elf-gcc 编译器,可编译出针对ARM CPU的 可执行代码
    4、在Windows系统上,利用Keil Uvison工具,开发出运行在89C51单片机上的程序。
    5、在Windows系统上,利用CodeWarrior IDE工具,开发出运行在Freescale XS128单片机上的程序。
    展开全文
  • 为解决上述问题,本文研究了一种新的测量交流输电线路交叉跨越区域空间电场测量方法,首先对交流输电线路交叉跨越区域的弧垂进行检查,然后利用弧垂检查结果设定电场测量模型,最后通过模型完成测量工作。...
  • 交叉验证是什么? 在模型建立中,通常有两个数据集:训练集(train)和测试集(test)。训练集用来训练模型;测试集是完全不参与训练的数据,仅仅用来观测测试效果的数据。 一般情况下,训练的结果对于训练集的拟合...

    交叉验证是什么?

    在模型建立中,通常有两个数据集:训练集(train)和测试集(test)。训练集用来训练模型;测试集是完全不参与训练的数据,仅仅用来观测测试效果的数据。

    一般情况下,训练的结果对于训练集的拟合程度通常还是挺好的,但是在测试集总的表现却可能不行。比如下面的例子:
    在这里插入图片描述

    • 图一的模型是一条线型方程。 可以看到,所有的红点都不在蓝线上,所以导致了错误率很高,这是典型的不拟合的情况
    • 图二 的蓝线则更加贴近实际的红点,虽然没有完全重合,但是可以看出模型表示的关系是正确的。
    • 图三,所有点都在蓝线上,这时候模型计算出的错误率很低,(甚至将噪音都考虑进去了)。这个模型只在训练集中表现很好,在测试集中的表现就不行。 这是典型的‘过拟合’情况。

    所以,训练的模型需要找出数据之间‘真正’的关系,避免‘过拟合’的情况发生。

    交叉验证:就是在训练集中选一部分样本用于测试模型。
    保留一部分的训练集数据作为验证集/评估集,对训练集生成的参数进行测试,相对客观的判断这些参数对训练集之外的数据的符合程度。

    留一验证(LOOCV,Leave one out cross validation )

    只从可用的数据集中保留一个数据点,并根据其余数据训练模型。此过程对每个数据点进行迭代,比如有n个数据点,就要重复交叉验证n次。例如下图,一共10个数据,就交叉验证十次
    在这里插入图片描述

    优点:

    • 适合小样本数据集
    • 利用所有的数据点,因此偏差将很低

    缺点:

    • 重复交叉验证过程n次导致更高的执行时间
    • 测试模型有效性的变化大。因为针对一个数据点进行测试,模型的估计值受到数据点的很大影响。如果数据点被证明是一个离群值,它可能导致更大的变化

    LOOCC是保留一个数据点,同样的你也可以保留P个数据点作为验证集,这种方法叫LPOCV(Leave P Out Cross Validation)

    LOOCC代码

    R

    score = list()
    
    LOOCV_function = function(x,label){
     for(i in 1:nrow(x)){
     training = x[-i,]
     model = #... train model on training
     validation = x[i,]
     pred = predict(model, validation[,setdiff(names(validation),label)])
     score[[i]] = rmse(pred, validation[[label]]) # score/error of ith fold
     }
     return(unlist(score)) # returns a vector
     }
    

    验证集方法

    交叉验证的步骤如下:

    1. 保留一个样本数据集, (取出训练集中20%的样本不用)
    2. 使用数据集的剩余部分训练模型 (使用另外的80%样本训练模型)
    3. 使用验证集的保留样本。(完成模型后,在20%的样本中测试)
    4. 如果模型在验证数据上提供了一个肯定的结果,那么继续使用当前的模型。

    优点: 简单方便。直接将训练集按比例拆分成训练集和验证集,比如50:50。

    缺点: 没有充分利用数据, 结果具有偶然性。如果按50:50分,会损失掉另外50%的数据信息,因为我们没有利用着50%的数据来训练模型。

    验证集方法代码

    Python 使用train_test_split

    from sklearn.model_selection import train_test_split
    train, validation = train_test_split(data, test_size=0.50, random_state = 5)
    
    

    train_test_split,划分成train 和test 两部分,其中train用来训练模型,test用来评估模型,模型通过fit方法从train数据集中学习,调用score方法在test集上进行评估。

    from sklearn.model_selection import train_test_split
    from sklearn.linear_model import LogisticRegression
    
    #已经导入数据
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=20, shuffle=True)
    
    # Logistic Regression
    model = LogisticRegression()
    model.fit(X_train, y_train)
    prediction = model.predict(X_test)
    print('The accuracy of the Logistic Regression is: {0}'.format(metrics.accuracy_score(prediction,y_test)))
    

    R

    set.seed(101) # Set Seed so that same sample can be reproduced in future also
    
    # Now Selecting 50% of data as sample from total 'n' rows of the data
    sample <- sample.int(n = nrow(data), size = floor(.50*nrow(data)), replace = F)
    train <- data[sample, ]
    test  <- data[-sample, ]
    

    K折交叉验证(k-fold cross validation)

    针对上面通过train_test_split划分,从而进行模型评估方式存在的弊端,提出Cross Validation 交叉验证。

    Cross Validation:简言之,就是进行多次train_test_split划分;每次划分时,在不同的数据集上进行训练、测试评估,从而得出一个评价结果;如果是5折交叉验证,意思就是在原始数据集上,进行5次划分,每次划分进行一次训练、评估,最后得到5次划分后的评估结果,一般在这几次评估结果上取平均得到最后的 评分。k-fold cross-validation ,其中,k一般取5或10。
    在这里插入图片描述

    1. 训练模型需要在大量的数据集基础上,否则就不能够识别数据中的趋势,导致错误产生
    2. 同样需要适量的验证数据点。 验证集太小容易导致误差
    3. 多次训练和验证模型。需要改变训练集和验证集的划分,有助于验证模型。
      步骤:
    4. 随机将整个数据集分成k折;
    5. 如图中所示,依次取每一折的数据集作验证集,剩余部分作为训练集
    6. 算出每一折测试的错误率
    7. 取这里K次的记录平均值 作为最终结果

    优点:

    • 适合大样本的数据集
    • 经过多次划分,大大降低了结果的偶然性,从而提高了模型的准确性。
    • 对数据的使用效率更高。train_test_split,默认训练集、测试集比例为3:1。如果是5折交叉验证,训练集比测试集为4:1;10折交叉验证训练集比测试集为9:1。数据量越大,模型准确率越高。

    缺点:

    • 对数据随机均等划分,不适合包含不同类别的数据集。比如:数据集有5类数据(ABCDE各占20%),抽取出来的也正好是按照类别划分的5类,第一折全是A,第二折全是B……这样就会导致,模型学习到测试集中数据的特点,用BCDE训练的模型去测试A类数据、ACDE的模型测试B类数据,这样准确率就会很低。

    如何确定K值?

    • 一般情况下3、5是默认选项,常建议用K=10。
    • k值越低,就越有偏差;K值越高偏差就越小,但是会受到很大的变化。
    • k值越小,就越类似于验证集方法;而k值越大,则越接近LOOCV方法。

    k-fold代码

    Python 使用cross_val_score或者KFold

    cross_val_score直接将整个交叉验证过程连接起来。

    from sklearn.model_selection import cross_val_score
    model  = LogisticRegression()
    scores = cross_val_score(model,X, y,cv=3) #cv:默认是3折交叉验证,可以修改cv=5,变成5折交叉验证。
    print("Cross validation scores:{}".format(scores))
    print("Mean cross validation score:{:2f}".format(scores.mean()))
    

    KFold 可以显示具体的划分情况。

    from sklearn.model_selection import KFold 
    
    kf = KFold(n_splits=5, random_state=None) # 5折
    
    #显示具体划分情况
    for train_index, test_index in kf.split(X):
          print("Train:", train_index, "Validation:",test_index)
          X_train, X_test = X[train_index], X[test_index] 
          y_train, y_test = y[train_index], y[test_index] 
    
    i = 1
    for train_index, test_index in kf.split(X, y):
        print('\n{} of kfold {}'.format(i,kf.n_splits))
        X_train, X_test = X[train_index], X[test_index] 
        y_train, y_test = y[train_index], y[test_index]
        model = LogisticRegression(random_state=1)
        model.fit(X_train, y_train)
        pred_test = model.predict(X_test)
        score = metrics.accuracy_score(y_test, pred_test)
        print('accuracy_score', score)
        i += 1
        #pred_test = model.predict(X_test)
        pred = model.predict_proba(X_test)[:, 1]
    

    R code

    library(caret)
    data(iris)
    
    # Define train control for k fold cross validation
    train_control <- trainControl(method="cv", number=10)
    # Fit Naive Bayes Model
    model <- train(Species~., data=iris, trControl=train_control, method="nb")
    # Summarise Results
    print(model)
    

    分层交叉验证 (Stratified k-fold cross validation)

    分层是重新将数据排列组合,使得每一折都能比较好地代表整体。

    比如下面这个例子:在一个二分类问题上,原始数据一共有两类(F和M),F:M的数据量比例大概是 1:3;划分了5折,每一折中F和M的比例都保持和原数据一致(1:3)。

    这样就避免了随机划分可能产生的的情况,像是一折全是F,其他3折都是M。

    在这里插入图片描述

    下图是标准交叉验证和分层交叉验证的区别:
    标准交叉验证(即K折交叉验证):直接将数据分成几折;
    分层交叉验证:先将数据分类(class1,2,3),然后在每个类别中划分三折。
    在这里插入图片描述

    分层验证代码

    Python 使用cross_val_scoreStratifiedKFold

    from sklearn.model_selection import StratifiedKFold
    skf = StratifiedKFold(n_splits=5,shuffle=False,random_state=0)
    
    # X is the feature set and y is the target
    for train_index, test_index in skf.split(X,y): 
        print("Train:", train_index, "Validation:", test_index) 
        X_train, X_test = X[train_index], X[test_index] 
        y_train, y_test = y[train_index], y[test_index]
        
    model = LogisticRegression()
    scores = cross_val_score(model,X,y,cv=skf)
    print("straitified cross validation scores:{}".format(scores))
    print("Mean score of straitified cross validation:{:.2f}".format(scores.mean()))
    

    ** R code**

    library(caret)
    # Folds are created on the basis of target variable
    folds <- createFolds(factor(data$target), k = 10, list = FALSE)
    

    重复交叉验证( k-fold cross validation with repetition)

    如果训练集不能很好地代表整个样本总体,分层交叉验证就没有意义了。这时候,可以使用重复交叉验证。

    重复验证代码

    Python:RepeatedKFold重复K折交叉验证

    kf = RepeatedKFold(n_splits=5, n_repeats=2, random_state=None)  #默认是5折
    
    for train_index, test_index in kf.split(X):
          print("Train:", train_index, "Validation:",test_index)
          X_train, X_test = X[train_index], X[test_index] 
          y_train, y_test = y[train_index], y[test_index]
            
    i = 1
    for train_index, test_index in kf.split(X, y):
        print('\n{} of kfold {}'.format(i,i))
        X_train, X_test = X[train_index], X[test_index] 
        y_train, y_test = y[train_index], y[test_index]
        model = LogisticRegression(random_state=1)
        model.fit(X_train, y_train)
        pred_test = model.predict(X_test)
        score = metrics.accuracy_score(y_test, pred_test)
        print('accuracy_score', score)
        i += 1
        #pred_test = model.predict(X_test)
        pred = model.predict_proba(X_test)[:, 1]
    

    对抗验证(Adversarial Validation)

    在处理实际数据集时,经常会出现测试集和训练集截然不同的情况。因此,可能导致交叉验证结果不一致

    在这种情况下,可以使用对抗验证法:总体思路是根据特征分布创建一个分类模型,以检查训练集和测试集之间的相似程度。

    步骤:

    1. 组合训练集和测试集;
    2. 分配0/1标签(0-训练、1-测试);
    3. 建立模型,(如果模型AUC在0.7以上,表示分类器表现较好,也间接说明train 和test 差异度较大
    4. 评估二进制分类任务来量化两个数据集的分布是否一致;
    5. 找出和测试集最相似的数据样本
    6. 构成与测试集最相似的验证集;

    优点: 使验证策略在训练集和测试集高度不同的情况下更加可靠。

    缺点: 一旦测试集的分布发生变化,验证集可能不再适合评估模型。

    对抗验证代码

    #1. 将目标变量删除
    train.drop(['target'], axis = 1, inplace = True)
    
    #2. 创建新的目标变量:训练集为1;测试集为0
    train['is_train'] = 1
    test['is_train'] = 0
    
    #3. 合并训练集和测试集
    df = pd.concat([train, test], axis = 0)
    
    #4. 使用新变量训练分类模型,并预测概率
    y = df['is_train']; df.drop('is_train', axis = 1, inplace = True) 
    # Xgboost parameters
    xgb_params = {'learning_rate': 0.05, 
                  'max_depth': 4,
                  'subsample': 0.9,        
                  'colsample_bytree': 0.9,
                  'objective': 'binary:logistic',
                  'silent': 1, 
                  'n_estimators':100, 
                  'gamma':1,         
                  'min_child_weight':4}   
    clf = xgb.XGBClassifier(**xgb_params, seed = 10)
    probs = clf.predict_proba(x1)[:,1]
    
    #5. 使用步骤4中计算的概率对序列集进行排序,并将前n%个样本/行作为验证集(n%是您希望保留在验证集中的序列集的分数)
    new_df = pd.DataFrame({'id':train.id, 'probs':probs})
    new_df = new_df.sort_values(by = 'probs', ascending=False) # 30% validation set
    val_set_ids = new_df.iloc[1:np.int(new_df.shape[0]*0.3),1]
    #val_set_ids将为提供列训练集的ID,这些ID将构成与测试集最相似的验证集。
    

    时间序列的交叉验证(Cross Validation for time series)

    对于时间序列的数据集,不能像上述方法一样随机地划分验证集。为了解决时间序列的预测问题,可以尝试时间序列交叉验证:采用正向链接的策略,即按照时间顺序划分每一折的数据集。

    假设我们有一个时间序列,表示在n年内消费者对某一产品的年需求量。
    在这里插入图片描述
    我们逐步选择新的训练集和测试集。我们从一个最小的训练集开始(这个训练集具有拟合模型所需的最少观测数)逐步地,每次都会更换训练集和测试集。在大多数情况下,不必一个个点向前移动,可以设置一次跨5个点/10个点。在回归问题中,可以使用以下代码执行交叉验证。

    时间序列代码

    pythonTimeSeriesSplit

    from sklearn.model_selection import TimeSeriesSplit
    X = np.array([[1, 2], [3, 4], [1, 2], [3, 4]])
    y = np.array([1, 2, 3, 4])
    tscv = TimeSeriesSplit(n_splits=3)
    
    for train_index, test_index in tscv.split(X):
         print("Train:", train_index, "Validation:", val_index)
         X_train, X_test = X[train_index], X[val_index]
         y_train, y_test = y[train_index], y[val_index]
    
    TRAIN: [0] TEST: [1]
    TRAIN: [0 1] TEST: [2]
    TRAIN: [0 1 2] TEST: [3]
    

    R code

    library(fpp)
    library(forecast)
    e <- tsCV(ts, Arima(x, order=c(2,0,0), h=1) #CV for arima model
    sqrt(mean(e^2, na.rm=TRUE)) # RMSE
    #h =1意味着我们只接受1步超前预报的误差。
    #(h=4)4步前进误差如下图所示。如果想评估多步预测的模型,可以使用此选项。
    

    在这里插入图片描述

    参考链接:https://www.analyticsvidhya.com/blog/2018/05/improve-model-performance-cross-validation-in-python-r/
    其他网上找到的有关文章:
    关于时间序列的:https://zhuanlan.zhihu.com/p/99674163
    关于对抗验证的:https://zhuanlan.zhihu.com/p/137580733

    展开全文
  • k-折交叉验证

    千次阅读 2019-06-18 20:52:58
    一、k折交叉验证的目的(为什么要用k折交叉验证?) 1.根本原因:数据有限,单一的把数据都用来做训练模型,容易导致过拟合。(反过来,如果数据足够多,完全可以不使用交叉验证。)较小的k值会导致可用于建模的数据...

    一、k折交叉验证的目的(为什么要用k折交叉验证?)

    1.根本原因:数据有限,单一的把数据都用来做训练模型,容易导致过拟合。(反过来,如果数据足够多,完全可以不使用交叉验证。)较小的k值会导致可用于建模的数据量太小,所以小数据集的交叉验证结果需要格外注意,建议选择较大的k值。
    2.理论上:使用了交叉验证,模型方差“应该”降低了。
    在理想情况下,我们认为k折交叉验证可以 O ( 1 / k ) O(1/k) O(1/k)的效率降低模型方差,从而提高模型的泛化能力。通俗地说,我们期望模型在训练集的多个子数据集上表现良好,要胜过单单在整个训练数据集上表现良好。(注意:但实际上,由于所得到的k折数据之间并非独立而是存在相关性,k折交叉验证到底能降低多少方差还不确定,同时可能会带来偏差上升。)

    二、 从方差偏差的角度来看交叉验证

    (1)什么是模型的偏差和方差?
    在机器学习中,我们用训练集去训练(学习)一个model(模型),通常的做法是定义一个loss function(误差函数),通过将这个loss最小化过程,来提高模型的性能(performance)。然而我们学习一个模型的目的是为了解决实际的问题(或者说是训练数据集这个领域(field)中的一般化问题),单纯地将训练数据集的loss最小化,并不能保证在解决更一般问题时仍然是最优的,甚至不能保证模型是可用的。这个训练数据集的loss与一般化的数据集的loss之间的差异就叫generalization error=bias+variance。(注意:bias和variance是针对generalization(一般化,泛化)来说的。)
    generalization error分为bias和variance两个部分。首先如果我们能够获得所有可能的数据集合,并在这个数据集合上将loss最小化,这样学习到的模型就可以称之为“真是模型”。当然,我们无论如何都不能获得并训练所有可能的数据,所以“真是模型”肯定存在,但是无法获得,我们最终的目标就是去学习一个模型使其更加接近这个“真实模型”。
    而bias和variance分别从两个方面来描述我们学习到的模型与真实模型之间的差距。
    Bias是“用所有可能的训练数据集训练出的所有模型的输出的平均值”与“真是模型”的输出值之间的差异
    Variance则是“不同的训练数据集训练出的模型”的输出值之间的差异。也就是说bias反映的是模型在样本上的输出值与真实值之间的差距,即模型本省的精准度(或者说算法本省的拟合能力);variance反映的是模型每次输出结果与模型期望输出之间的误差,即模型的稳定性。
    这里需要注意的是我们能够用来学习的训练数据集只是全部数据中的一个子集。举两个例子:

    a. 开枪问题:
    想象你开着一架黑鹰直升机,得到命令攻击地面上一只敌军部队,于是你连打数十梭子,结果有一下几种情况:
    1.子弹基本上都打在队伍经过的一棵树上了,连在那棵树旁边等兔子的人都毫发无损,这就是方差小(子弹打得很集中),偏差大(跟目的相距甚远)。
    2.子弹打在了树上,石头上,树旁边等兔子的人身上,花花草草也都中弹,但是敌军安然无恙,这就是方差大(子弹到处都是),偏差大(同1)。
    3.子弹打死了一部分敌军,但是也打偏了些打到花花草草了,这就是方差大(子弹不集中),偏差小(已经在目标周围了)。
    4.子弹一颗没浪费,每一颗都打死一个敌军,跟抗战剧里的八路军一样,这就是方差小(子弹全部都集中在一个位置),偏差小(子弹集中的位置正是它应该射向的位置)。
    b. 打靶问题:
    一次打靶实验,目标是为了打到10环,但是实际上只打到了7环,那么这里面的Error就是3。具体分析打到7环的原因,可能有两方面:一是瞄准出了问题,比如实际上射击瞄准的是9环而不是10环;二是枪本身的稳定性有问题,虽然瞄准的是9环,但是只打到了7环。那么在上面一次射击实验中,Bias就是1,反应的是模型期望与真实目标的差距,而在这次试验中,由于Variance所带来的误差就是2,即虽然瞄准的是9环,但由于本身模型缺乏稳定性,造成了实际结果与模型期望之间的差距。

    衡量一个模型评估方法的好坏,主要是从偏差和方差两个方面进行的。
    E r r o r = B a i s 2 + V a r i a n c e + N o i s e Error=Bais^2+Variance+Noise Error=Bais2+Variance+Noise
    其中Noise不是真正的数据,是造成过拟合的原因之一。模型过度追求Low Bias会导致训练过度,对训练集判断表现优秀,导致噪声点也被拟合进去了。
    (2)交叉验证k值对bias和variance的影响。
    假设我们现在有一组训练数据,需要训练一个模型。在训练过程的最初,bias很大,因为我们的模型还没有来得及开始学习,也就是说与“真实模型”差距很大。然而此时variance却很小,因为训练数据集(training data)还没有来得及对模型产生影响,此时将模型应用于“不同的”训练数据集也不会有太大的差异。而随着训练过程的进行,bias变小,因为我们的模型变得“聪明”了,懂得了更多关于“真实模型”的信息,输出值与真实值之间更加接近了。但是如果我们训练的时间太久,variance就会变得很大,因为我们除了学习关于真实模型的信息,还会学到许多具体的,只针对我们使用的训练集(真实数据的子集)信息。而不同的可能训练数据集(真实数据集的子集)之间的某些特征和噪声是不一致的,这就导致了我们的模型在很多其他的数据集上无法获得很好的效果,也就是所谓的overfitting(过拟合)。
    因此实际的训练过程中会用到validation set,会用到诸如early stopping以及regularization等方法来避免过拟合的发生,然而没有一种固定的策略方法适用于所有的task和data,所以bias和variance之间的trade off应该是机器学习永恒的主题。
    (3)交叉验证方法
    交叉验证是一种通过估计模型的泛化误差,从而进行模型选择的方法。基本思想是将训练数据分为两部分,一部分数据用来模型的训练,另一部分数据用于测试模型的误差,成为验证集。由于两部分数据不同,估计得到的泛化误差更接近真实的模型表现。
    交叉验证的方法:
    考虑两种极端情况:
    ·完全不使用交叉验证: k = 1 k=1 k=1,这个时候,所有数据都被用于训练,模型很容易过拟合,因此容易是低偏差、高方差。
    ·留一交叉验证(leave-one-out): k = n k=n k=n,每次从个数为n的样本集中,取出一个样本作为验证集,剩下的(n-1)个作为训练集,重复进行n次,最后平均n个结果作为泛化误差估计。
    当k在1到n之间游走时,可以理解为方差和偏差妥协的结果。
    ·**k折交叉验证:**把数据分成k份,每次拿出一份作为验证集,剩下(k-1)份作为训练集,重复k 次。最后平均k次的结果,作为误差评估的结果。
    (4) k到底该取多少?为什么大部分人都要取10?
    k- fold 交叉验证是用来确定不同类型的模型(线性、指数等)哪一种更好,为了减少数据划分对模型评价的影响,最终选出来的模型类型(线性、指数等)是k次建模的误差平均值最小的模型。当k较大时,经过更多次数的平均可以学习得到更符合真实数据分布份模型,bias就较小了,但是这样一来模型就更加拟合训练数据集,再去测试集上预测的时候,预测误差的期望值就变大了,从而variance就大了;反之,k较小时模型不会过度拟合训练数据,从而bias较大,但是正因为没有过度拟合训练数据,variance也较小。
    由于实际情况中,交叉的折数(fold)受很多因素的影响,所以k值取多少也没能给出准确的答案。一般两种流行的取值:(i)k=10,(ii)k=n,n指的是训练数据的总数,就是上面介绍的留一法。
    (1)对于稳定的模型来说,留一法的结果较为统一,值得信赖。对于不稳定的模型,留一法往往比k折更为有效。
    (2)模型稳定性较低时,增大k的取值可以给出更好的效果,但是要考虑计算的开销。
    (3)2017年的一项研究给出了另一种经验式的选择方法,建议 K ≈ l o g ( n ) K\approx log(n) Klog(n)并且保证 n / K &gt; 3 d n/K&gt;3d n/K>3d,其中n表示数据量,d表述特征数。

    三、Bias, Variance和Overfitting, Underfitting

    过拟合(overfitting),就是我们对训练样本能够百分百命中,但是在测试时掉链子,拟合很差,也就是我们说的泛化性能不好。所以如果太追求在训练集上的完美二采用一个很复杂的模型,会使得模型把训练集中的噪声也当成真实数据分布特征,从而得到错误的数据分布估计。
    一句话,过拟合会出现高方差问题。
    欠拟合(underfitting),训练样本太少,导致模型不足以刻画数据分布,体现为在训练集上的错误率都很高。
    一句话,欠拟合会出现高偏差问题

    怎样避免过拟合和欠拟合?

    避免欠拟合(训练不够充分)
    1.寻找更好的特征–具有代表性的特征
    2.用更多的特征–增大输入向量的维度
    避免过拟合(刻画太细,泛化太差)
    1.增大数据集合–使用更多的数据,噪声点比重减少
    2.减少数据特征–减小数据维度,高维空间密度小
    3.正则化方法–即在对模型的目标函数或代价函数加上正则项
    4.交叉验证方法

    致谢

    https://www.jianshu.com/p/651f998a6398
    https://blog.csdn.net/Li_yi_chao/article/details/82665745

    展开全文
  • 交叉小径的花园

    千次阅读 2012-05-29 15:52:44
    交叉小径的花园》是南美的博尔赫斯一篇带有科幻色彩的小说,主人公是一个中国人。作者在小说中布开了一张时间的网,它的网线相互接近、交叉、隔断,或者几个世纪毫不相关,包括了一切的可能性。我们并不存在于这种时间...
  • Ubuntu 14.04 交叉编译工具制作

    千次阅读 2014-07-11 10:16:59
    各变量的具体意义如下: PRJROOT : 整个工程的根目录,这里当然是 Embeded 了 TARGET : 目标文件对应的体系结构, arm-linux 代表编译出来的 target 只能在 arm 体系结构中运行 PREFIX : 设置目标...
  • 使用 Clang 交叉编译1. 介绍2. 交叉编译问题(Cross compilation issues)3. Clang中的一般交叉编译选项(General Cross-Compilation Options in Clang)3.1 Target Triple3.2 CPU、FPU、ABI3.3 工具链选项4. 特定目标的...
  • 交叉分类表,是以两个不同时期的地理实体类型为横纵坐标的表格。 ①用于参照的时期的类型位于表格的上方,按照横方向排列 ②用以比较的时期的类型位于表格的左方,垂直排列 ③在横纵坐标上类型的排列顺序一致 ④...
  •  交叉测试有哪些意义 1、每一个测试人员有自己思维的局限性,一种思维测试过之后,软件会对这种测试思维产生抗性,很难再发现新的问题,通过交叉测试,可以把新的测试思维带进来,测试出未发现的bug。 2、防止...
  • 1 环境变量的意义 环境变量相当于操作系统的全局变量。每一个环境变量对操作系统来说都是唯一的,名字和所代表的意义都是唯一的。Linux系统可以有很多个环境变量。其中有一部分是Linux系统自带的,还有一些是我们...
  • QT官网关于交叉编译说明

    千次阅读 2018-03-16 12:02:15
    执行交叉编译时也支持pkg-config。 configure会自动设置PKG_CONFIG_LIBDIR以使pkg-config报告编译器和链接器设置基于sysroot而不是主机。这通常运行良好,无需进一步调整。但是,在运行configure之前,必须为主机...
  • 交叉编译安装alsa_lib和alsa_utils以及基本使用 交叉编译alsa_lib A、环境 系统:Ubuntu16.04 64bit 交叉编译器:arm-linux-gnueabi alsa_lib库版本:alsa-lib-1.1.8.tar.bz2 (下载路径:...
  •  线段交叉判断是最为基础的算法。最简单的场景:判断两个独立的线段是否相交。算法相当简单。把两条线段延长为直线,看直线是否相交,如果相交,判断焦点是否在一条线段上。判断直线是否相交可以转换成一个二元方程...
  • 方法:检查单独B-SES治疗前后的结果(4 Hz,20 min,两个下肢)的即时效果。 结果指标为:髋关节屈曲和内收的ROM和改良Ashworth量表(MAS)。 膝盖屈伸 髋关节屈伸位置的膝关节距离(膝关节距离)。 进行了一项随机...
  • 这里提一点,我并不建议你用虚拟机来搞Linux开发,你的host至少应该是个ubuntu+windows双系统,虚拟机可能有各种问题,不要浪费时间在这些没有意义的问题上,可能会影响到你搞正事的情绪。 配置交叉编译环境 请...
  • 在Ubuntu10.04中建立ARM交叉编译环境

    万次阅读 2011-09-30 11:15:43
    在Ubuntu10.04中建立ARM交叉编译环境   在Linux中建立整个ARM交叉编译环境的整体过程为: 1、  下载源文件 2、  在Linux中建立编译目录并设置环境变量 3、  建立内核头文件 4、  建立二进制工具...
  • 今天本来想看看交叉滞后怎么做,然后给粉丝写写教程,查资料的过程中发现了一篇很好的文献,记录下来分享给大家。 这篇文献主要是讲如何用R的lavaan包做交叉滞后模型的。 文献一开始首先介绍Measurement ...
  • Router Advertisement Daemon (radvd)移植到ARM——交叉编译   IPv6中的路由通告(router advertisement)在linux操作系统中为radvd模块,现在要在arm平台上实现IPv6的路由通告。要将rad
  • 编译环境: 内核名称:Linux 内核发行版:3.0.0-12-generic 内核版本:#20-Ubuntu SMP Fri Oct 7 14:50:42 UTC 2011 硬件架构名称:i686 ...在Linux中建立整个ARM交叉编译环境的整体过程为:  1、
  • 0. 引言 ...linux是unix的克隆版本,是由其创始人Linus和诸多世界知名的黑客手工打造的一个操作系统。为什么linux和unix之间有很多软件可以很轻松的移植?...同时,POSIX标准也是Linux、windows下能够进行交叉编译
  • 各个环境变量的意义如下: PRJROOT:整个交叉编译环境的根目录 TARGET:目标文件对应的architecture,arm-linux表示编译出来的target只能在arm architecture中运行 PREFIX:目标文件夹的...
  • Ubuntu11.04中搭建交叉编译环境(arm-linux-gcc-4.6.1版本)  声明:本文主要参考http://blog.csdn.net/xt_xiaotian/article/details/6836739,并根据实际情况作了一定的修改与说明   编译环境: ...
  • 地统计之检查空间自相关

    千次阅读 2020-03-15 21:05:57
    在ArcGIS中的地统计分析模块中为探究数据集的空间自相关和方向变换提供了现成的工具——半变异函数/协方差云和交叉协方差工具。 工具路径 半变异函数/协方差云 该工具条主要由三部分组成 函数图表 X轴为各位置对的...
  • 交叉验证其实就是为了检查模型的泛化行和稳定性,让模型的输出更加可靠。 因为当我们只将训练数据划分一次时,有可能划分的不好,所以模型的结果会有偏差,不可靠。所以,我们可以使用交叉验证。经常使用的是k-...
  • 昨天终于把交叉编译环境、移植内核和制作root文件系统在arm开发板上顺利跑通了。期间有的步骤很顺利,但更多的是被诸多问题困扰,比如最后一个不起眼的小问题导致文件系统无法加载,郁闷了我一个星期,最终通过分析...
  • 这项随机,交叉研究的目的是研究氯化物负载量对肾血浆流量(RPF),滤过率(FF)和肾小球滤过率(GFR)的影响,以阐明潜在的氯化物输注肾毒性机制。 方法:15名健康男性在接受2L等渗盐水和血浆溶解液治疗后进行了两...
  • tsql可以而QT测试代码不行,那就是配置文件的问题,仔细检查配置文件的路径。也可用下面的代码测试。 QSqlDatabase OpenDB()  {   QSqlDatabase db=QSqlDatabase::addDatabase( "QODBC" ); ...
  • GetLastError 返回值意义

    千次阅读 2012-09-10 17:21:21
    GetLastError()返回值的意义  2007年12月13日 星期四 下午 10:12  〖0〗-操作成功完成。  〖1〗-功能错误。  〖2〗-系统找不到指定的文件。  〖3〗-系统找不到指定的路径。  〖4〗-系统无法打开文件。 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 27,941
精华内容 11,176
关键字:

交叉检查的意义