C语言指针详解

article/2025/8/29 10:05:49

一、什么是指针

C语言里,变量存放在内存中,而内存其实就是一组有序字节组成的数组,每个字节有唯一的内存地址。CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里,数据对象是指存储在内存中的一个指定数据类型的数值或字符串,它们都有一个自己的地址,而指针便是保存这个地址的变量。也就是说:指针是一种保存变量地址的变量

前面已经提到内存其实就是一组有序字节组成的数组,数组中,每个字节大大小固定,都是 8bit。对这些连续的字节从 0 开始进行编号,每个字节都有唯一的一个编号,这个编号就是内存地址。示意如下图:
在这里插入图片描述
 这是一个 4GB 的内存,可以存放 2^32 个字节的数据。左侧的连续的十六进制编号就是内存地址,每个内存地址对应一个字节的内存空间。而指针变量保存的就是这个编号,也即内存地址
我们只需要对两件事情感兴趣:
1.内存中的两个位置由一个独一无二的地址标识。
2.内存中的每个位置都包含一个值。

二、为什么要使用指针

在C语言中,指针的使用非常广泛,因为使用指针往往可以生成更高效、更紧凑的代码。总的来说,使用指针有如下好处:
1)指针的使用使得不同区域的代码可以轻易的共享内存数据,这样可以使程序更为快速高效;
2)C语言中一些复杂的数据结构往往需要使用指针来构建,如链表、二叉树等;
3)C语言是传值调用,而有些操作传值调用是无法完成的,如通过被调函数修改调用函数的对象,但是这种操作可以由指针来完成,而且并不违背传值调用。

三、指针运算符&和*

*&是取地址运算符,是间接运算符

取地址运算符&:单目运算符&是用来取操作对象的地址。例:&i 为取变量 i 的地址。对于常量表达式、寄存器变量不能取地址(因为它们存储在存储器中,没有地址)。

指针运算符(间接寻址符)*:与&为逆运算,作用是通过操作对象的地址,获取存储的内容。例:x = &i,x 为 i 的地址,*x 则为通过 i 的地址,获取 i 的内容。

#include "stdio.h"    int main()
{int a=1;//声明了一个普通变量 aint *pa;//声明一个指针变量,指向变量 a 的地址pa = &a;//通过取地址符&,获取 a 的地址,赋值给指针变量printf("&a=%d\n", &a);//打印变量a的地址printf("pa=%d\n", pa);//其实还是打印pa的地址printf("&pa=%d\n", &pa);//打印生命的指针变量*pa的地址printf("a=%d\n", a);//打印变量a的值printf("*pa=%d\n", *pa);//通过间接寻址符,获取指针指向的内容return 0;
}

程序运行结果如下:
在这里插入图片描述
实际对应关系:
在这里插入图片描述
通俗的讲,指针赋值传递的是地址,使用指针找到的就是指向的地址变量的值,因此修改指针指向的数值可以直接修改对应地址的数据。

四、指针的用法

4.1 声明并初始化一个指针

指针其实就是一个变量,指针的声明方式与一般的变量声明方式没太大区别:

int *p;        // 声明一个 int 类型的指针 p
char *p        // 声明一个 char 类型的指针 p
int *arr[10]   // 声明一个指针数组,该数组有10个元素,其中每个元素都是一个指向 int 类型对象的指针
int (*arr)[10] // 声明一个数组指针,该指针指向一个 int 类型的一维数组
int **p;       // 声明一个指针 p ,该指针指向一个 int 类型的指针

指针的声明比普通变量的声明多了一个一元运算符 “”。运算符 “” 是间接寻址或者间接引用运算符。当它作用于指针时,将访问指针所指向的对象。在上述的声明中: p 是一个指针,保存着一个地址该地址指向内存中的一个变量; *p 则会访问这个地址所指向的变量

声明一个指针变量并不会自动分配任何内存。在对指针进行间接访问之前,指针必须进行初始化或是使他指向现有的内存,或者给他动态分配内存,否则我们并不知道指针指向哪儿,这将是一个很严重的问题,稍后会讨论这个问题。初始化操作如下:

/* 方法1:使指针指向现有的内存 */
int x = 1;
int *p = &x;  // 指针 p 被初始化,指向变量 x ,其中取地址符 & 用于产生操作数内存地址/* 方法2:动态分配内存给指针 */
int *p;
p = (int *)malloc(sizeof(int) * 10);    // malloc 函数用于动态分配内存
free(p);  // free 函数用于释放一块已经分配的内存,常与 malloc 函数一起使用,要使用这两个函数需要头文件 stdlib.h

指针的初始化实际上就是给指针一个合法的地址,让程序能够清楚地知道指针指向哪儿。

4.2、NULL指针

NULL 指针是一个特殊的指针变量,表示不指向任何东西。可以通过给一个指针赋一个零值来生成一个 NULL 指针。
举例:

#include "stdio.h"int main(){int *p = NULL;printf("p的地址为%p\n",p);return 0;
}

程序执行结果:
在这里插入图片描述

4.3 未初始化和非法的指针

如果一个指针没有被初始化,那么程序就不知道它指向哪里。它可能指向一个非法地址,这时,程序会报错,在 Linux 上,错误类型是 Segmentation fault(core dumped),提醒我们段违例或内存错误。它也可能指向一个合法地址,实际上,这种情况更严重,你的程序或许能正常运行,但是这个没有被初始化的指针所指向的那个位置的值将会被修改,而你并无意去修改它。举例如下:

#include "stdio.h"int main(){int *p;*p = 1;printf("%d\n",*p);return 0;  
}

程序执行结果如下所示,虽然没有报错,但是程序并没有正常的运行。
在这里插入图片描述
警告:
但是这个p指向了哪里呢?我们声明了这个变量,但从未对它及进行初始化,所以我们没有办法预测1这个值存储于什么地方。从这一点看,指针变量和其他变量并无区别。如果变量是静态的,它会被初始化为0;但如果变量是自动的,它根本不会被初始化。无论是哪种情况,声明一个指向的整型的指针都不会“创建”用于存储整型值的内存空间。
所以,如果程序执行了这个操作,会发生什么情况呢?如果你运气好,a的初始值是个非法地址,这样的赋值语句将会出错,从而终止程序。在UNIX系统上,这个错误被称为“段违例”或“内存错误”,它提示程序试图访问一个并未分配给程序的内存位置。在一台运行windows的PC上,对未初始化或非法指针进行间接的访问操作是一般保护性异常的根源之一。
一个更为严重的情况是:这个指针偶尔可能包含了一个合法的地址。接下来的事情很简单:位于那个位置的值被修改,虽然你并无意去修改它。像这种类型的错误非常难以捕捉,因为引发错误的代码可能与原先用于操作那个值的代码完全不相干。所以,在你对指针进行间接访问之前,必须非常小心,确保它们已被初始化!

五、指针的指针

指针的指针也叫做双重指针,下面举一个例子说明指针的指针的用法。

int a=12;
int *b=&a;
int **c=&b;

它们在内存中的模样大致如下所示:
在这里插入图片描述
间接操作符具有从右向左的结合性,所以这个表达式相当于*(*c),我们必须从里向外逐层求值。第一个间接符指向的位置,就是变量b;第二个间接符访问这个位置所指向的位置,也就是变量a。如果表达式中出现了间接访问操作符,就随箭头访问它所指向的位置。

表达式相当的表达式
a12
b&a
*ba,12
c&b
*cb,&a
**c*b,a,12

举例:

#include "stdio.h"int main()
{int a=12;int *b=&a;int **c=&b;printf("a=%d\n", a);printf("&a=%d\n", &a);printf("b=%d\n", b);printf("*b=%d\n",*b);printf("a=%d\n", a);printf("c=%d\n", c);printf("&b=%d\n", &b);printf("*c=%d\n", *c);printf("b=%d\n", b);printf("&a=%d\n", &a);printf("**c=%d\n", **c);printf("*b=%d\n", *b);printf("a=%d\n", a);return 0;
}

运行结果:
在这里插入图片描述

六、指针的运算

6.1 赋值运算

指针变量可以互相赋值,也可以赋值某个变量的地址,或者赋值一个具体的地址。

int *px, *py, *pz, x = 10;
//赋予某个变量的地址
px = &x;
//相互赋值
py = px;
//赋值具体的地址
pz = 4000;

6.2 指针与整数的加减运算

指针变量的自增自减运算。指针加 1 或减 1 运算,表示指针向前或向后移动一个单元(不同类型的指针,单元长度不同)。这个在数组中非常常用。

指针变量加上或减去一个整形数。和第一条类似,具体加几就是向前移动几个单元,减几就是向后移动几个单元。

举例:

#include "stdio.h"int main(){
//定义一个一维数组
int a[3]={1,2,3};
//定义一个指针,指向 x
int *px = &a[0];//打印数组的地址
printf("&a[0] = %d\n", &a[0]);
printf("&a[1] = %d\n", &a[1]);
printf("&a[2] = %d\n", &a[2]);
//打印指针的地址,看是否与数组地址一样
printf("px = %d\n", px);
printf("(px+1) = %d\n", (px+1));
printf("(px+2) = %d\n", (px+2));
//打印数组的值
printf("a[0] = %d\n", a[0]);
printf("a[1] = %d\n", a[1]);
printf("a[2] = %d\n", a[2]);
//打印指针的值,看是否与数组的值一样
printf("*px = %d\n", *px);
printf("*(px+1) = %d\n", *(px+1));
printf("*(px+2) = %d\n", *(px+2));return 0;
}

运行结果:
在这里插入图片描述

6.3 关系运算

假设有指针变量 px、py。

px > py ——表示 px 指向的存储地址是否大于 py 指向的地址
px == py ——表示 px 和 py 是否指向同一个存储单元
px == 0 和 px != 0 ——表示 px 是否为空指针

举例:

#include "stdio.h"int main(){
//定义一个数组,数组中相邻元素地址间隔一个单元
int num[2] = {1, 3};//将数组中第一个元素地址和第二个元素的地址赋值给 px、py
int *px = &num[0], *py = &num[1];
int *pz = &num[0];
int *pn;//则 py > px
if(py > px){printf("py 指向的存储地址大于 px 所指向的存储地址\n");
}//pz 和 px 都指向 num[0]
if(pz == px){printf("px 和 pz 指向同一个地址\n");
}//pn 没有初始化
if(pn == NULL || pn == 0){printf("pn 是一个空指针\n");
}return 0;
}

运行结果:
在这里插入图片描述

七、数组和指针

7.1 一维数组

指针和数组并不是相等的,可以考虑下面的两个声明:

int a[3]={1,2,3};//声明个一维数组
int *b;//声明一个指针
b=a;//数组名a代表数组的第一个值的地址,将该值赋值给指针b
//b=&a[0];//也可以使用这种方式赋值
//int *b = &a[0];

机器地址和数值具体对应关系如下:
在这里插入图片描述

举例:

#include "stdio.h"int main(){int a[3]={1,2,3};//声明个一维数组int *b;//声明一个指针b=a;//数组名a代表数组的第一个值的地址,将该值赋值给指针b//b=&a[0];//也可以使用这种方式赋值//int *b = &a[0];//打印数组的地址printf("打印数组的地址\n");printf("&a[0] = %d\n", &a[0]);printf("&a[1] = %d\n", &a[1]);printf("&a[2] = %d\n", &a[2]);//打印指针的地址,看是否与数组地址一样printf("打印指针的地址,看是否与数组地址一样\n");printf("b = %d\n", b);printf("(b+1) = %d\n", (b+1));printf("(b+2) = %d\n", (b+2));//打印数组的值printf("打印数组的值\n");printf("a[0] = %d\n", a[0]);printf("a[1] = %d\n", a[1]);printf("a[2] = %d\n", a[2]);//打印指针的值,看是否与数组的值一样printf("打印指针的值,看是否与数组的值一样\n");printf("*b = %d\n", *b);printf("*(b+1) = %d\n", *(b+1));printf("*(b+2) = %d\n", *(b+2));return 0;
}

运行结果:
在这里插入图片描述

7.2 二维数组

由于计算机的内存是一维的,多维数组的元素应排成线性序列后存入存储器。数组一般不做插入和删除操作,即结构中元素个数和元素间的关系不变。所以采用顺序存储方法表示数组。

1、 行优先存储——将数组元素按行向量排列,第i+1个行向量紧接在第i个行向量后面。
2、 列优先存储——将数组元素按列向量排列,第i+1个列向量紧接在第i个列向量后面。

声明一个二维数组和指针:

int a[2][3]={{1,2,3},{4,5,6}};//声明个二维数组
int *b;//声明一个指针
b=a[0];//数组名a代表数组的第一个值的地址,将该值赋值给指针b
//b=&a[0][0];//也可以使用这种方式赋值
//int *b = &a[0][0];

机器地址和数值具体对应关系如下:
在这里插入图片描述
举例:

#include "stdio.h"int main(){int a[2][3]={{1,2,3},{4,5,6}};//声明个二维数组int *b;//声明一个指针b=a[0];//数组名a代表数组的第一个值的地址,将该值赋值给指针b//b=&a[0][0];//也可以使用这种方式赋值//int *b = &a[0][0];//打印数组的地址printf("打印数组的地址\n");printf("&a[0][0] = %d\n", &a[0][0]);printf("&a[0][1] = %d\n", &a[0][1]);printf("&a[0][2] = %d\n", &a[0][2]);printf("&a[1][0] = %d\n", &a[1][0]);printf("&a[1][1] = %d\n", &a[1][1]);printf("&a[1][2] = %d\n", &a[1][2]);//打印指针的地址,看是否与数组地址一样printf("打印指针的地址,看是否与数组地址一样\n");printf("b = %d\n", b);printf("(b+1) = %d\n", (b+1));printf("(b+2) = %d\n", (b+2));printf("(b+3) = %d\n", (b+3));printf("(b+4) = %d\n", (b+4));printf("(b+5) = %d\n", (b+5));//打印数组的值printf("打印数组的值\n");printf("a[0][0] = %d\n", a[0][0]);printf("a[0][1] = %d\n", a[0][1]);printf("a[0][2] = %d\n", a[0][2]);printf("a[1][0] = %d\n", a[1][0]);printf("a[1][1] = %d\n", a[1][1]);printf("a[1][2] = %d\n", a[1][2]);//打印指针的值,看是否与数组的值一样printf("打印指针的值,看是否与数组的值一样\n");printf("*b = %d\n", *b);printf("*(b+1) = %d\n", *(b+1));printf("*(b+2) = %d\n", *(b+2));printf("*(b+3) = %d\n", *(b+3));printf("*(b+4) = %d\n", *(b+4));printf("*(b+5) = %d\n", *(b+5));return 0;
}

运行结果:
在这里插入图片描述

7.3 指针数组

指针数组——它实际上是一个数组,数组的每个元素存放的是一个指针类型的元素。指针数组可以说成是”指针的数组”,首先这个变量是一个数组,其次,”指针”修饰这个数组,意思是说这个数组的所有元素都是指针类型,在32位系统中,指针占四个字节。
在这里插入图片描述

7.4 数组指针

数组指针——它实际上是一个指针,该指针指向一个数组。数组指针可以说成是”数组的指针”,首先这个变量是一个指针,其次,”数组”修饰这个指针,意思是说这个指针存放着一个数组的首地址,或者说这个指针指向一个数组的首地址。
在这里插入图片描述

指针数组和数组指针举例:

#include "stdio.h"int  main(){int *a[4]; //指针数组int a1[2][4]={{1,2,3,4},{5,6,7,8}};//将数组a1中元素赋给数组afor(int i=0;i<2;i++){a[i]=a1[i];//这里int *a[4] 表示一个一维数组内存放着四个指针变量,分别是a[0]、a[1]、a[2]、a[3]}int (*b)[2]; //数组指针,该语句是定义一个数组指针,指向含4个元素的一维数组。int b1[4][2]={{1,2},{3,4},{5,6},{7,8}};b=b1;将该二维数组的首地址赋给p,也就是a[0]或&a[0][0]printf("*(a[0])=%d\n",*(a[0]));			//输出1就对printf("*(a[0]+1)=%d\n",*(a[0]+1));		//输出2就对printf("*(a[0]+2)=%d\n",*(a[0]+2));		//输出3就对printf("*(a[0]+3)=%d\n",*(a[0]+3));		//输出4就对//该语句表示a数组指向下一个数组元素。注:此数组每一个元素都是一个指针printf("*(a[1])=%d\n",*(a[1]));			//输出5就对printf("*(a[1]+1)=%d\n",*(a[1]+1));		//输出6就对printf("*(a[1]+2)=%d\n",*(a[1]+2));		//输出7就对printf("*(a[1]+3)=%d\n",*(a[1]+3));		//输出8就对printf("(*b)[0]=%d\n",(*b)[0]);			//输出3就对printf("(*b)[1]=%d\n",(*b)[1]);			//输出7就对//该语句执行过后,也就是b=b+1;p跨过行b1[0][]指向了行b1[1][]printf("(*(b+1))[0]=%d\n",(*(b+1))[0]);	//输出3就对printf("(*(b+1))[1]=%d\n",(*(b+1))[1]);	//输出3就对printf("(*(b+2))[0]=%d\n",(*(b+2))[0]);	//输出3就对printf("(*(b+2))[1]=%d\n",(*(b+2))[1]);	//输出3就对printf("(*(b+3))[0]=%d\n",(*(b+3))[0]);	//输出3就对printf("(*(b+3))[1]=%d\n",(*(b+3))[1]);	//输出3就对return 0;
}

程序运行结果:
在这里插入图片描述
数组指针只是一个指针变量,似乎是C语言里专门用来指向二维数组的,它占有内存中一个指针的存储空间。指针数组是多个指针变量,以数组形式存在内存当中,占有多个指针的存储空间。

还需要说明的一点就是,同时用来指向二维数组时,其引用和用数组名引用都是一样的。
比如要表示数组中i行j列一个元素:
(p[i]+j)、((p+i)+j)、((p+i))[j]、p[i][j]

八、结构体和指针

8.1 结构体的存储格式

struct是一种复合数据类型,其构成元素既可以是基本数据类型(如int、long、float等)的变量,也可以是一些复合数据类型(如array、struct、union等)的数据单元。对于结构体,编译器会自动进行成员变量的对齐,以提高运算效率。缺省情况下,编译器为结构体的每个成员按其自然对齐(natural alignment)条件分配空间。各个成员按照它们被声明的顺序在内存中顺序存储,第一个成员的地址和整个结构的地址相同

自然对齐(natural alignment)即默认对齐方式,是指按结构体的成员中(类型)size最大的成员作为基本的分配单元,而且与其顺序有这密切的联系。

结构体的存储:

1、结构体整体空间是占用空间最大的成员(的类型)所占字节数的整数倍。
2.、结构体的每个成员相对结构体首地址的偏移量(offset)都是最大基本类型成员字节大小的整数倍,如果不是编译器会自动补齐,

举例:

#include "stdio.h"
//定义一个结构体
typedef struct test{int a;float c;int b[3];}test;int  main(){test d;//结构体声明d.a=1;//结构体初始化for(int i=0;i<3;i++){d.b[i]=2+i;}d.c=5.6;//打印结构体内的数值printf("d.a=%d\n",d.a);printf("d.c=%f\n",d.c);printf("d.b[0]=%d\n",d.b[0]);printf("d.b[1]=%d\n",d.b[1]);printf("d.b[2]=%d\n",d.b[2]);//打印结构体的地址printf("&d.a=%d\n",&d.a);printf("&d.c=%d\n",&d.c);printf("&d.b[0]=%d\n",&d.b[0]);printf("&d.b[1]=%d\n",&d.b[1]);printf("&d.b[2]=%d\n",&d.b[2]);//打印结构体所占的字节数printf("int占=%d\n",sizeof(int));printf("float占=%d\n",sizeof(float));printf("b[3]占=%d\n",sizeof(d.b));printf("sizeof(test)占=%d\n",sizeof(test));return 0;
}

程序运行结果:
在这里插入图片描述
存储格式:
在这里插入图片描述

8.2 结构体指针

喜欢使用指针的人一定很高兴能使用只想结构的指针。至少有4个理由可以解释为何要使用指向结构的指针。第一,就像指向数组的指针比数组本身更容易操作一样,指向结构的指针通常比结构本身更容易操作。第二,在一些早期的C实现中,结构不能作为参数传递给函数,但是可以传递指向结构的指针。第三,即使能传递一个结构,传递指针通常更有效率。第四,一些用于表示数据的结构中包含只想其他结构的指针。
具体举例如下所示:

#include "stdio.h"
//定义一个新的结构体
typedef struct test{int a;float c;
}test;int  main(){test d;//声明结构体d.a=1;//结构体初始化d.c=5.6;test *f;//声明结构体指针f=&d;//结构体指针初始化//以不同的方式打印结构体指针的变量printf("(*f).a=%d\n",f->a);//第一种方式打印结构体指针变量,使用“->”运算符printf("(*f).a=%d\n",(*f).a);//第二种方式打印结构体指针变量初始化printf("d.a=%d\n",d.a);printf("(*f).c=%f\n",f->c);printf("(*f).c=%f\n",(*f).c);printf("d.c=%f\n",d.c);return 0;
}

运行结果如下:
在这里插入图片描述
用指针访问成员变量,下面关系是恒成立的:

d.a==(*f).a==f->a

九、指针和函数

C和C++中经常会用到指针,和数据项一样,函数也是有地址的,函数的地址是存储其机器语言代码的内存的开始地址。

指针函数和函数指针经常会混淆,一个是返回值是指针,另一个是指向函数的地址,下面就分别解释指针函数和函数指针的区别。

9.1 指针函数

指针函数是 返回指针的函数主体是函数,返回值是一个指针
基本声明形式:返回数据类型 + * + 函数名 + (变量类型1,…);

int* fun(int,int);  
int * fun(int,int);
int *fun(int,int);

举例:

#include<stdio.h>
int* fun(int* x)    //传入指针  
{int* tmp = x;	  //指针tmp指向xreturn tmp;       //返回tmp指向的地址
}
int main()
{int b = 2;      int* p = &b;   //p指向b的地址printf("%d",*fun(p));//输出p指向的地址的值return 0;
}

运行结果:
在这里插入图片描述

9.2 函数指针

函数指针是 指向函数的指针 主体是指针 指向的是一个函数的地址
基本声明形式:返回数据类型 + (*函数名) + (变量类型1,…);
注意 * 和函数名要用括号括起来,否则因为运算符的优先级原因就变成指针函数了
函数指针的参数列表要和函数指针指向的函数的参数列表一致。

int (*fun) (int);

举例:

#include<stdio.h>
int add(int x,int y)
{return x + y;
}
int (*fun) (int,int);			//声明函数指针
int main()
{fun = &add;					//fun函数指针指向add函数printf("%d ",fun(3,5));		//使用函数指针时使用fun(3,5)和(*fun)(3,5)都可以printf("%d",(*fun)(4,2));return 0;
}

运行结果:
在这里插入图片描述

参考资料:
《C Primer Plus(第六版)中文版》
《C和指针》


http://chatgpt.dhexx.cn/article/Y6C4rMHM.shtml

相关文章

C语言之指针详解

文章目录 1 指针1.1 简介1.2 什么是指针1.2.1 定义1.2.2 指针表示1.2.3 为什么*p&a不正确 1.3 使用指针1.3.1 简单使用1.3.2 NULL 指针1.3.3 指针算术运算1.3.3.1 定义1.3.3.2 遍历数组&#xff1a;递增一个指针1.3.3.3 遍历数组&#xff1a;递减一个指针1.3.3.4 指针的比较…

c语言—指针详解

文章目录 一、指针是什么二、指针和指针变量1.左值与右值2.两者的区别 三、指针和指针类型1.定义指针2.大小端3.指针的解引用 四、野指针野指针成因如何规避野指针 五、指针运算1.指针- 整数2.指针-指针3.指针的关系运算 六、指针和数组七、二级指针八、指针数组和数组指针1.指…

机器学习主动学习和半监督学习

一、主动学习&#xff08;active learning&#xff09; 学习器能够主动选择包含信息量大的未标注的样例并将其交由专家进行标注&#xff0c;然后置入训练集进行训练&#xff0c;从而在训练集较小的情况下获得较高的分类正确率&#xff0c;这样可以有效的降低构建高性能分类器的…

active learning主动学习

active learning 是半监督式的机器学习的一种&#xff0c;这种机器学习算法能够交互式地查询用户或者信息源&#xff0c;从而对于一个新的数据样例得到可人的输出。在统计学文献中&#xff0c;它有时也被称为最佳实验设计。 在这样的一种情形下&#xff1a;无标签的数据量很大…

深度主动学习综述2020

A Survey of Deep Active Learning 中文版仅作参考&#xff0c;以正式的pdf版为主。 https://arxiv.org/pdf/2009.00236.pdf 西北大学等最新《深度主动学习》全面综述论文&#xff0c;30页pdf abstract 主动学习试图通过标记最少量的样本使得模型的性能收益最大化。而深度学习…

每日一学-- 主动学习(active learning)

1. 在机器学习中&#xff0c;有监督学习、半监督学习、无监督学习。 在使用监督学习时&#xff0c;模型在标注的数据中学习信息&#xff0c;而存在的问题就是有大量的数据需要标注&#xff0c;非常费时费力。so主动学习为我们提供了方法&#xff0c;通过一定的算法找出最有用的…

一张图展示被动学习与主动学习的效率差距

一张图展示被动学习与主动学习的效率差距 起因一张图 起因 由于工作原因。最近的一段时间&#xff0c;又回到了大量的学习实践当中。之前的主观感受是&#xff0c;通过文字语音视频结合的多渠道信息获取方式学到的东西&#xff0c;记忆会比自己只是看文字&#xff0c;读文字&a…

深度学习 主动学习(Active Learning)概述、策略和不确定性度量

文章目录 主动学习概念策略基于数据流的主动学习方法基于数据池的主动学习方法基于查询的主动学习方法 不确定性度量 参考 主动学习 概念 主动学习是指对需要标记的数据进行优先排序的过程&#xff0c;这样可以确定哪些数据对训练监督模型产生最大的影响。主动学习不是一次为…

主动学习-综述

主动学习是机器学习&#xff08;更普遍的说是人工智能&#xff09;的一个子领域&#xff0c;在统计学领域也叫查询学习、最优实验设计”(Active learning (sometimes called “query learning” or “optimal experimental design” in the statistics literature) is a subfie…

深度学习--主动学习

主动学习简介 主动学习是指对需要标记的数据进行优先排序的过程&#xff0c;这样可以确定哪些数据对训练监督模型产生最大的影响。主动学习是一种学习算法可以交互式查询用户(teacher 或 oracle)&#xff0c;用真实标签标注新数据点的策略。主动学习的过程也被称为优化实验设计…

机器学习/深度学习几种典型学习范式|主动学习

机器学习/深度学习几种典型学习范式|主动学习 主动学习&#xff08;Active Learning,AL&#xff09;&#xff1a;Introduction主动学习的例子 应用场景成员查询合成流式选择抽样基于池的主动学习 查询策略框架不确定性抽样Uncertainty Sampling基于委员会的查询Query-By-Commit…

机器学习中的主动学习(Active Learning)

最近在做主动学习相关的东西&#xff0c;随着深入了解和学习对于某些东西有一些模糊&#xff0c;先将所见所感整理如下&#xff0c;如有不正确之处希望大佬能够指正&#xff1a; 1.主动学习 1.1关键问题 对于监督学习模型&#xff0c;足够多的已标注样例是获得高精度分类器的…

主动学习数据标注

active learning与passive(supervised) learning最大的不同是其不需要大量的专家标注样本训练模型。 主动学习是利用少量标注样本&#xff0c;然后由模型&#xff08;Learner&#xff09;主动选择hard sample返回给用户或专家&#xff08;Oracle&#xff09;打标签&#xff0c;…

浅谈主动学习(Active Learning)

1背景概述 在机器学习领域有很多学习模式&#xff0c;比方说监督学习、半监督学习、强化学习、无监督学习等。平时大家接触比较多的一般都是监督学习&#xff0c;在监督学习里面&#xff0c;比方说要做个人和鱼的图像分类模型&#xff0c;假设有200张图片&#xff0c;那就需要把…

深度主动学习综述(Deep Active Learning)

原文 Abstract 主动学习试图通过标记最少量的样本使得模型的性能收益最大化。而深度学习则对数据比较贪婪&#xff0c;需要大量的数据供给来优化海量的参数&#xff0c;从而使得模型学会如何提取高质量的特征。近年来&#xff0c;由于互联网技术的快速发展&#xff0c;使得我…

AL-实体抽取主动学习调研

实体抽取主动学习调研 文章目录 实体抽取主动学习调研资料前言相关文献阅读一、主动学习与自学习的中文命名实体识别算法流程图 二、DEEP ACTIVE LEARNING FOR NAMED ENTITYRECOGNITION三、Visual Active Learning for Labeling: A Case for Soundscape四、Interactive visual …

《异常检测——从经典算法到深度学习》15 通过无监督和主动学习进行实用的白盒异常检测

《异常检测——从经典算法到深度学习》 0 概论1 基于隔离森林的异常检测算法 2 基于LOF的异常检测算法3 基于One-Class SVM的异常检测算法4 基于高斯概率密度异常检测算法5 Opprentice——异常检测经典算法最终篇6 基于重构概率的 VAE 异常检测7 基于条件VAE异常检测8 Donut: …

主动学习简单教程及代码示例

本文是这篇文章的&#xff08;翻译&#xff09;简化版。 本文代码地址 已经不止一次有人说代码地址打不开&#xff0c;但是每次我都打得开。。这里放个阿里云的地址吧Active_Learning_Tutorial.ipynb。需要的去阿里云下载文件就行了。 建议直接看代码地址&#xff08;代码地…

主动学习研究现状

主动学习研究现状 一. 传统查询策略&#xff08;Query Strategy&#xff09;二. 在图像分类的应用三. 在目标检测的研究3.1.《Localization-Aware Active Learning for Object Detection 》(ACCV, 2018)3.2. 《Active Learning for Deep Object Detection via Probabilistic Mo…

什么是主动学习?

机器学习算法特别需要数据&#xff0c;需要成千上万的例子才能做出明智的决定。为我们的算法提供高质量的训练数据是一项昂贵的任务。主动学习是一种优化构建有效机器学习系统所需人力的策略。 主动学习定义 主动学习是一种机器学习训练策略&#xff0c;它使算法能够主动识别…