Merge branch 'master' of gitee.com:Eyestorm/notes
@@ -1,12 +1,7 @@
|
||||
# 拷贝控制
|
||||
|
||||
> 目录
|
||||
> * 拷贝、赋值与销毁
|
||||
> * 拷贝控制和资源管理
|
||||
> * 交换操作
|
||||
> * 拷贝控制实例
|
||||
> * 动态内存管理类
|
||||
> * 对象移动
|
||||
> 参考文献
|
||||
> * [https://www.cnblogs.com/sunchaothu/p/11392116.html](https://www.cnblogs.com/sunchaothu/p/11392116.html)
|
||||
|
||||
> 类的特殊函数
|
||||
> * 初始化——构造函数
|
||||
@@ -14,10 +9,20 @@
|
||||
> * 移动——移动构造函数
|
||||
> * 赋值——拷贝赋值运算符、移动赋值运算符
|
||||
> * 销毁——析构函数
|
||||
```
|
||||
默认构造(无参) T()
|
||||
|
||||
拷贝构造 T(const T& )
|
||||
移动构造 T()
|
||||
|
||||
拷贝赋值 T& operator=(T& )
|
||||
移动赋值 T& operator=(T&& )
|
||||
|
||||
析构 ~T()
|
||||
```
|
||||
## 1 构造函数
|
||||
|
||||
> 与类同名的,没有返回值的函数,用来创建、赋值、移动、销毁该类的对象。
|
||||
> 与类同名的,没有返回值的函数,用来创建、拷贝、移动、销毁该类的对象。
|
||||
## 1.1 合成构造函数
|
||||
|
||||
编译器自动生成的一系列构造函数。包括以下几种
|
||||
@@ -29,11 +34,11 @@
|
||||
* 合成析构函数
|
||||
* 系统自动生成的析构函数。
|
||||
|
||||
## 1.2 默认构造函数
|
||||
## 1.2 默认构造函数和普通构造函数
|
||||
* 默认构造函数是无参构造函数
|
||||
* 普通构造函数是一系列有参数的构造函数。
|
||||
|
||||
无参构造函数。
|
||||
|
||||
## 1.3 拷贝构造函数
|
||||
## 1.3 拷贝构造函数和拷贝赋值运算符
|
||||
|
||||
唯一参数是当前类类型,或者当前类型的const引用。
|
||||
|
||||
@@ -57,15 +62,88 @@ string nies = string("efji");
|
||||
* 从一个返回类型为费引用类型的函数返回一个对象
|
||||
* 用花括号列表初始化一个数组中的元素或一个聚合类中的成员
|
||||
|
||||
### 赋值运算符(拷贝运算符)
|
||||
### 赋值运算符(拷贝赋值运算符)
|
||||
|
||||
> 普通赋值的时候,会调用重载的赋值运算符。
|
||||
|
||||
* 编译器会自动生成合成拷贝赋值运算符
|
||||
* 需要重载赋值运算符。
|
||||
|
||||
## 1.4 移动构造函数
|
||||
## 1.4 移动构造函数和移动赋值运算符
|
||||
|
||||
* 在面向对象中,有的类是可以拷贝的,例如车、房等他们的属性是可以复制的,可以调用拷贝构造函数,有点类的对象则是独一无二的,或者类的资源是独一无二的,比如 IO 、 std::unique_ptr等,他们不可以复制,但是可以把资源交出所有权给新的对象,称为可以移动的。
|
||||
* C++11最重要的一个改进之一就是引入了move语义,这样在一些对象的构造时可以获取到已有的资源(如内存)而不需要通过拷贝,申请新的内存,这样移动而非拷贝将会大幅度提升性能。例如有些右值即将消亡析构,这个时候我们用移动构造函数可以接管他们的资源。
|
||||
```
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A{
|
||||
public:
|
||||
//默认构造函数
|
||||
A():i(new int[500]){
|
||||
cout<<"class A construct!"<<endl;
|
||||
}
|
||||
//拷贝构造函数
|
||||
A(const A &a):i(new int[500]){
|
||||
memcpy(i, a.i,500*sizeof(int));
|
||||
cout<<"class A copy!"<<endl;
|
||||
}
|
||||
//拷贝赋值运算符
|
||||
A &operator =(A &rhs) noexcept{
|
||||
// check self assignment
|
||||
if(this != &rhs){
|
||||
delete []i;
|
||||
i = rhs.i;
|
||||
}
|
||||
cout<< "class A copy and assignment"<<std::endl;
|
||||
return *this;
|
||||
}
|
||||
//移动构造函数
|
||||
A(A &&a)noexcept:i(a.i)
|
||||
{
|
||||
a.i = nullptr;
|
||||
cout<< "class A move"<<endl;
|
||||
}
|
||||
//移动赋值运算符
|
||||
A &operator =(A &&rhs) noexcept{
|
||||
// check self assignment
|
||||
if(this != &rhs){
|
||||
delete []i;
|
||||
i = rhs.i;
|
||||
rhs.i = nullptr;
|
||||
}
|
||||
cout<< "class A move and assignment"<<std::endl;
|
||||
return *this;
|
||||
}
|
||||
//析构函数
|
||||
~A(){
|
||||
delete []i;
|
||||
cout<<"class A destruct!"<<endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int *i;
|
||||
};
|
||||
|
||||
A get_A_value(){
|
||||
return A();
|
||||
}
|
||||
void pass_A_by_value(A a){
|
||||
|
||||
}
|
||||
int main(){
|
||||
A a = get_A_value();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
* 在移动构造函数中,我们做了什么呢,我们只是获取了被移动对象的资源(这里是内存)的所有权,同时把被移动对象的成员指针置为空(以避免移动过来的内存被析构),这个过程中没有新内存的申请和分配,在大量对象的系统中,移动构造相对与拷贝构造可以显著提高性能!这里noexcept告诉编译器这里不会抛出异常,从而让编译器省一些操作(这个也是保证了STL容器在重新分配内存的时候(知道是noexpect)而使用移动构造而不是拷贝构造函数),通常移动构造都不会抛出异常的。
|
||||
|
||||
注意事项:
|
||||
* 偷梁换柱直接“浅拷贝”右值引用的对象的成员;
|
||||
* 需要把原先右值引用的指针成员置为 nullptr,以避免右值在析构的时候把我们浅拷贝的资源给释放了;
|
||||
* 移动构造函数需要先检查一下是否是自赋值,然后才能先delet自己的成员内存再浅拷贝右值的成员,始终记住第2条。
|
||||
|
||||
## 1.5 委托构造函数
|
||||
|
||||
@@ -110,4 +188,32 @@ class Foo{
|
||||
### 析构函数必须是虚函数
|
||||
|
||||
1. 删除动态运行时的具体对象。
|
||||
2. 普通对象如果不被继承,析构函数可以不使用虚函数。避免生成虚函数表和虚函数指针,浪费内存空间。
|
||||
2. 普通对象如果不被继承,析构函数可以不使用虚函数。避免生成虚函数表和虚函数指针,浪费内存空间。
|
||||
|
||||
|
||||
## 4 三五法则
|
||||
|
||||
在较新的 C++11 标准中,为了支持移动语义,又增加了移动构造函数和移动赋值运算符,这样共有五个特殊的成员函数,所以又称为“C++五法则”;也就是说,“三法则”是针对较旧的 C++89 标准说的,“五法则”是针对较新的 C++11 标准说的;为了统一称呼,后来人们干把它叫做“C++ 三/五法则”;
|
||||
|
||||
1. 需要析构函数的类也需要拷贝构造函数和拷贝赋值函数。
|
||||
2. 需要拷贝操作的类也需要赋值操作,反之亦然。
|
||||
3. 析构函数不能是删除的
|
||||
4. 如果一个类有删除的或不可访问的析构函数,那么其默认和拷贝构造函数会被定义为删除的。
|
||||
5. 如果一个类有const或引用成员,则不能使用合成的拷贝赋值操作。
|
||||
|
||||
|
||||
## 5 概念区分:声明declare、定义define、初始化initialize、赋值assign
|
||||
|
||||
### 声明declare
|
||||
* 声明一个符号。如果有extern,则表示变量在外部顶底,链接其他问件事,匹配外部定义的变量。
|
||||
|
||||
### 定义define
|
||||
* 分配内存、指定变量名。
|
||||
|
||||
### 初始化initialize
|
||||
* 对象创建时获得的初始值。初始化的含义是,在创建变量的时候赋予其一个初始值。
|
||||
|
||||
### 赋值assign
|
||||
|
||||
* 赋值的含义是,将当前的值擦除,而以一个新的值来代替。
|
||||
* 不能是简单的覆盖,将当前值擦除,需要调用当前对象的析构函数,对指针变量进行析构,如果只是简单的覆盖,肯定不行。
|
||||
183
C++/高级特性/1 C++左值右值.md
Normal file
@@ -0,0 +1,183 @@
|
||||
# 左值右值
|
||||
|
||||
> 参考文献
|
||||
> * [cnblogs.com/sunchaothu/p/11343517.html](cnblogs.com/sunchaothu/p/11343517.html)
|
||||
|
||||
|
||||
> 为了导入右值和移动语义,首先复习了以下临时对象在函数返回值和传参数时构造了几次;然后对比介绍了左值和右值,以及右值引用的形式和含义。为移动语义和完美转发的介绍做铺垫。
|
||||
## 1 问题导入
|
||||
|
||||
C++11 引入了 std::move 语义、右值引用、移动构造和完美转发这些特性。
|
||||
|
||||
|
||||
* 函数返回值是传值的时候发生几次对象构造、几次拷贝?
|
||||
* 函数的形参是值传递的时候发生几次对象构造?
|
||||
|
||||
### 函数返回值原理
|
||||
```
|
||||
// main.cpp
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
|
||||
class A{
|
||||
public:
|
||||
A(){
|
||||
cout<<"class A construct!"<<endl;
|
||||
}
|
||||
A(const A&){
|
||||
cout<<"class A copy!"<<endl;
|
||||
}
|
||||
A& operator=(const A&){
|
||||
cout<<"assignment called!"<<endl;
|
||||
}
|
||||
~A(){
|
||||
cout<<"class A destruct!"<<endl;
|
||||
}
|
||||
};
|
||||
|
||||
A get_A_value(){
|
||||
return A();
|
||||
}
|
||||
int main(){
|
||||
A a = get_A_value();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
使用 g++ 编译;注意使用 -fno-elide-constructors关闭省略构造优化
|
||||
|
||||
```
|
||||
g++ main.cpp -fno-elide-constructors
|
||||
```
|
||||
可以得到以下输出
|
||||
```
|
||||
class A construct!
|
||||
class A copy!
|
||||
class A destruct!
|
||||
class A copy!
|
||||
class A destruct!
|
||||
class A destruct!
|
||||
```
|
||||
|
||||
|
||||
可以看到A a=get_A_value(); 一行代码居然产生1次对象构造和2次对象的拷贝构造!具体为
|
||||
|
||||
1. 在 get_A_value() 里 A() 构造了临时对象,发生了一次默认构造;
|
||||
2. 函数返回的时候会把临时对象拷贝后作为返回值,发生一次拷贝构造;
|
||||
3. A a = 函数返回值发生了拷贝构造。
|
||||
|
||||
如果使用编译器优化(默认), 则会把临时对象拷贝的那次 和 用返回值构造最终对象的拷贝的给省略了;也即,只有一次构造和析构。
|
||||
```
|
||||
class A construct!
|
||||
class A destruct!
|
||||
```
|
||||
|
||||
### 函数参数原理
|
||||
|
||||
```
|
||||
// ... A
|
||||
|
||||
void pass_A_by_value(A a){
|
||||
|
||||
}
|
||||
int main(){
|
||||
A a;
|
||||
pass_A_by_value(a);
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
在去掉优化 g++ main.cpp -fno-elide-constructors时输出为
|
||||
```
|
||||
class A construct!
|
||||
class A copy!
|
||||
class A destruct!
|
||||
class A destruct!
|
||||
```
|
||||
|
||||
* 1次构造加上1次拷贝。
|
||||
|
||||
|
||||
### 总结拷贝构造函数
|
||||
|
||||
事实上,在未经优化的情况下,以下时候拷贝构造函数会被调用:
|
||||
|
||||
1. 函数内的局部对象做为返回值返回(不是引用)的时候会发生拷贝(拷贝为临时对象返回)
|
||||
2. 函数形参为传值的时候,会发生拷贝构造
|
||||
3. 一个对象以另外一个对象进行初始化的时候
|
||||
|
||||
对象的频繁构造是程序的开销,特别是当对象内部有堆上内存(比如有 new 出来的成员)的时候,每次拷贝构造的时候都需要用 new 申请一块内存,造成性能的降低。对于情况2,好习惯是如果函数参数是只读的(也即不会在程序内进行修改),传引用作为参数,也即 pass_A_by_refrence(const A &a); 对于情况1,编译器会为我们进行优化; 对于情况3,C++11 引入了一种移动构造函数的概念,它将获取**右值引用*,右值的“资源” move 到新对象中,这个过程中不会申请新的内存,从而达到提高了效率和性能。
|
||||
|
||||
所以,要理解些关键词 “移动构造”、“移动语义” ,首先要理解右值和右值引用。
|
||||
|
||||
## 2 左值(lvalue)和右值(rvalue)
|
||||
|
||||
### 概念
|
||||
|
||||
左值的英文简写为“lvalue”,右值的英文简写为“rvalue”。很多人认为它们分别是"left value"、"right value" 的缩写,其实不然。lvalue 是“loactor value”的缩写,可意为存储在内存中、有明确存储地址(可寻址)的数据,而 rvalue 译为 "read value",指的是那些可以提供数据值的数据(不一定可以寻址,例如存储于寄存器中的数据)。
|
||||
|
||||
```C++
|
||||
A a = foo(); // foo() 为右值
|
||||
int a = 5; //5字面量为右值
|
||||
char *x = "thu"; // “thu”为字面值也为右值
|
||||
a = b + c; // b + c这个结果也是一个右值
|
||||
return a //临时对象,也即函数返回值的时候只会“临时”存在的对象(运行超过那一行就会结束它的生存期),这个临时返回值就是一个右值;
|
||||
```
|
||||
|
||||
* 位于赋值运算符 = 右边的值,为右值;在左边的则为左值
|
||||
|
||||
* 左值可以取得地址、有名字; 不可以取得地址、没有名字的为右值。所以 A a = foo()可以用 &a取得a的地址,a 是左值,然是不能取得 foo()的地址,(&foo())无法通过编译, foo()返回的临时对象也是没有名字的,所以是右值。
|
||||
|
||||
* 在C++11中,右值包括两种,一中是将亡值(xvalue, eXpiring Value),一种是纯右值(prvalue,Pure Rvalue)[1]。函数非引用返回的临时对象、运算表达式的结果、1, 3.14,'c'这样的字面值等都属于纯右值。而xvalue则是由 C++11引入的 如返回值为 A&& 的函数返回值或者std::move()的返回值等。
|
||||
|
||||
|
||||
|
||||
## 3 左值引用和右值引用
|
||||
|
||||
### 左值引用
|
||||
|
||||
左值引用就是一般的引用,一般用一个&表示,例如
|
||||
|
||||
```
|
||||
const A &a_ref = a; // 取得对象 a 的引用
|
||||
```
|
||||
|
||||
左值引用相当于别名,指向一个具体的对象。
|
||||
|
||||
|
||||
### 右值引用
|
||||
|
||||
|
||||
右值引用顾名思义,就是右值的引用, 用 &&表示;
|
||||
```
|
||||
A &&r_ref = getRvalue(); // r_ref 是一个右值引用
|
||||
```
|
||||
右值引用也相当于别名,与左值的区别为右值引用是无名变量的别名。
|
||||
|
||||
getRvalue() 是一个返回右值的函数,右值在这一句执行完就该结束他的生存期了,如果是对象就该调用析构函数了;但是右值引用让它强行续命;使用右值引用指向右值,右值的生存期和右值引用一样长了,这也就少一次对象的析构和构造了。
|
||||
|
||||
C++的右值引用主要有两个用处,
|
||||
* 一个是移动语义
|
||||
* 一个是完美转发。
|
||||
|
||||
### 性质补充
|
||||
|
||||
|
||||
* 虽然 C++98/03 标准不支持为右值建立非常量左值引用,但允许使用常量左值引用操作右值。也就是说,常量左值引用既可以操作左值,也可以操作右值,例如:
|
||||
```
|
||||
int num = 10;
|
||||
const int &b = num;
|
||||
const int &c = 10;
|
||||
```
|
||||
* 和声明左值引用一样,右值引用也必须立即进行初始化操作,且只能使用右值进行初始化
|
||||
```
|
||||
int num = 10;
|
||||
//int && a = num; //右值引用不能初始化为左值
|
||||
int && a = 10;
|
||||
```
|
||||
|
||||
* 和常量左值引用不同的是,右值引用还可以对右值进行修改。例如:
|
||||
```
|
||||
int && a = 10;
|
||||
a = 100;
|
||||
cout << a << endl;
|
||||
````
|
||||

|
||||
220
C++/高级特性/2 C++移动语义.md
Normal file
@@ -0,0 +1,220 @@
|
||||
# C++移动语义
|
||||
|
||||
> 参考文献
|
||||
> * [https://www.cnblogs.com/sunchaothu/p/11392116.html](https://www.cnblogs.com/sunchaothu/p/11392116.html)
|
||||
> * [
|
||||
https://stackoverflow.com/questions/3106110/what-are-move-semantics/3109981#3109981](
|
||||
https://stackoverflow.com/questions/3106110/what-are-move-semantics/3109981#3109981)
|
||||
|
||||
## 1 可拷贝和可移动的概念
|
||||
|
||||
* 在面向对象中,有的类是可以拷贝的,例如车、房等他们的属性是可以复制的,可以调用拷贝构造函数和拷贝赋值函数。
|
||||
* 有点类的对象则是独一无二的,或者类的资源是独一无二的,比如 IO 、 std::unique_ptr等,他们不可以复制,但是可以把资源交出所有权给新的对象,称为可以移动的,可以调用移动构造函数和移动赋值函数。
|
||||
* C++11最重要的一个改进之一就是引入了move语义,这样在一些对象的构造时可以获取到已有的资源(如内存)而不需要通过拷贝,申请新的内存,这样移动而非拷贝将会大幅度提升性能。例如有些右值即将消亡析构,这个时候我们用移动构造函数可以接管他们的资源。
|
||||
|
||||
## 2 移动构造函数和移动赋值函数
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
#include <cstring>
|
||||
|
||||
using namespace std;
|
||||
|
||||
class A{
|
||||
public:
|
||||
A():i(new int[500]){
|
||||
cout<<"class A construct!"<<endl;
|
||||
}
|
||||
//拷贝构造函数
|
||||
A(const A &a):i(new int[500]){
|
||||
memcpy(i, a.i,500*sizeof(int));
|
||||
cout<<"class A copy!"<<endl;
|
||||
}
|
||||
//移动构造函数
|
||||
A(A &&a)noexcept
|
||||
:i(a.i)
|
||||
{
|
||||
a.i = nullptr;
|
||||
cout<< "class A move"<<endl;
|
||||
}
|
||||
//移动赋值运算符
|
||||
A &operator =(A &&rhs) noexcept{
|
||||
// check self assignment
|
||||
if(this != &rhs){
|
||||
delete []i;
|
||||
i = rhs.i;
|
||||
rhs.i = nullptr;
|
||||
}
|
||||
cout<< "class A move and assignment"<<std::endl;
|
||||
return *this;
|
||||
}
|
||||
~A(){
|
||||
delete []i;
|
||||
cout<<"class A destruct!"<<endl;
|
||||
}
|
||||
|
||||
private:
|
||||
int *i;
|
||||
};
|
||||
|
||||
A get_A_value(){
|
||||
return A();
|
||||
}
|
||||
void pass_A_by_value(A a){
|
||||
|
||||
}
|
||||
int main(){
|
||||
A a = get_A_value();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
对于拷贝构造函数运行时可以看到
|
||||
```
|
||||
class A construct!
|
||||
class A copy!
|
||||
class A destruct!
|
||||
class A copy!
|
||||
class A destruct!
|
||||
class A destruct!
|
||||
```
|
||||
发生了一次构造和两次拷贝!在每次拷贝中数组都得重新申请内存,而被拷贝后的对象很快就会析构,这无疑是一种浪费。
|
||||
|
||||
|
||||
对于移动移动构造函数;可以看到输出为
|
||||
```
|
||||
class A construct!
|
||||
class A move
|
||||
class A destruct!
|
||||
class A move
|
||||
class A destruct!
|
||||
class A destruct!
|
||||
```
|
||||
|
||||
原先的两次构造变成了两次移动!!在移动构造函数中,我们做了什么呢,我们只是获取了被移动对象的资源(这里是内存)的所有权,同时把被移动对象的成员指针置为空(以避免移动过来的内存被析构),这个过程中没有新内存的申请和分配,在大量对象的系统中,移动构造相对与拷贝构造可以显著提高性能!这里noexcept告诉编译器这里不会抛出异常,从而让编译器省一些操作(这个也是保证了STL容器在重新分配内存的时候(知道是noexpect)而使用移动构造而不是拷贝构造函数),通常移动构造都不会抛出异常的。
|
||||
|
||||
|
||||
### 移动构造和移动赋值
|
||||
|
||||
1. 偷梁换柱直接“浅拷贝”右值引用的对象的成员;
|
||||
2. 需要把原先右值引用的指针成员置为 nullptr,以避免右值在析构的时候把我们浅拷贝的资源给释放了;
|
||||
3. 移动构造函数需要先检查一下是否是自赋值,然后才能先delete自己的成员内存再浅拷贝右值的成员,始终记住第2条。
|
||||
|
||||
|
||||
|
||||
## 2 std::move()
|
||||
* std::move(lvalue) 的作用就是把一个左值转换为右值。关于左右值的含义我们上一篇博客C++11的右值引用进行过阐述。
|
||||
|
||||
|
||||
```
|
||||
int lv = 4;
|
||||
int &lr = lv;// 正确,lr是l的左值引用
|
||||
int &&rr = lv; // 错误,不可以把右值引用绑定到一个左值
|
||||
```
|
||||
|
||||
如果使用std::move 函数
|
||||
```
|
||||
int &&rr = std::move(lv); // 正确,把左值转换为右值
|
||||
```
|
||||
|
||||
可以看到 std::move的作用是把左值转换为右值的。
|
||||
|
||||
让我们看一看 std::move 的源码实现:
|
||||
```
|
||||
// FUNCTION TEMPLATE move
|
||||
template <class _Ty>
|
||||
_NODISCARD constexpr remove_reference_t<_Ty>&& move(_Ty&& _Arg) noexcept { // forward _Arg as movable
|
||||
return static_cast<remove_reference_t<_Ty>&&>(_Arg);
|
||||
}
|
||||
```
|
||||
|
||||
可以看到std::move 是一个模板函数,通过remove_reference_t获得模板参数的原本类型,然后把值转换为该类型的右值。用C++大师 Scott Meyers 的在《Effective Modern C++》中的话说, std::move 是个cast ,not a move.
|
||||
|
||||
值得注意的是: 使用move意味着,把一个左值转换为右值,原先的值不应该继续再使用(承诺即将废弃)
|
||||
|
||||
## 4 使用 std::move 实现一个高效的 swap 函数
|
||||
我们可以使用 move语义实现一个 交换操作,swap;在不使用 Move 语义的情况下
|
||||
```
|
||||
swap(A &a1, A &a2){
|
||||
A tmp(a1); // 拷贝构造函数一次,涉及大量数据的拷贝
|
||||
a1 = a2; // 拷贝赋值函数调用,涉及大量数据的拷贝
|
||||
a2 = tmp; // 拷贝赋值函数调用,涉及大量数据的拷贝
|
||||
}
|
||||
```
|
||||
如果使用 Move语义,即加上移动构造函数和移动赋值函数:
|
||||
```
|
||||
void swap_A(A &a1, A &a2){
|
||||
A tmp(std::move(a1)); // a1 转为右值,移动构造函数调用,低成本
|
||||
a1 = std::move(a2); // a2 转为右值,移动赋值函数调用,低成本
|
||||
a2 = std::move(tmp); // tmp 转为右值移动给a2
|
||||
}
|
||||
```
|
||||
可以看到move语义确实可以提高性能,事实上, move语义广泛地用于标准库的容器中。C++11标准库里的std::swap 也是基于移动语义实现的。
|
||||
|
||||
说到了 swap, 那就不得不说一下啊 move-and-swap 技术了
|
||||
|
||||
## 5 Move and swap 技巧
|
||||
看下面一段代码,实现了一个 unique_ptr ,和标准的std::unqiue_ptr的含义一致,智能指针的一种。
|
||||
```C++
|
||||
template<typename T>
|
||||
class unique_ptr
|
||||
{
|
||||
T* ptr;
|
||||
|
||||
public:
|
||||
|
||||
|
||||
explicit unique_ptr(T* p = nullptr)
|
||||
{
|
||||
ptr = p;
|
||||
}
|
||||
|
||||
~unique_ptr()
|
||||
{
|
||||
delete ptr;
|
||||
}
|
||||
|
||||
// move constructor
|
||||
unique_ptr(unique_ptr&& source) // note the rvalue reference
|
||||
{
|
||||
ptr = source.ptr;
|
||||
source.ptr = nullptr;
|
||||
}
|
||||
|
||||
/* unique_ptr& operator=(unique_ptr&& source) // 这里使用右值引用
|
||||
{
|
||||
if (this != &source) // beware of self-assignment
|
||||
{
|
||||
delete ptr; // release the old resource
|
||||
|
||||
ptr = source.ptr; // acquire the new resource
|
||||
source.ptr = nullptr;
|
||||
}
|
||||
return *this;
|
||||
} */
|
||||
|
||||
// move and swap idiom replace the move assignment operator
|
||||
unique_ptr& operator=(unique_ptr rhs) // 这里不用引用,会调用移动构造函数
|
||||
{
|
||||
std::swap(ptr, rhs.ptr);
|
||||
// std::swap(*this,rhs) // is also ok
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
|
||||
T* operator->() const
|
||||
{
|
||||
return ptr;
|
||||
}
|
||||
|
||||
T& operator*() const
|
||||
{
|
||||
return *ptr;
|
||||
}
|
||||
};
|
||||
```
|
||||
在这里如果要按照常规办法写移动赋值函数,函数体内需要写一堆检查自赋值等冗长的代码。使用 move-and-swap语义,只用简短的两行就可以写出来。 在移动赋值函数中 source 是个局部对象,这样在形参传递过来的时候必须要调用拷贝构造函数(这里没有实现则不可调用)或者移动构造函数
|
||||
,(事实上仅限右值可以传进来了)。然后 std::swap 负责把原先的资源和source 进行交换,完成了移动赋值。这样写节省了很多代码,很优雅。
|
||||
|
||||
|
||||
126
C++/高级特性/3 C++完美转发.md
Normal file
@@ -0,0 +1,126 @@
|
||||
# 完美转发
|
||||
|
||||
|
||||
## 1 概念
|
||||
|
||||
首先解释一下什么是完美转发,它指的是函数模板可以将自己的参数“完美”地转发给内部调用的其它函数。所谓完美,即不仅能准确地转发参数的值,还能保证被转发参数的左、右值属性不变。
|
||||
|
||||
```
|
||||
template<typename T>
|
||||
void function(T t) {
|
||||
otherdef(t);
|
||||
}
|
||||
```
|
||||
|
||||
function() 函数模板中调用了 otherdef() 函数。在此基础上,完美转发指的是:如果 function() 函数接收到的参数 t 为左值,那么该函数传递给 otherdef() 的参数 t 也是左值;反之如果 function() 函数接收到的参数 t 为右值,那么传递给 otherdef() 函数的参数 t 也必须为右值。
|
||||
|
||||
|
||||
## 2 C++98实现完美转发
|
||||
|
||||
* C++98通过左值引用和常量左值引用+函数重载实现完美转发
|
||||
|
||||
* C++98/03 标准下的 C++ 也可以实现完美转发,只是实现方式比较笨拙。通过前面的学习我们知道,C++ 98/03 标准中只有左值引用,并且可以细分为非 const 引用和 const 引用。其中,使用非 const 引用作为函数模板参数时,只能接收左值,无法接收右值;而 const 左值引用既可以接收左值,也可以接收右值,但考虑到其 const 属性,除非被调用函数的参数也是 const 属性,否则将无法直接传递。
|
||||
|
||||
|
||||
* 如果使用 C++ 98/03 标准下的 C++ 语言,我们可以采用函数模板重载的方式实现完美转发
|
||||
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
//重载被调用函数,查看完美转发的效果
|
||||
void otherdef(int & t) {
|
||||
cout << "lvalue\n";
|
||||
}
|
||||
void otherdef(const int & t) {
|
||||
cout << "rvalue\n";
|
||||
}
|
||||
//重载函数模板,分别接收左值和右值
|
||||
//接收右值参数
|
||||
template <typename T>
|
||||
void function(const T& t) {
|
||||
otherdef(t);
|
||||
}
|
||||
//接收左值参数
|
||||
template <typename T>
|
||||
void function(T& t) {
|
||||
otherdef(t);
|
||||
}
|
||||
int main()
|
||||
{
|
||||
function(5);//5 是右值
|
||||
int x = 1;
|
||||
function(x);//x 是左值
|
||||
return 0;
|
||||
}
|
||||
// 程序执行结果为:
|
||||
// rvalue
|
||||
// lvalue
|
||||
```
|
||||
从输出结果中可以看到,对于右值 5 来说,它实际调用的参数类型为 const T& 的函数模板,由于 t 为 const 类型,所以 otherdef() 函数实际调用的也是参数用 const 修饰的函数,所以输出“rvalue”;对于左值 x 来说,2 个重载模板函数都适用,C++编译器会选择最适合的参数类型为 T& 的函数模板,进而 therdef() 函数实际调用的是参数类型为非 const 的函数,输出“lvalue”。
|
||||
|
||||
|
||||
|
||||
## 3 C++ 11实现完美转发。
|
||||
|
||||
* C++ 11 标准中允许在函数模板中使用右值引用来实现完美转发
|
||||
|
||||
|
||||
### 万能引用规则
|
||||
* C++11 标准中规定,通常情况下右值引用形式的参数只能接收右值,不能接收左值。但对于函数模板中使用右值引用语法定义的参数来说,它不再遵守这一规定,既可以接收右值,也可以接收左值(此时的右值引用又被称为“万能引用”)
|
||||
|
||||
|
||||
* 在 C++11 标准中实现完美转发,只需要编写如下一个模板函数即可
|
||||
```
|
||||
template <typename T>
|
||||
void function(T&& t) {
|
||||
otherdef(t);
|
||||
}
|
||||
```
|
||||
|
||||
### 引用折叠规则
|
||||
* 此模板函数的参数 t 既可以接收左值,也可以接收右值。但仅仅使用右值引用作为函数模板的参数是远远不够的,还有一个问题继续解决,即如果调用 function() 函数时为其传递一个左值引用或者右值引用的实参。
|
||||
|
||||
* C++ 11标准为了更好地实现完美转发,特意为其指定了新的类型匹配规则,又称为引用折叠规则(假设用 A 表示实际传递参数的类型):
|
||||
* 当实参为左值或者左值引用(A&)时,函数模板中 T&& 将转变为 A&(A& && = A&);
|
||||
* 当实参为右值或者右值引用(A&&)时,函数模板中 T&& 将转变为 A&&(A&& && = A&&)。
|
||||
|
||||
```
|
||||
int n = 10;
|
||||
int & num = n;
|
||||
function(num); // T 为 int&
|
||||
int && num2 = 11;
|
||||
function(num2); // T 为 int &&
|
||||
```
|
||||
### Foward<T>模板函数
|
||||
|
||||
* 引入了一个模板函数 forword<T>(),我们只需要调用该函数,将函数模板接收到的形参连同其左、右值属性,一起传递给被调用的函数呢?
|
||||
|
||||
```C++
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
//重载被调用函数,查看完美转发的效果
|
||||
void otherdef(int & t) {
|
||||
cout << "lvalue\n";
|
||||
}
|
||||
void otherdef(const int & t) {
|
||||
cout << "rvalue\n";
|
||||
}
|
||||
//实现完美转发的函数模板
|
||||
template <typename T>
|
||||
void function(T&& t) {
|
||||
otherdef(forward<T>(t));
|
||||
}
|
||||
int main()
|
||||
{
|
||||
function(5);
|
||||
int x = 1;
|
||||
function(x);
|
||||
return 0;
|
||||
}
|
||||
// 程序执行结果为:
|
||||
// rvalue
|
||||
// lvalue
|
||||
```
|
||||
|
||||
* 总的来说,在定义模板函数时,我们采用右值引用的语法格式定义参数类型,由此该函数既可以接收外界传入的左值,也可以接收右值;其次,还需要使用 C++11 标准库提供的 forword() 模板函数修饰被调用函数中需要维持左、右值属性的参数。由此即可轻松实现函数模板中参数的完美转发。
|
||||
27
C++/高级特性/3.cpp
Normal file
@@ -0,0 +1,27 @@
|
||||
#include <iostream>
|
||||
using namespace std;
|
||||
//重载被调用函数,查看完美转发的效果
|
||||
void otherdef(int & t) {
|
||||
cout << "lvalue\n";
|
||||
}
|
||||
void otherdef(const int & t) {
|
||||
cout << "rvalue\n";
|
||||
}
|
||||
//重载函数模板,分别接收左值和右值
|
||||
//接收右值参数。常量左值引用可以接受左值、常量左值、右值、常量右值。
|
||||
template <typename T>
|
||||
void function(const T& t) {
|
||||
otherdef(t);
|
||||
}
|
||||
//接收左值参数
|
||||
template <typename T>
|
||||
void function(T& t) {
|
||||
otherdef(t);
|
||||
}
|
||||
int main()
|
||||
{
|
||||
function(5);//5 是右值
|
||||
int x = 1;
|
||||
function(x);//x 是左值
|
||||
return 0;
|
||||
}
|
||||
BIN
C++/高级特性/image/2021-07-21-11-45-51.png
Normal file
|
After Width: | Height: | Size: 26 KiB |
1
C++/高级特性/说明.md
Normal file
@@ -0,0 +1 @@
|
||||
> 主要用来记录 effectiveC++ 和more effective c++中涉及到的基础知识和高级特性。
|
||||
@@ -3,7 +3,14 @@ module example.com/m
|
||||
go 1.16
|
||||
|
||||
require (
|
||||
github.com/ramya-rao-a/go-outline v0.0.0-20200117021646-2a048b4510eb // indirect
|
||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||
golang.org/x/tools v0.1.1 // indirect
|
||||
github.com/cweill/gotests v1.6.0 // indirect
|
||||
github.com/fatih/gomodifytags v1.13.0 // indirect
|
||||
github.com/go-delve/delve v1.6.2-0.20210708052754-e1febcf6093b // indirect
|
||||
github.com/haya14busa/goplay v1.0.0 // indirect
|
||||
github.com/josharian/impl v1.1.0 // indirect
|
||||
github.com/ramya-rao-a/go-outline v0.0.0-20210608161538-9736a4bde949 // indirect
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 // indirect
|
||||
github.com/uudashr/gopkgs/v2 v2.1.2 // indirect
|
||||
golang.org/x/tools/gopls v0.7.0 // indirect
|
||||
honnef.co/go/tools v0.2.0 // indirect
|
||||
)
|
||||
|
||||
@@ -1,39 +1,153 @@
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
|
||||
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
|
||||
github.com/jtolds/gls v4.20.0+incompatible h1:xdiiI2gbIgH/gLH7ADydsJ1uDOEzR8yvV7C0MuV77Wo=
|
||||
github.com/jtolds/gls v4.20.0+incompatible/go.mod h1:QJZ7F/aHp+rZTRtaJ1ow/lLfFfVYBRgL+9YlvaHOwJU=
|
||||
github.com/ramya-rao-a/go-outline v0.0.0-20200117021646-2a048b4510eb h1:ilZSL4VaIq4Hsi+lH928xQKnSWymFug6r2gJomUBpW8=
|
||||
github.com/ramya-rao-a/go-outline v0.0.0-20200117021646-2a048b4510eb/go.mod h1:1WL5IqM+CnRCAbXetRnL1YVoS9KtU2zMhOi/5oAVPo4=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d h1:zE9ykElWQ6/NYmHa3jpm/yHnI4xSofP+UP6SpjHcSeM=
|
||||
github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc=
|
||||
github.com/smartystreets/goconvey v1.6.4 h1:fv0U8FUIMPNf1L9lnHLvLhgicrIVChEkdzIKYqbNC9s=
|
||||
github.com/smartystreets/goconvey v1.6.4/go.mod h1:syvi0/a8iFYH4r/RixwvyeAJjdLS9QV7WQ/tjFTllLA=
|
||||
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
|
||||
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
|
||||
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
||||
github.com/cosiner/argv v0.1.0 h1:BVDiEL32lwHukgJKP87btEPenzrrHUjajs/8yzaqcXg=
|
||||
github.com/cosiner/argv v0.1.0/go.mod h1:EusR6TucWKX+zFgtdUsKT2Cvg45K5rtpCcWz4hK06d8=
|
||||
github.com/cpuguy83/go-md2man v1.0.10 h1:BSKMNlYxDvnunlTymqtgONjNnaRV1sTpcovwwjF22jk=
|
||||
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/cweill/gotests v1.6.0 h1:KJx+/p4EweijYzqPb4Y/8umDCip1Cv6hEVyOx0mE9W8=
|
||||
github.com/cweill/gotests v1.6.0/go.mod h1:CaRYbxQZGQOxXDvM9l0XJVV2Tjb2E5H53vq+reR2GrA=
|
||||
github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/fatih/camelcase v1.0.0 h1:hxNvNX/xYBp0ovncs8WyWZrOrpBNub/JfaMvbURyft8=
|
||||
github.com/fatih/camelcase v1.0.0/go.mod h1:yN2Sb0lFhZJUdVvtELVWefmrXpuZESvPmqwoZc+/fpc=
|
||||
github.com/fatih/gomodifytags v1.13.0 h1:fmhwoecjZ5c34Q2chjRB9cL8Rgag+1TOSMy+grissMc=
|
||||
github.com/fatih/gomodifytags v1.13.0/go.mod h1:TbUyEjH1Zo0GkJd2Q52oVYqYcJ0eGNqG8bsiOb75P9c=
|
||||
github.com/fatih/structtag v1.2.0 h1:/OdNE99OxoI/PqaW/SuSK9uxxT3f/tcSZgon/ssNSx4=
|
||||
github.com/fatih/structtag v1.2.0/go.mod h1:mBJUNpUnHmRKrKlQQlmCrh5PuhftFbNv8Ys4/aAZl94=
|
||||
github.com/go-delve/delve v1.6.2-0.20210708052754-e1febcf6093b h1:f/GASUP2QbcfqIolbdSlJXsyLXpMc8QitdTlX9zsspU=
|
||||
github.com/go-delve/delve v1.6.2-0.20210708052754-e1febcf6093b/go.mod h1:2DpgGoHOW7r7MXyykmT7axp9IEEIc8EV/swa5m8rkbo=
|
||||
github.com/go-delve/delve v1.7.0 h1:MaWAD3LtvjE/LL98urSHPjaMT+OubpQ2sqF3R2Uj1rc=
|
||||
github.com/go-delve/delve v1.7.0/go.mod h1:2DpgGoHOW7r7MXyykmT7axp9IEEIc8EV/swa5m8rkbo=
|
||||
github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.5 h1:Khx7svrCpmxxtHBq5j2mp/xVjsi8hQMfNLvJFAlrGgU=
|
||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-dap v0.5.0 h1:RMHAVn5xeunBakYk65ggHXttk6qjZVdbmi+xhAoL2wY=
|
||||
github.com/google/go-dap v0.5.0/go.mod h1:5q8aYQFnHOAZEMP+6vmq25HKYAEwE+LF5yh7JKrrhSQ=
|
||||
github.com/google/safehtml v0.0.2/go.mod h1:L4KWwDsUJdECRAEpZoBn3O64bQaywRscowZjJAzjHnU=
|
||||
github.com/hashicorp/golang-lru v0.5.4 h1:YDjusn29QI/Das2iO9M0BHnIbxPeyuCHsjMW+lJfyTc=
|
||||
github.com/hashicorp/golang-lru v0.5.4/go.mod h1:iADmTwqILo4mZ8BN3D2Q6+9jd8WM5uGBxy+E8yxSoD4=
|
||||
github.com/haya14busa/goplay v1.0.0 h1:ED4BMrGQ3WH7H3YXrcnWMVzj1xeSepaYTkLh1DtFi/4=
|
||||
github.com/haya14busa/goplay v1.0.0/go.mod h1:TUcdOVV7TTx0Fo9CmTf16Erfju/DzXTbB70+RYb43h8=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jba/templatecheck v0.6.0/go.mod h1:/1k7EajoSErFI9GLHAsiIJEaNLt3ALKNw2TV7z2SYv4=
|
||||
github.com/josharian/impl v1.1.0 h1:gafhg1OFVMq46ifdkBa8wp4hlGogjktjjA5h/2j4+2k=
|
||||
github.com/josharian/impl v1.1.0/go.mod h1:SQ6aJMP6xsJpGSD/36IIqrUdigLCYe9bz/9o5AKm6Aw=
|
||||
github.com/karrick/godirwalk v1.12.0 h1:nkS4xxsjiZMvVlazd0mFyiwD4BR9f3m6LXGhM2TUx3Y=
|
||||
github.com/karrick/godirwalk v1.12.0/go.mod h1:H5KPZjojv4lE+QYImBI8xVtrBRgYrIVsaRPx4tDPEn4=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3 h1:CE8S1cTafDpPvMhIxNJKvHsGVBgn1xWYf1NbHQhywc8=
|
||||
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
|
||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561 h1:isR/L+BIZ+rqODWYR/f526ygrBMGKZYFhaaFRDGvuZ8=
|
||||
github.com/mattn/go-colorable v0.0.0-20170327083344-ded68f7a9561/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
|
||||
github.com/mattn/go-isatty v0.0.3 h1:ns/ykhmWi7G9O+8a448SecJU3nSMBXJfqQkl0upE1jI=
|
||||
github.com/mattn/go-isatty v0.0.3/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
|
||||
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b h1:8uaXtUkxiy+T/zdLWuxa/PG4so0TPZDZfafFNNSaptE=
|
||||
github.com/peterh/liner v0.0.0-20170317030525-88609521dc4b/go.mod h1:xIteQHvHuaLYG9IFj6mSxM0fCKrs34IrEQUhOYuGPHc=
|
||||
github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/ramya-rao-a/go-outline v0.0.0-20210608161538-9736a4bde949 h1:iaD+iVf9xGfajsJp+zYrg9Lrk6gMJ6/hZHO4cYq5D5o=
|
||||
github.com/ramya-rao-a/go-outline v0.0.0-20210608161538-9736a4bde949/go.mod h1:9V3eNbj9Z53yO7cKB6cSX9f0O7rYdIiuGBhjA1YsQuw=
|
||||
github.com/rogpeppe/go-internal v1.5.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/rogpeppe/go-internal v1.6.2/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||
github.com/russross/blackfriday v1.5.2 h1:HyvC0ARfnZBqnXwABFeSZHpKvJHJJfPz81GNueLj0oo=
|
||||
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
|
||||
github.com/sanity-io/litter v1.5.0/go.mod h1:5Z71SvaYy5kcGtyglXOC9rrUi3c1E8CamFWjQsazTh0=
|
||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
|
||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
|
||||
github.com/sirupsen/logrus v1.6.0 h1:UBcNElsrwanuuMsnGSlYmtmgbb23qDR5dG+6X6Oo89I=
|
||||
github.com/sirupsen/logrus v1.6.0/go.mod h1:7uNnSEd1DgxDLC74fIahvMZmmYsHGZGEOFrfsX/uA88=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA=
|
||||
github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog=
|
||||
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372 h1:eRfW1vRS4th8IX2iQeyqQ8cOUNOySvAYJ0IUvTXGoYA=
|
||||
github.com/spf13/cobra v0.0.0-20170417170307-b6cb39589372/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
|
||||
github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1 h1:7bozMfSdo41n2NOc0GsVTTVUiA+Ncaj6pXNpm4UHKys=
|
||||
github.com/spf13/pflag v0.0.0-20170417173400-9e4c21054fa1/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/uudashr/gopkgs/v2 v2.1.2 h1:A0+QH6wqNRHORJnxmqfeuBEsK4nYQ7pgcOHhqpqcrpo=
|
||||
github.com/uudashr/gopkgs/v2 v2.1.2/go.mod h1:O9VKOuPWrUpVhaxcg7N3QiTrlDhgJb/84Y7b3qaX1rI=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||
go.starlark.net v0.0.0-20200821142938-949cc6f4b097 h1:YiRMXXgG+Pg26t1fjq+iAjaauKWMC9cmGFrtOEuwDDg=
|
||||
go.starlark.net v0.0.0-20200821142938-949cc6f4b097/go.mod h1:f0znQkUKRrkk36XxWbGjMqQM8wGv/xHBVE2qc3B5oFU=
|
||||
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4 h1:QlVATYS7JBoZMVaf+cNjb90WD/beKVHnIxFKT4QaHVI=
|
||||
golang.org/x/arch v0.0.0-20190927153633-4e8777c89be4/go.mod h1:flIaEI6LNU6xOCD5PaJvn9wGP0agmIOqjrtsKGRguv4=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
|
||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20190422165155-953cdadca894/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200625212154-ddb9806d33ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007 h1:gG67DSER+11cZvqIMb8S8bt0vZtiN6xWYARwirrOSfE=
|
||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/tools v0.0.0-20180824175216-6c1c5e93cdc1/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
|
||||
golang.org/x/tools v0.0.0-20191109212701-97ad0ed33101/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20191127201027-ecd32218bd7f/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||
golang.org/x/tools v0.0.0-20200522201501-cb1345f3a375/go.mod h1:EkVYQZoAsY45+roYkvgYkIh4xh/qjgUK9TdY2XT94GE=
|
||||
golang.org/x/tools v0.0.0-20210101214203-2dba1e4ea05c/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
|
||||
golang.org/x/tools v0.1.1 h1:wGiQel/hW0NnEkJUk8lbzkX2gFJU6PFxf1v5OlCfuOs=
|
||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools v0.1.3-0.20210608163600-9ed039809d4c h1:Pv9gNyJFYVdpUAVZYJ1BDSU4eGgXQ+0f3DIGAdolO5s=
|
||||
golang.org/x/tools v0.1.3-0.20210608163600-9ed039809d4c/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||
golang.org/x/tools/gopls v0.7.0 h1:JQBHW81Gsyim6iDjUwGoPeSpXrSqwen3isPJLfDfaYU=
|
||||
golang.org/x/tools/gopls v0.7.0/go.mod h1:2e5c16p2T50tIFn0V3ZHHJz0+CRHvJb8TGR9RPFdw8A=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
|
||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||
gopkg.in/yaml.v2 v2.2.1 h1:mUhvW9EsL+naU5Q3cakzfE91YhliOondGd6ZrsDBHQE=
|
||||
gopkg.in/yaml.v2 v2.2.1/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
honnef.co/go/tools v0.2.0 h1:ws8AfbgTX3oIczLPNPCu5166oBg9ST2vNs0rcht+mDE=
|
||||
honnef.co/go/tools v0.2.0/go.mod h1:lPVVZ2BS5TfnjLyizF7o7hv7j9/L+8cZY2hLyjP9cGY=
|
||||
mvdan.cc/gofumpt v0.1.1 h1:bi/1aS/5W00E2ny5q65w9SnKpWEF/UIOqDYBILpo9rA=
|
||||
mvdan.cc/gofumpt v0.1.1/go.mod h1:yXG1r1WqZVKWbVRtBWKWX9+CxGYfA51nSomhM0woR48=
|
||||
mvdan.cc/xurls/v2 v2.2.0 h1:NSZPykBXJFCetGZykLAxaL6SIpvbVy/UFEniIfHAa8A=
|
||||
mvdan.cc/xurls/v2 v2.2.0/go.mod h1:EV1RMtya9D6G5DMYPGD8zTQzaHet6Jh8gFlRgGRJeO8=
|
||||
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
1. 获取数据集
|
||||
2. 数据预处理
|
||||
3. 训练模型
|
||||
1. 神经网络:torch.nn.Model.__init__定义具有一些可学习参数(或权重)的神经网络
|
||||
2. 正向传播:torch.nn.Model.forward通过网络处理输入,进行正向传播
|
||||
3. 计算损失:torch.nn.loss输出正确的距离有多远
|
||||
4. 反向传播:torch.tensor.backward将梯度传播回网络参数
|
||||
5. 更新权重:troch.optim通常使用简单的更新规则来更新网络的权重:weight = weight - learning_rate * gradient
|
||||
6. 循环迭代:train cycle
|
||||
1. 创建模型:torch.nn.Model.__init__定义具有一些可学习参数(或权重)的神经网络
|
||||
2. 训练算法:
|
||||
1. 正向传播:torch.nn.Model.forward通过网络处理输入,进行正向传播
|
||||
2. 计算损失:torch.nn.loss输出正确的距离有多远
|
||||
3. 反向传播:torch.tensor.backward将梯度传播回网络参数
|
||||
4. 更新权重:troch.optim通常使用简单的更新规则来更新网络的权重:weight = weight - learning_rate * gradient
|
||||
5. 迭代循环:重复以上步骤直到(精确度满足要求 或者 迭代次数到达上限)
|
||||
4. 验证模型
|
||||
5. 使用模型
|
||||
|
||||
|
||||
BIN
pytorch/官方教程/2021-07-27-21-14-52.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
pytorch/官方教程/2021-07-27-21-15-37.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
@@ -1,4 +1,5 @@
|
||||
# 张量
|
||||

|
||||
|
||||
张量如同数组和矩阵一样, 是一种特殊的数据结构。在`PyTorch`中, 神经网络的输入、输出以及网络的参数等数据, 都是使用张量来进行描述。
|
||||
|
||||
|
||||
@@ -0,0 +1,112 @@
|
||||
# 数据集和数据加载器
|
||||
|
||||
## 1 torchvision.datasets 官方数据集加载
|
||||
|
||||
我们使用以下参数加载FashionMNIST 数据集:
|
||||
* root 是存储训练/测试数据的路径,
|
||||
* train 指定训练或测试数据集,
|
||||
* download=True如果数据不可用,则从 Internet 下载数据root。
|
||||
* transform并target_transform指定特征和标签转
|
||||
|
||||
```py
|
||||
import torch
|
||||
from torch.utils.data import Dataset
|
||||
from torchvision import datasets
|
||||
from torchvision.transforms import ToTensor
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
|
||||
training_data = datasets.FashionMNIST(
|
||||
root="data",
|
||||
train=True,
|
||||
download=True,
|
||||
transform=ToTensor()
|
||||
)
|
||||
|
||||
test_data = datasets.FashionMNIST(
|
||||
root="data",
|
||||
train=False,
|
||||
download=True,
|
||||
transform=ToTensor()
|
||||
)
|
||||
```
|
||||
|
||||
对加载的数据集进行可视化显示
|
||||
```py
|
||||
labels_map = {
|
||||
0: "T-Shirt",
|
||||
1: "Trouser",
|
||||
2: "Pullover",
|
||||
3: "Dress",
|
||||
4: "Coat",
|
||||
5: "Sandal",
|
||||
6: "Shirt",
|
||||
7: "Sneaker",
|
||||
8: "Bag",
|
||||
9: "Ankle Boot",
|
||||
}
|
||||
figure = plt.figure(figsize=(8, 8))
|
||||
cols, rows = 3, 3
|
||||
for i in range(1, cols * rows + 1):
|
||||
sample_idx = torch.randint(len(training_data), size=(1,)).item()
|
||||
img, label = training_data[sample_idx]
|
||||
figure.add_subplot(rows, cols, i)
|
||||
plt.title(labels_map[label])
|
||||
plt.axis("off")
|
||||
plt.imshow(img.squeeze(), cmap="gray")
|
||||
plt.show()
|
||||
```
|
||||
|
||||
|
||||
## 2 自定义dataset加载数据集
|
||||
|
||||
* 自定义 Dataset 类必须实现三个函数:__init__、__len__和__getitem__。看看这个实现;FashionMNIST 图像存储在一个目录中img_dir,它们的标签单独存储在一个 CSV 文件中annotations_file。
|
||||
|
||||
```py
|
||||
import os
|
||||
import pandas as pd
|
||||
from torchvision.io import read_image
|
||||
|
||||
class CustomImageDataset(Dataset):
|
||||
def __init__(self, annotations_file, img_dir, transform=None, target_transform=None):
|
||||
self.img_labels = pd.read_csv(annotations_file)
|
||||
self.img_dir = img_dir
|
||||
self.transform = transform
|
||||
self.target_transform = target_transform
|
||||
|
||||
def __len__(self):
|
||||
return len(self.img_labels)
|
||||
|
||||
def __getitem__(self, idx):
|
||||
img_path = os.path.join(self.img_dir, self.img_labels.iloc[idx, 0])
|
||||
image = read_image(img_path)
|
||||
label = self.img_labels.iloc[idx, 1]
|
||||
if self.transform:
|
||||
image = self.transform(image)
|
||||
if self.target_transform:
|
||||
label = self.target_transform(label)
|
||||
return image, label
|
||||
|
||||
```
|
||||
|
||||
* __init__ 函数在实例化 Dataset 对象时运行一次。我们初始化包含图像、注释文件和两个转换的目录
|
||||
* __len__ 函数返回我们数据集中的样本数。
|
||||
* __getitem__ 函数从给定索引处的数据集中加载并返回一个样本idx。基于索引,它识别图像在磁盘上的位置,使用 将其转换为张量read_image,从 中的 csv 数据中检索相应的标签self.img_labels,调用它们的变换函数(如果适用),并返回张量图像和相应的标签一个元组。
|
||||
|
||||
|
||||
|
||||
## 3 使用DataLoader进行训练
|
||||
|
||||
* 我们已将该数据集加载到 中,Dataloader并且可以根据需要遍历数据集。下面的每次迭代都会返回一批train_features和train_labels(batch_size=64分别包含特征和标签)。因为我们指定了shuffle=True,在我们遍历所有批次后,数据会被打乱
|
||||
|
||||
```py
|
||||
# Display image and label.
|
||||
train_features, train_labels = next(iter(train_dataloader))
|
||||
print(f"Feature batch shape: {train_features.size()}")
|
||||
print(f"Labels batch shape: {train_labels.size()}")
|
||||
img = train_features[0].squeeze()
|
||||
label = train_labels[0]
|
||||
plt.imshow(img, cmap="gray")
|
||||
plt.show()
|
||||
print(f"Label: {label}")
|
||||
```
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
# transform对数据集进行转换
|
||||
|
||||
## 1 torchvision数据集才有的转换
|
||||
|
||||
|
||||
所有 TorchVision 数据集都有两个参数 -transform修改特征和 target_transform修改标签 - 接受包含转换逻辑的可调用对象。该torchvision.transforms模块提供几种常用的变换开箱
|
||||
|
||||
```py
|
||||
import torch
|
||||
from torchvision import datasets
|
||||
from torchvision.transforms import ToTensor, Lambda
|
||||
|
||||
ds = datasets.FashionMNIST(
|
||||
root="data",
|
||||
train=True,
|
||||
download=True,
|
||||
transform=ToTensor(),
|
||||
target_transform=Lambda(lambda y: torch.zeros(10, dtype=torch.float).scatter_(0, torch.tensor(y), value=1))
|
||||
)
|
||||
```
|
||||
|
||||
|
||||
### ToTensor()
|
||||
ToTensor 将 PIL 图像或 NumPyndarray转换为FloatTensor. 并在 [0., 1.] 范围内缩放图像的像素强度值
|
||||
|
||||
### Lambda 变换
|
||||
Lambda 转换适用于任何用户定义的 lambda 函数。在这里,我们定义了一个函数来将整数转换为单热编码的张量。它首先创建一个大小为 10(我们数据集中的标签数量)的零张量,并调用 scatter_,它value=1在标签给定的索引上分配 a y。
|
||||
```py
|
||||
target_transform = Lambda(lambda y: torch.zeros(
|
||||
10, dtype=torch.float).scatter_(dim=0, index=torch.tensor(y), value=1))
|
||||
```
|
||||
@@ -2,4 +2,7 @@
|
||||
|
||||
# torch.Tensor
|
||||
|
||||
> 包含tensor处理的各种方法和属性。
|
||||
> 包含tensor处理的各种方法和属性。
|
||||
|
||||
|
||||

|
||||
BIN
工作日志/2021-07-31-21-57-24.png
Normal file
|
After Width: | Height: | Size: 1.7 MiB |
@@ -1,2 +1,22 @@
|
||||
> 六月份已经过去了。乱七八糟。
|
||||
|
||||
|
||||
|
||||
|
||||
## 总结
|
||||
* 与高中同学背景聚会。去交通大学玩耍。还挺他们唱歌,自己终于也能跟着志鹏哼两句了。
|
||||
* 后来汉卿来了,打第一次篮球脚扭了。
|
||||
* 汉卿、李静、我、玄哥?一款在胡同小馆吃饭。瞎扯
|
||||
* 跟玄哥、志鹏、平子吃了一次两份去吃了一次两份,在肯德基里完了一晚上的剧本杀,居然是个凶手累的一批。
|
||||
* 康明、刘迪、东哥。多年未见的老朋友终于又一次聚在了一块。去做了各种各样的过山车,真的好玩。真想给你讲述一下那样的经历。
|
||||
* 回家了一趟,感慨万千。见了茹姐。
|
||||
|
||||
|
||||
> 过了六月就已经是下半年了。我发现这半年来。自己的状态有所好转。但是没有以前的热情了。我想回到从前,对生活的充满期待,而不是因为焦虑不得不去做这些事情。是因为对未来的期待。
|
||||
> 果然,不能抱着侥幸的心里,不能过分在乎别人对自己的目光。太过焦虑了,过分厌烦。气死了。果然这样什么事情都处理不好。本来就应该回宿舍,既不会过分担心发生的事情。
|
||||
> 六月份应该是诸事顺利的日子,但是我发现。被乱七八糟的事情搞得很难受。六月份的冲动已经消失了。
|
||||
> 我需要想一个让自己能记得住的口号和方法。重读自己的日记。找到正确的方法。争取在八月份之前,返回工作岗位。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
20
工作日志/2021年7月10日-今日计划.md
Normal file
@@ -0,0 +1,20 @@
|
||||
## 计划
|
||||
|
||||
> 由于citavi彻底崩掉了。不得不采取这样的方式。恶心的citavi,垃圾的同步问题。从今以后,那些大公司承诺和支持的软件的,千万不要相信。永远拥抱开源就对了,总有一堆活跃的大佬,不断完善开源软件,比瞎搞的citavi、mendeley强多了。
|
||||
|
||||
- [X] 学习zotero使用教程。
|
||||
- [X] 将所有的中英文文献导入到zotero中。(逐步将翻译、笔记插入到当前的文档管理软件当中。)
|
||||
- [X] 将文献翻译导入到指定的条目当中
|
||||
- [X] 导入中文文献
|
||||
- [X] 回顾自己的计划
|
||||
- [ ] 读论文联邦学习相关(10篇)做好相关的总结。
|
||||
|
||||
## 总结
|
||||
|
||||
* 两套软件使用。逐步过渡到zotero。这个垃圾的citavi配置问题,太闹心了。就喜欢简单一键解决问题。想要啥都做好。往往啥都做不好。垃圾软件,毫无用户体验。md,刚配置完成,这东西居然又连上网络了。我觉得还是把软件当工具用,工具始终是工具而不是目标。
|
||||
* 与citavi相比,在于知识的管理。可能笔记的内容无法非常好的索引出来。无法形成最后文献阅读的csv表格。但是无所谓。可以最后的时候自己做成一个表格。附件中的笔记使用来索引的。
|
||||
|
||||
|
||||
|
||||
|
||||
* 终于可以开了。兄弟,别等了。开始吧。
|
||||
13
工作日志/2021年7月16日-今日计划.md
Normal file
@@ -0,0 +1,13 @@
|
||||
## 计划
|
||||
|
||||
* 八篇文章
|
||||
* [x] FedRep联邦表示学习、本地个性化模型
|
||||
* [x] FLmeta 联邦元学习
|
||||
* [x] MAML 元学习
|
||||
* [ ] Deeplearning
|
||||
* [ ] Federated Learning
|
||||
* [ ] FedFMC
|
||||
* [ ] On the coverage
|
||||
* [ ] Personality
|
||||
|
||||
## 总结
|
||||
14
工作日志/2021年7月18日-今日计划.md
Normal file
@@ -0,0 +1,14 @@
|
||||
## 计划
|
||||
|
||||
* 十篇文章(2021.04文件夹下的内容)
|
||||
* [x] FedFMC
|
||||
* [x] EWC(FedFMC中用到的一种终身学习的方法,需要了解,作为参考文献)是一种增量学习方案
|
||||
* [x] Overcoming Forgetting in Federated Learning on Non-IID Data 利用增量学习方案解决联邦学习中非独立同分布问题的另外一个方法。
|
||||
* [x] Federated Meta-Learning for Fraudulent Credit Card Detection 联邦元学习解决信用卡诈骗检测
|
||||
* [x] Learning Classifiers When the Training Data Is Not IID
|
||||
* [x] on the convergence of fl on noniid data
|
||||
* [x] federated learning with non iid data
|
||||
* [x] federated learning with non iid data : a survey
|
||||
|
||||
## 总结
|
||||
|
||||
59
工作日志/2021年7月19日-科研汇报.md
Normal file
@@ -0,0 +1,59 @@
|
||||
## 第6次科研汇报
|
||||
|
||||
> 按照中期答辩或者小论文完成的方式进行汇报。
|
||||
|
||||
这次的研究进展就按照小论文的形式进行汇报,因为中期答辩的话,必然要把开题的那一套全都讲一遍。试一下,尝试一下中期答辩的方式。
|
||||
|
||||
看完这几篇关于非独立同分布的文章,然后用一个表格总结一下,放到PPT中。
|
||||
|
||||
|
||||
|
||||
|
||||
## 研究路线
|
||||
|
||||
背景---->目标----> 切入点
|
||||
|
||||
恶意软件检测------> 数据隐私需求-----> 联邦学习-----> 非独立同分布问题
|
||||
|
||||
|
||||
|
||||
## 理论研究
|
||||
|
||||
### 问题定义——什么是非独立同分布?
|
||||
怎么产生的,有哪几种类别。
|
||||
|
||||
### 非独立同分布到底会产生什么影响?
|
||||
|
||||
### 联邦学习非独立同分布的主要解决方案
|
||||
|
||||
每种方法给出几个典型的文章的方法和内容。使用表格
|
||||
|
||||
1. 样本共享
|
||||
2. 终身学习
|
||||
3. 全局修正
|
||||
4. 元学习
|
||||
|
||||
|
||||
|
||||
## 研究进展
|
||||
|
||||
|
||||
理论研究80%
|
||||
|
||||
1. 采取联邦元学习,通过本地个性化解决联邦学习在恶意软件过程中因为数据非独立同分布导致的准确率下降的问题。再次基础上进行改进,添加全局修正项。
|
||||
|
||||
工程研究20%
|
||||
|
||||
1. 完成了prox和idx两个全局修正非独立同分布解决方案。
|
||||
|
||||
|
||||
预期成果
|
||||
1. 完成基于联邦元学习的的恶意软件检测方法 小论文
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
8
工作日志/2021年7月21日-今日计划.md
Normal file
@@ -0,0 +1,8 @@
|
||||
## 计划
|
||||
|
||||
### 毕设——论文阅读2.00-6.00
|
||||
* [x] federated learning on non iid data silos an experiment
|
||||
* [x] fedAT
|
||||
* [x] 自适应联邦学习算法
|
||||
|
||||
## 总结
|
||||
18
工作日志/2021年7月22日-今日计划.md
Normal file
@@ -0,0 +1,18 @@
|
||||
## 计划
|
||||
|
||||
### 毕设——论文阅读2.00-6.00
|
||||
* [x] mocha 联邦多任务学习
|
||||
* [x] Improving Federated Learning Personalization via Model Agnostic Meta Learning
|
||||
* [x] Personalized Federated Learning for Intelligent IoT Applications: A Cloud-Edge Based Framework
|
||||
* [x] Personalized Federated Learning With Differential Privacy
|
||||
* [x] Personalized Federated Learning with Moreau Envelopes
|
||||
* [x] Personalized Federated Learning: A Meta-Learning Approach
|
||||
* [x] Salvaging Federated Learning by Local Adaptation
|
||||
* [x] Survey of Personalization Techniques for Federated Learning
|
||||
|
||||
|
||||
|
||||
## 总结
|
||||
|
||||
|
||||
* 基本把非独立同分布问题的经典方法看完了。接下来进行复现。尝试对各种方法进行对比,主要是基于手写体数据集构建非独立同分布的实验。然后将数据集更改为自己的数据集(等选择好数据集之后,将数据及进行更换。)
|
||||
23
工作日志/2021年7月23日-今日计划.md
Normal file
@@ -0,0 +1,23 @@
|
||||
## 计划
|
||||
|
||||
### 毕设——论文阅读2.00-6.00
|
||||
|
||||
* [x] Android Malware Detection using Deep Learning on API Method Sequences
|
||||
* [x] LoAdaBoost: loss-based AdaBoost federated machine learning with reduced computational complexity on IID and non-IID intensive care data
|
||||
* [x] A scalable and extensible framework for android malware detection and family attribution
|
||||
* [x] CTDroid: Leveraging a Corpus of Technical Blogs for Android Malware Analysis
|
||||
* [x] Optimizing symbolic execution for malware behavior classification
|
||||
* [x] Cross-Gradient Aggregation for Decentralized Learning from Non-IID data
|
||||
* [x] JOWMDroid: Android malware detection based on feature weighting with joint optimization of weight-mapping and classifier parameters
|
||||
* [x] DAMBA: Detecting Android Malware by ORGB Analysis
|
||||
* [x] DeepIntent: Deep Icon-Behavior Learning for Detecting Intention-Behavior Discrepancy in Mobile Apps
|
||||
|
||||
|
||||
### 就业
|
||||
|
||||
- [x] LeetCode一道困难题。10.00-12.00
|
||||
- [ ] C++基础知识看完。8.00-10.00
|
||||
|
||||
|
||||
|
||||
## 总结
|
||||
40
工作日志/2021年7月24日-今日计划.md
Normal file
@@ -0,0 +1,40 @@
|
||||
## 计划
|
||||
|
||||
|
||||
### 就业
|
||||
|
||||
- [ ] LeetCode一道困难题。10.00-12.00
|
||||
- [ ] C++基础知识看完。8.00-10.00
|
||||
|
||||
|
||||
|
||||
## 总结
|
||||
|
||||
* 一个模板可以用来复制黏贴
|
||||
```
|
||||
# DNN
|
||||
|
||||
|
||||
## 文献贡献
|
||||
|
||||
|
||||
## 问题定义
|
||||
|
||||
|
||||
## 算法模型
|
||||
|
||||
|
||||
## 实验内容
|
||||
|
||||
1. 目标设置:
|
||||
2. 样本设置:
|
||||
3. 工具设置:
|
||||
4. 算法设置:
|
||||
5. 参数设置:
|
||||
|
||||
|
||||
## 研究结论
|
||||
|
||||
|
||||
## 存在问题
|
||||
```
|
||||
97
工作日志/2021年7月25日-rythm分享.md
Normal file
@@ -0,0 +1,97 @@
|
||||
# rythm 孙锐 诗歌与节奏
|
||||
|
||||
## 什么是
|
||||
1. 节奏,断句,停顿。
|
||||
2. 韵律,升降,平仄调。不太一样。
|
||||
|
||||
|
||||
### 三种类型🌿
|
||||
1. 图解法。使用
|
||||
2. 音乐性理论
|
||||
3. 节奏韵律。使用科学上的物理参数。
|
||||
|
||||
|
||||
### 韵文格律与意义
|
||||
|
||||
1. 无关系
|
||||
2. 韵律能够在一定意义上反应意义。
|
||||
3. 节奏、音高的连续性。
|
||||
|
||||
> 同一个音能够通过不同的节奏反应不同的意思。啊?,啊~,啊、,啊——,。
|
||||
|
||||
|
||||
## 诗歌
|
||||
|
||||
|
||||
|
||||
## 中国诗歌
|
||||
|
||||
1. 诗经。最后动词的变迁。
|
||||
2. 楚辞,赋。
|
||||
3. 汉乐府、汉赋。音乐和词的脱离。
|
||||
4. 五言诗、七言诗。
|
||||
5. 南北朝民歌
|
||||
6. 南朝文学。赋,很押韵。
|
||||
7. 律体。意义上的对仗---->声音上的对仗。声韵学。
|
||||
8. 永明体。诗歌的音乐性降低,而文字上的音。
|
||||
|
||||
> 神婆。会在死亡的时候,唱诗。
|
||||
|
||||
|
||||
> 诗是一种高雅的文学形式。可是从诗经、古代严格的五律七律、到后来宽泛的词、到现在的现代诗、到现在的歌曲。是否从一种高雅的形式,逐渐再融合成一种普通人用来表达感情的很世俗的东西。感觉诗歌的文学上的韵律,越来越宽泛。是由什么原因?
|
||||
|
||||
|
||||
## 总结
|
||||
音节。节奏。重音和停顿上
|
||||
|
||||
|
||||
1. 字的个数,也就是一个节奏下,音的个数,变得更随意。
|
||||
|
||||
|
||||
|
||||
# rythm 张玄 音乐的节奏
|
||||
|
||||
### 定义
|
||||
|
||||
1. 音乐:旋律、和声、节奏。
|
||||
2. 规律,能够预测的变换。
|
||||
3. 节奏(有规律的声音变化):速度、拍子、重音。
|
||||
|
||||
|
||||
### 组成
|
||||
|
||||
1. 速度:取决于人能理解的上限。
|
||||
2. 拍子:古代传统音乐。一板(重音)三眼(轻音 ),一板一眼
|
||||
|
||||
|
||||
|
||||
## 概念
|
||||
|
||||
音乐的三要素指的是旋律、节奏与和声。
|
||||
|
||||
旋律:
|
||||
|
||||
又称曲调。音乐的起伏是按照一定的节奏水平有序地组织起来的,形成一个曲调。旋律是音乐形式中最重要的表现手段,是音乐的本质,是音乐的决定性因素。曲调的方向是可变的。有三个基本方向:水平方向、向上方向和向下方向。
|
||||
同一音调的进展方向称为水平;从低音到高音,向上;从高音到低音,向下。曲调发展的常用方式是“谐音重复”、“渐进”和“跳进”。根据音阶的相邻音调,它被称为进行音,三度的跳跃称为小跳跃,四度以上的跳跃称为大跳跃。
|
||||
节奏:
|
||||
|
||||
音乐的节奏是指音乐运动中中音的长度和强度。音乐的节奏常被比作音乐的骨架。节拍是音乐中拍子和拍子的周期性和规则性的重复。中国传统音乐称节奏为“板眼”,“板眼”等同于强拍;“眼”等同于亚强拍(中眼)或弱拍。
|
||||
和声:
|
||||
|
||||
和声包括“和弦”和“和声进行”。和弦通常是三个或更多声音的组合,这些声音根据一定的规则纵向(同时)重叠。和弦的横向组织就是和声进行。和声具有明显的强、轻、厚、薄的色彩效果,还具有构成分句、段落和结尾乐的功能。
|
||||
|
||||
|
||||
## 问题
|
||||
|
||||
声音上的和谐。和意义上的和谐。诗歌包含声音和意义。
|
||||
|
||||
|
||||
一段意义上的终止符。
|
||||
|
||||
|
||||
|
||||
|
||||
# 下次的主题
|
||||
|
||||
|
||||
西部。
|
||||
1
工作日志/2021年7月28日-今日计划.md
Normal file
@@ -0,0 +1 @@
|
||||
## 任务
|
||||
56
工作日志/2021年7月31日-西部分享.md
Normal file
@@ -0,0 +1,56 @@
|
||||
## 荒野大镖客
|
||||
|
||||
* 1899年美国西部。移民,秩序。
|
||||
|
||||
|
||||
|
||||
## 中国“西部”
|
||||
> 中国语境下的西部与西方。
|
||||
|
||||
|
||||
* 西部与西方
|
||||
* 西部的自然景色,风光很美
|
||||
* 西部的经济特征,落后奇异
|
||||
* 西方一般是指文化政治上的一种团体。
|
||||
* 中国的“西部”
|
||||
* 以行政区划作为西部的官方定义。
|
||||
* 西部大开发的几个省份。东部支援西部。
|
||||
* 语言习惯与地理上的西部,西部、中部、东部、东北
|
||||
* 美国西部
|
||||
* 狂野,潇洒。西部世界、荒野大镖客。
|
||||
* 共同点:地理上。气候上相似。历史上的演变,向西部扩张。未知与浪漫。
|
||||
* 不通点:经济发展差异问题。扩张方式,民族自治与血腥残暴。
|
||||
* “西”
|
||||
* 死亡、沉寂、岁月流逝、人生迟暮
|
||||
* 西风、阴(西)阳(东)
|
||||
* 是不是西部的文化里,总感觉与奇异,那种毒药,
|
||||
|
||||

|
||||
|
||||
|
||||
|
||||
## 中国历史上的“西域”。
|
||||
* 北京城这么考究,他的方位到底是地磁北方还是地轴北方呢?
|
||||
*
|
||||
## 西部世界观影及推荐
|
||||
|
||||
|
||||
## 西部军区
|
||||
|
||||
|
||||
1. 作战指挥(打仗)
|
||||
2. 领导管理(培养)
|
||||
|
||||
|
||||
|
||||
|
||||
## “电话”
|
||||
* 科幻,源于未知的浪漫。
|
||||
|
||||
* 门。一扇门。人们总在赋予它更多的含义。刚开始,打开这扇门,你能听到电话线另外一段的声音,再后来,可能听到来自更遥远的声音,甚至是千里之外的影像图片。基于这种门的思路,越来越多的人,想要通过这扇门看到更多的东西。像现在手机上已经可以传递货币,可以传递爱情,但究其本质还是一种数据。而科幻无非基于两点,空间上的延展与时间上的穿梭。
|
||||
* 人们希望通过这扇门能够传递物质,实现瞬间的转移,也想要通过这扇门跨越时间,向过去与未来发送信息。说不定真的可以实现,而且还可以很好的解决某个悖论。我们没有收到未来的信息,是因为我们还没有造出第一扇门,迎接未来的人。
|
||||
* 而科幻作品往往不是用来像漫威动画里那种堆切科幻元素的现代社会情愫,而是在探讨某一科技出现之后的社会学问题。我觉得科幻作品中的科幻元素只是背景,而真正让人思考的是其中的人文社会变化。
|
||||
|
||||
|
||||
|
||||
* 我觉得我抛出的每一个观点都有很强的主观色彩,很容易出现矛盾和冲突。要讨论的可能还真的挺多。
|
||||
44
工作日志/2021年7月9日-七月份安排.md
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
## 任务
|
||||
### 毕设
|
||||
* 阅读论文(两周)(每天十篇可能读完!!!)
|
||||
* 恶意软件相关的论文
|
||||
* 联邦学习相关的论文
|
||||
* 非独立同分布相关的文章
|
||||
* ~~联邦半监督学习的文章(这一个点确实可以去掉了)~~
|
||||
* 完成实验(四周)(7.25-8.8)
|
||||
* 联邦学习针对非独立同分布(手写体数据实验实现)的实验(一周)
|
||||
* 恶意软件特征提取的实验(一周) 什么样的数据集?怎样的方法提取特征?提取哪些特征用于实验?使用什么样的模型?
|
||||
* 联邦学习针对恶意软件数据集的实验。(一周)
|
||||
* 差分隐私应用的实验(一周)
|
||||
* ~~联邦半监督学习的实验~~
|
||||
* 完成小论文(三周)
|
||||
* 一篇关于非独立同分布联邦学习的小实验
|
||||
* 完成大论文(四周)
|
||||
* 基于联邦学习的恶意软件检测。
|
||||
* 完成恶意软件检测展示系统(四周)
|
||||
|
||||
### 就业
|
||||
|
||||
* 基础知识复习
|
||||
* 算法刷题
|
||||
* 参加招聘会。能在实习结束前,拿到三个offer。
|
||||
|
||||
|
||||
## 计划
|
||||
1. 阅读联邦学习的相关论文7.10-7.24
|
||||
2. 在手写体数据集上复现一些列解决非独立同分布的方法。7.24-7.30
|
||||
3. 阅读恶意软件的相关论文7.30-8.2
|
||||
4. 实现恶意软件数据集处理和特征提取8.2-8.6
|
||||
5. 在恶意软件数据集上复现一系列解决非独立同分布的方法。8.6-8.10
|
||||
6. 完成小论文8.15、大论文8.20、恶意软件检测的展示系统8.25
|
||||
|
||||
## 安排
|
||||
|
||||
* 上午8.00-12.00
|
||||
* 读论文
|
||||
* 下午2.00-6.00
|
||||
* 做实验
|
||||
* 晚上7.00-11.00
|
||||
* 准备就业
|
||||
|
||||
37
工作日志/2021年8月7日.-电话分享md
Normal file
@@ -0,0 +1,37 @@
|
||||
# 电话
|
||||
|
||||
|
||||
## 电话定义
|
||||
|
||||
* 一种通信工具、一种传输工具。端到端的通信模式。
|
||||
|
||||
## 电影
|
||||
|
||||
* 剧情介绍
|
||||
* “电话”功能
|
||||
* 电话对于电影剧情的作用以及电话意向的分析
|
||||
|
||||
|
||||
## 动漫
|
||||
|
||||
* 剧情介绍
|
||||
* “电话”功能
|
||||
* 电话对于电影剧情的作用以及电话意向的分析
|
||||
* 为什么选择电话
|
||||
|
||||
|
||||
## 小说
|
||||
|
||||
* 剧情介绍
|
||||
* “电话”功能
|
||||
* 电话对于电影剧情的作用以及电话意向的分析
|
||||
* 为什么选择电话
|
||||
|
||||
|
||||
## “科幻世界的电话”——通向异世界的大门
|
||||
|
||||
|
||||
## “科幻世界的电话”——融合尖端科技的设备(功能幻想)
|
||||
|
||||
|
||||
## “科幻世界的电话”——形式变化
|
||||
14
工作日志/中期报告.md
Normal file
@@ -0,0 +1,14 @@
|
||||
|
||||
l 开题报告中确定的论文研究计划,按计划应该完成的工作;
|
||||
|
||||
l 已完成的论文研究工作和取得的阶段性成果;
|
||||
|
||||
l 存在的问题、尚未完成的工作及后期工作的设想和安排。
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
截止时间为2021年8月30日
|
||||
分组,学生才能打印中期检查表
|
||||
报告时间15分钟左右,其中学生汇报不超过10分钟,专家提问不超过5分钟。
|
||||
33
工作日志/小论文.md
Normal file
@@ -0,0 +1,33 @@
|
||||
## Introduction
|
||||
|
||||
### Background
|
||||
|
||||
### Problems
|
||||
|
||||
### Contributions
|
||||
> what we do to achieve aims.
|
||||
* fedRed算法
|
||||
* 收敛速度
|
||||
* 实验内容(通过实验内容得出来的结论)
|
||||
|
||||
### Aims & Goodneeds
|
||||
* More local updates.
|
||||
* Gains of cooperation.
|
||||
* Generalization to new clients.
|
||||
|
||||
|
||||
## Model
|
||||
### problems
|
||||
* 用数学语言描述自己的目标
|
||||
### models
|
||||
* 用数学语言描述自己的**模型**本身。
|
||||
* 这里更偏向与目标的模型
|
||||
|
||||
## Algorithm
|
||||
|
||||
* **模型训练**算法。这里更偏向与训练的过程和合作的过程。
|
||||
|
||||
|
||||
|
||||
## Experiment
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
|
||||
# 2020年9月
|
||||
|
||||
## 第一周(9.1-9.6)
|
||||
* 阅读漏洞利用的相关知识,证明了漏洞利用的不可行。
|
||||
@@ -37,3 +37,4 @@
|
||||
* 吴恩达深度学习完成
|
||||
|
||||
|
||||
# 2021年3月
|
||||
20
工作日志/毕业设计.md
@@ -51,9 +51,18 @@
|
||||
|
||||
### 研究内容和研究目标
|
||||
|
||||
1. 联邦隐私保护学习方案
|
||||
2. 联邦半监督学习方案
|
||||
3. 联邦非独立同分布学习方案
|
||||
1. 联邦隐私保护学习方案——差分隐私、同态加密
|
||||
2. 联邦半监督学习方案——半监督方案?
|
||||
3. 联邦非独立同分布学习方案——某一个方案
|
||||
|
||||
论文贡献(到时候再展开或者压缩内容。)
|
||||
1. 实现了差分隐私,并通过实验验证了差分隐私对参数隐私的保护
|
||||
2. ~~实现了半监督学习方案。这个可以去掉,如果最后实现起来比较简单,则可以加上~~
|
||||
3. 使用了联邦元学习解决了非独立同分布问题
|
||||
4. 一个恶意软件特征提取和分析工具
|
||||
5. 完成了相关的实验验证。证明了balabala
|
||||
6. 构建了联邦学习框架和恶意软件检测系统。能够使用半监督学习,差分隐私保护用户的隐私,能够针对非独立同分布场景,训练机器学习模型。恶意软件检测系统包括特征提取模块和模型检测模块。
|
||||
7. 提供了一个训练框架,以及一个可用的模型。
|
||||
|
||||
### 论文结构
|
||||
|
||||
@@ -82,8 +91,9 @@
|
||||
### 6 非独立同分布的原理
|
||||
|
||||
> 非独立同分布的原理、表示方法(衡量标准)、产生的影响(论证非独立同分布是联邦学习解决问题中的关键问题。)
|
||||
> 对非独立同分布的数学的描述。
|
||||
|
||||
## 第三章:基于联邦学习的恶意软件检测算法
|
||||
## 第三章:基于差分隐私和联邦学习的恶意软件检测算法
|
||||
|
||||
## 第四章:基于联邦半监督学习的恶意软件检测算法
|
||||
|
||||
@@ -91,7 +101,7 @@
|
||||
|
||||
## 第六章:恶意软件检测算法的实验与结果
|
||||
|
||||
## 第七章:恶意软件检测系统构建
|
||||
## 第七章:恶意软件检测仿真系统构建
|
||||
|
||||
1. 训练控制模块
|
||||
2. 网络通信模块
|
||||
|
||||
@@ -121,7 +121,7 @@ public int climbStairs(int n) {
|
||||
|
||||
### 算法设计
|
||||
|
||||
* **状态定义**: 设动态规划列表 dpdp ,dp[i]dp[i] 代表以元素 nums[i]nums[i] 为结尾的连续子数组最大和。
|
||||
* **状态定义**: 设动态规划列表 dp ,dp[i]dp[i] 代表以元素 nums[i]nums[i] 为结尾的连续子数组最大和。
|
||||
* 为何定义最大和 dp[i]dp[i] 中必须包含元素 nums[i]nums[i] :保证 dp[i]dp[i] 递推到 dp[i+1]dp[i+1] 的正确性;如果不包含 nums[i]nums[i] ,递推时则不满足题目的 连续子数组 要求。
|
||||
* **转移方程**: 若 dp[i-1] \leq 0dp[i−1]≤0 ,说明 dp[i - 1]dp[i−1] 对 dp[i]dp[i] 产生负贡献,即 dp[i-1] + nums[i]dp[i−1]+nums[i] 还不如 nums[i]nums[i] 本身大。
|
||||
* 当 dp[i - 1] > 0dp[i−1]>0 时:执行 dp[i] = dp[i-1] + nums[i]dp[i]=dp[i−1]+nums[i]
|
||||
@@ -183,4 +183,102 @@ public int climbStairs(int n) {
|
||||
}
|
||||
return max;
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## 4 传递信息
|
||||
|
||||
### 问题描述
|
||||
小朋友 A 在和 ta 的小伙伴们玩传信息游戏,游戏规则如下:
|
||||
|
||||
有 n 名玩家,所有玩家编号分别为 0 ~ n-1,其中小朋友 A 的编号为 0
|
||||
每个玩家都有固定的若干个可传信息的其他玩家(也可能没有)。传信息的关系是单向的(比如 A 可以向 B 传信息,但 B 不能向 A 传信息)。
|
||||
每轮信息必须需要传递给另一个人,且信息可重复经过同一个人
|
||||
给定总玩家数 n,以及按 [玩家编号,对应可传递玩家编号] 关系组成的二维数组 relation。返回信息从小 A (编号 0 ) 经过 k 轮传递到编号为 n-1 的小伙伴处的方案数;若不能到达,返回 0。
|
||||
|
||||
示例 1:
|
||||
```
|
||||
输入:n = 5, relation = [[0,2],[2,1],[3,4],[2,3],[1,4],[2,0],[0,4]], k = 3
|
||||
|
||||
输出:3
|
||||
|
||||
解释:信息从小 A 编号 0 处开始,经 3 轮传递,到达编号 4。共有 3 种方案,分别是 0->2->0->4, 0->2->1->4, 0->2->3->4。
|
||||
```
|
||||
|
||||
### 问题分析
|
||||
|
||||
|
||||
### 策略选择
|
||||
* 有三种不同的策略选择:广度优先搜索、深度优先搜索、动态规划。本文采用动态规划的思路,实际上与广度优先搜索的思路是一致的。看在第k步能到达的所有节点。
|
||||
|
||||
### 算法设计
|
||||
|
||||
|
||||
* **状态定义**dp[j] 为经过 i轮传递到编号j 的玩家的方案数,其中k0≤i≤k,n0≤j<n。可以不用记住更久远的历史状态。
|
||||
* **转移方程** 
|
||||
* **初始状态** dp[0]=1
|
||||
* **终止状态** 最终得到dp[n−1] 即为总的方案数
|
||||
|
||||
|
||||
### 算法分析
|
||||
|
||||
* 时间复杂度:O(km)。其中 m 为 relation 数组的长度。
|
||||
* 空间复杂度:O(n)O(n)。
|
||||
|
||||
### 算法实现
|
||||
```c++
|
||||
class Solution {
|
||||
public:
|
||||
int numWays(int n, vector<vector<int>>& relation, int k) {
|
||||
// // 构建邻接矩阵
|
||||
// vector<vector<int>> vec(n,vector<int>(n,0));
|
||||
// for(auto a:relation){
|
||||
// vec[a[0]][a[1]]=1;
|
||||
|
||||
// }
|
||||
// // for(int i=0;i<n;i++){
|
||||
// // for(int j=0;j<n;j++){
|
||||
// // cout<<vec[i][j]<<"\t";
|
||||
// // }
|
||||
// // cout<<endl;
|
||||
// // }
|
||||
// // 构建有向图
|
||||
|
||||
|
||||
// vector<int> result;
|
||||
// result.push_back(0);
|
||||
// for(int i=0;i<k;i++){
|
||||
// // for(int k:result){
|
||||
// // cout<<k<<"\t";
|
||||
// // }
|
||||
// // cout<<endl;
|
||||
// vector<int> temp;
|
||||
// for(auto a:result){
|
||||
// for(int j=0;j<n;j++){
|
||||
// if(vec[a][j]==1)temp.push_back(j);
|
||||
// }
|
||||
// }
|
||||
// result.assign(temp.begin(),temp.end());
|
||||
|
||||
// }
|
||||
// int sum =0;
|
||||
// for(auto a:result){
|
||||
// if(a==n-1)sum++;
|
||||
// }
|
||||
// return sum;
|
||||
|
||||
// 尝试使用动态规划求解。可以不用构建关系矩阵,每次遍历关系矩阵就好了。。然后每轮迭代能够到的位置。
|
||||
vector<int> dp(n,0);
|
||||
dp[0]=1;
|
||||
for(int i=0;i<k;i++){
|
||||
vector<int> temp(n,0);
|
||||
for(auto a: relation){
|
||||
temp[a[1]]+=dp[a[0]];
|
||||
}
|
||||
dp.assign(temp.begin(),temp.end());
|
||||
}
|
||||
return dp[n-1];
|
||||
|
||||
}
|
||||
};
|
||||
```
|
||||
BIN
算法/A类:基本算法/image/2021-07-23-22-46-02.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
BIN
算法/A类:基本算法/image/2021-07-23-22-46-11.png
Normal file
|
After Width: | Height: | Size: 5.7 KiB |
@@ -94,4 +94,81 @@ public:
|
||||
return ans;
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
|
||||
|
||||
## 2 区间覆盖问题
|
||||
|
||||
### 问题描述
|
||||
|
||||
给你一个二维整数数组 ranges 和两个整数 left 和 right 。每个 ranges[i] = [starti, endi] 表示一个从 starti 到 endi 的 闭区间 。
|
||||
|
||||
如果闭区间 [left, right] 内每个整数都被 ranges 中 至少一个 区间覆盖,那么请你返回 true ,否则返回 false 。
|
||||
|
||||
已知区间 ranges[i] = [starti, endi] ,如果整数 x 满足 starti <= x <= endi ,那么我们称整数x 被覆盖了。
|
||||
|
||||
|
||||
|
||||
示例 1:
|
||||
```
|
||||
输入:ranges = [[1,2],[3,4],[5,6]], left = 2, right = 5
|
||||
输出:true
|
||||
解释:2 到 5 的每个整数都被覆盖了:
|
||||
- 2 被第一个区间覆盖。
|
||||
- 3 和 4 被第二个区间覆盖。
|
||||
- 5 被第三个区间覆盖。
|
||||
```
|
||||
### 问题分析
|
||||
|
||||
* 区间覆盖问题
|
||||
|
||||
### 策略选择
|
||||
|
||||
* 数据结构:数组
|
||||
* 算法选择:线性区间操作
|
||||
### 算法设计
|
||||
* 遍历 \textit{ranges}ranges 中的所有区间 [l, r][l,r],将区间内每个整数的 \textit{cnt}cnt 值加上 11。遍历结束后,检查 [\textit{left},\textit{right}][left,right] 内的每个整数的 \textit{cnt}cnt 值是否均大于 00,是则返回 \texttt{true}true,否则返回 \texttt{false}false。
|
||||
* 在维护完差分数组 \textit{diff}diff 后,我们遍历 \textit{diff}diff 求前缀和得出覆盖每个整数的区间数量。下标 ii 对应的被覆盖区间数量即为初始数量 00 加上 [1, i][1,i] 闭区间的变化量之和。在计算被覆盖区间数量的同时,我们可以一并判断 [\textit{left}, \textit{right}][left,right] 闭区间内的所有整数是否都被覆盖。
|
||||
|
||||
### 算法分析
|
||||
* 时间复杂度:O(n + l)
|
||||
* 空间复杂度:O(l)
|
||||
### 算法实现
|
||||
|
||||
```C++
|
||||
class Solution {
|
||||
public:
|
||||
bool isCovered(vector<vector<int>>& ranges, int left, int right) {
|
||||
// 一种差分数组的方法。
|
||||
vector<int> vec(right-left+2,0);
|
||||
for(auto k:ranges){
|
||||
if(k[0]>right || k[1]<left)continue;
|
||||
|
||||
if(k[0]<left){
|
||||
vec[left-left]++;
|
||||
}
|
||||
else{
|
||||
vec[k[0]-left]++;
|
||||
}
|
||||
|
||||
if(k[1]>right){
|
||||
vec[right-left+1]--;
|
||||
}
|
||||
else{
|
||||
vec[k[1]-left+1]--;
|
||||
}
|
||||
}
|
||||
|
||||
int m = 0;
|
||||
for(int a =left;a<=right;a++){
|
||||
m+=vec[a-left];
|
||||
if(m<=0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
}
|
||||
};
|
||||
```
|
||||
94
算法/B类:数据结构算法/4.5 链表与映射.md
Normal file
@@ -0,0 +1,94 @@
|
||||
# 链表与映射
|
||||
|
||||
|
||||
## 复制带随机指针的链表
|
||||
|
||||
### 问题描述
|
||||
|
||||
给你一个长度为 n 的链表,每个节点包含一个额外增加的随机指针 random ,该指针可以指向链表中的任何节点或空节点。
|
||||
|
||||
构造这个链表的 深拷贝。 深拷贝应该正好由 n 个 全新 节点组成,其中每个新节点的值都设为其对应的原节点的值。新节点的 next 指针和 random 指针也都应指向复制链表中的新节点,并使原链表和复制链表中的这些指针能够表示相同的链表状态。复制链表中的指针都不应指向原链表中的节点 。
|
||||
|
||||
例如,如果原链表中有 X 和 Y 两个节点,其中 X.random --> Y 。那么在复制链表中对应的两个节点 x 和 y ,同样有 x.random --> y 。
|
||||
|
||||
返回复制链表的头节点。
|
||||
|
||||
用一个由 n 个节点组成的链表来表示输入/输出中的链表。每个节点用一个 [val, random_index] 表示:
|
||||
|
||||
val:一个表示 Node.val 的整数。
|
||||
random_index:随机指针指向的节点索引(范围从 0 到 n-1);如果不指向任何节点,则为 null 。
|
||||
你的代码 只 接受原链表的头节点 head 作为传入参数。
|
||||
|
||||
|
||||
|
||||
示例 1:
|
||||
|
||||

|
||||
```
|
||||
输入:head = [[7,null],[13,0],[11,4],[10,2],[1,0]]
|
||||
输出:[[7,null],[13,0],[11,4],[10,2],[1,0]]
|
||||
```
|
||||
|
||||
### 问题分析
|
||||
|
||||
* 需要建立原链表节点到新链表节点的映射。这个映射本可以通过添加子段实现,但是不能添加。只能使用一个map完成链表映射了。
|
||||
|
||||
### 策略选择
|
||||
|
||||
|
||||
|
||||
### 算法设计
|
||||
|
||||
### 算法分析
|
||||
|
||||
### 算法实现
|
||||
|
||||
```C++
|
||||
/*
|
||||
// Definition for a Node.
|
||||
class Node {
|
||||
public:
|
||||
int val;
|
||||
Node* next;
|
||||
Node* random;
|
||||
|
||||
Node(int _val) {
|
||||
val = _val;
|
||||
next = NULL;
|
||||
random = NULL;
|
||||
}
|
||||
};
|
||||
*/
|
||||
class Solution {
|
||||
public:
|
||||
Node* copyRandomList(Node* head) {
|
||||
if(head==nullptr)return nullptr;
|
||||
// 使用vector,修改原链表的方法不行。
|
||||
// 使用map建立原链表到新链表的映射
|
||||
map<Node*,Node*> m;
|
||||
Node* old_head = head;
|
||||
Node* temp_old = head;
|
||||
Node* new_head = new Node(head->val);
|
||||
Node* temp_new = new_head;
|
||||
while(temp_old->next!=nullptr){
|
||||
m[temp_old]=temp_new;
|
||||
temp_new->next = new Node(temp_old->next->val);
|
||||
|
||||
temp_old=temp_old->next;
|
||||
temp_new=temp_new->next;
|
||||
|
||||
}
|
||||
m[temp_old]=temp_new;
|
||||
|
||||
temp_old = head;
|
||||
while(temp_old!=nullptr){
|
||||
if(temp_old->random!=nullptr){
|
||||
m[temp_old]->random=m[temp_old->random];
|
||||
}
|
||||
temp_old=temp_old->next;
|
||||
}
|
||||
|
||||
return new_head;
|
||||
}
|
||||
};
|
||||
```
|
||||
BIN
算法/B类:数据结构算法/image/2021-07-23-13-09-12.png
Normal file
|
After Width: | Height: | Size: 42 KiB |
98
读书思考/《呼吸》.md
Normal file
@@ -0,0 +1,98 @@
|
||||
## 《商人和炼金术师之门》
|
||||
|
||||
也许因为在做“科幻世界的电话”主题的分享,感觉电话与门有异曲同工之妙。主人公讲述了三位商人与一个炼金术师巴沙拉特的门的故事。
|
||||
|
||||
巴沙拉特展示了一种可以在过去和未来之间穿梭的神奇的年门,通过一个金属环的穿梭实验,展示了从一端到另一端会存在时间差。
|
||||
|
||||
第一个故事中,一个叫哈桑的绳匠,在二十年后的自己的指引下,躲过劫难,发现了一箱金子,然后发财,在二十年后成为了一个富豪。“仗势未来,横行现在的人,也许在第一次使用你年门的饿时候,就会发现他年长的自己早已亡故”。“忏悔和赎罪可以抹掉过去的罪孽”。“未来也是一样的,在这方面,它和过去没有区别”。故事没有着眼于未来与现在的矛盾,到底是先挖出箱子还是未来的人先知道箱子就在那里,无从得知。
|
||||
|
||||
第二个故事中,一个叫阿吉布的织工,发现二十年后的自己依旧穷困潦倒,却在床头存有一箱金币。于是从二十年后自己那里偷走了一箱金币,因此与爱慕的女人生活在一起,但是妻子却被强盗掳走,金币全都做了赎金。于是他开始一点点攒着金币,放在床头的箱子里,等着有朝一日,年轻的自己来偷走攒下的金币。同样他的妻子也回到过去,教会了他未来才掌握的、展示给妻子的东西。同样故事没有解释因果之间的矛盾,到底是自己先偷了金币,还是先攒下金币,到底是他妻子先看到自己的丈夫展示了床上的技巧还是先回去教会了她丈夫技巧。两个故事,无法从因果的角度解释问题,但却说明了一件事,过去和未来一样,都无法改变,只存在一条时间线,实现了自洽。
|
||||
|
||||
第三个故事,是作者自己,穿越到过去,想要去拯救因为自己一时冲动而错过的女人。同样,历史没办法改变,他一路上经历各种变故,自己的妻子还是在到达之前死亡了。“不会回头的东西有四件:说出口的话、离弦的箭、逝去的生活和失去的机会”。“偶然事件和有意安排,他们是同一张壁毯的两面。您或许觉得某一面更好看,但您不能说只有这一面才是真的,另一面是假的”。
|
||||
|
||||
“她让我告诉您,弥留之际,她仍旧想念着您。她让我告诉您,虽然他的一生很短暂,但却十分幸福,这全是因为有了您”。
|
||||
“无论过去还是未来,我们都无法改变,只能更深刻地理解他们。我第一次回到过去旅行,什么都没有改变,但我知道的事情却改变了一切。事情只能这样,必然这样。如果我们的人生是安啦讲述的一个故事,那么我们即使故事的聆听着,有事故事的角色。聆听和扮演人生这个故事,我们最终才能从中得到教益。”
|
||||
“没有什么能抹掉过去。但你可以忏悔,可以赎罪。你可以得到宽恕。只有这些,但这已经足够了。”
|
||||
“时间旅行更像一扇门”。“只存在唯一一条自洽的时间线”。“无力改变过去不一定就会带来悲伤”。
|
||||
|
||||
|
||||
|
||||
## 《呼吸》
|
||||
|
||||
神作。神在我根本读不懂,又能读懂一点点。我想我比较喜欢作者,很大一部分原因,是前两篇科幻文章中那种对于无可奈何的时空观的讨论,最终的结论居然都那么积极。虽然我们面对的是悲哀的宇宙规律,但是我们仍旧可以选择积极应对。太阳迟早要落下,但是我们依然要学会微笑。
|
||||
|
||||
在这里人们生活在一个由巨大穹顶的笼中(可以想象,那就是我们看不到边际的宇宙)。而所有的动力都来源那两个肺,肺中的氩气。主人公在由一次时钟紊乱一起的恐慌中,进行了一次自我解刨实验,发现驱动生命的本质,靠着内外的气压差,推动自己肢体运动、大脑思考。而导致时钟紊乱的,是由于多年来,周围气压升高,气压差推动的动力不足,使所有人的认知出现了偏差。
|
||||
|
||||
“其实我们不是在消耗空气。每天我从新欢的费仲获取的空气完全从关节溢出,排放到周围的大气中。我们只是把高压的气体变成了低压气体。我们身体的每一个动作都对宇宙气压平衡起到了推波助澜的作用,我所思考的每一个想法,都加速了世界末日的到来。”
|
||||
|
||||
“我所有的欲望都是这个宇宙缓缓呼吸溢出的气流。在这漫长的呼吸结束之前,我的思维将一直存在。”
|
||||
|
||||
“随着钟摆疯狂地摆动,滴答的时钟好像变成了叫个不休的鸟儿;坠向地面的物体似乎受到了弹簧的推动;舞动的绳索仿佛变成了噼啪作响的皮鞭”。
|
||||
|
||||
“我们的宇宙在花香平衡点的过程中也许只能静静的呼气,但它繁衍出的我们这个丰富多彩的世界却是个奇迹,只有诞生了你们的宇宙才能与之媲美”。
|
||||
|
||||
“得以生存便是一个奇迹,能够思考就是一件快乐的事情。”
|
||||
|
||||
|
||||
我想这篇文章关于熵(混乱度)的讨论,也是我一直疑惑的问题。能量虽然守恒,但是熵却一直在增加。也就是说能量不会消失,但会从有序的能量变成无需的能量。人们所有在做的事情,都是一样的。人们耗费大量的能量,实现了局部逆商的过程。例如将水流从低处运到高出,通过吃各种食物,让最开始的卵细胞变成复杂的精巧的学会思考的人体。然后又逐渐的将这种局部有序释放出来,产生各种所谓的价值,例如奔跑的汽车。宇宙亦是如此,通过收缩爆炸将能量释放到广袤的空间当中,又通过塌缩将能量汇聚成一点。
|
||||
|
||||
释放能量等于摧毁秩序。
|
||||
|
||||
“能量守恒定律说能量既不会创生,也不会消失。我们在消耗秩序,造成无序。我们靠增加宇宙的无序度卫生。正因为宇宙诞生在一个高度有序的状态,我们才能够存在。”
|
||||
|
||||
|
||||
## 《前路迢迢》
|
||||
|
||||
“反向延时电路”一种向过去通信的方法。也是电话的一种吧。其实科幻作品的本质并非科学。而是社会学。无论是三体当中,逻辑作为社会学家成为一个成功的面壁者还是程心最终导致了同归于尽结局,所有的原因,都是人性,而不是科技。哪怕是银河帝国,也是描述的披着高科技外衣的帝国政治,而非漫威那种通过科技和力量来左右社会。真正能够左右社会的,只有社会规律,只有组成社会的个体——人。
|
||||
|
||||
本篇与第一篇更相似。第一篇是对时间穿梭的积极响应,而这里却展示了如何通过因果律来摧毁人的自由意志。在不违背因果的情况下与过去通信,等价与失去自由意志。我觉得我们可以讨论这种设定的巧妙之处,针对这种设定造成的社会现象,讨论可能出现的一些问题。
|
||||
|
||||
一个能在你按下一秒之前闪烁的预测器。通过一个所谓的反向延时电路实现。负延时为一秒钟。
|
||||
“通常来说,一个人会着魔般地连续玩好几天,拿给朋友看,绞尽脑汁瞒骗装置。这个人可以假装对它失去兴趣,但他不可能忘记其中的内涵——接下来几周里,‘未来无法改变’这个年头深入他的脑海。有一部分人意识到选择毫无意义,从此拒绝再做出任何决定。他们纷纷停止了一起自发活动,最后甚至三分之一的玩家必须入院治疗,因为他们连自己吃饭都做不到。终极状态是运动不能性缄默,醒状昏迷的一种。他们能用眼球追踪动作,偶尔改变躺姿,但仅止于此。运动能力依然存在,动因却已经消失”
|
||||
|
||||
“我正在你的额未来一年以后想你发送这个警告,它是兆秒级反向延时电路首次应用于通信设备后收到的第一个长信息。关于其他问题的消息将陆续送来。我给你的信息是这样的:假装你拥有自由意志。关键在于你必须假装你的决定至关重要,即使你知道事实并非如此。显示不重要,重要的是你相信什么,而相信谎言是避免醒状昏迷的唯一方法。文明如今维系于自我欺骗智商。也许一向如此。”
|
||||
|
||||
“我既然直到无法改变,那我为何还要这样做呢?因为我无法选择。”
|
||||
|
||||
|
||||
|
||||
## 《软件体的生命周期》
|
||||
|
||||
一次关于机器人的全面思考与讨论。我觉得作者没有强调什么是对的、什么是错的。而是抛出了各种观点之间的大辩论。
|
||||
|
||||
|
||||
|
||||
* 数据地球(瑞山数码、虚拟世界)——神经源引擎
|
||||
* 下一维度(虚拟世界)——千纸引擎
|
||||
* 任意之所(虚拟世界)——花白姿引擎
|
||||
* 真实空间(维萨传媒、虚拟世界)——新的分布式架构
|
||||
* 蓝色伽马(数码体公司)——神经源(基因组引擎,需要漫长的培养生命周期)——数码体。经验是最好的老师。赋予学习的能力,让他们自由掌握知识。强调与数码体的互动、陪伴和成长。
|
||||
* 灵猴机甲(玩具公司)——灵猴机甲。将虚拟数码体映射到现实世界中的躯体内。
|
||||
* 信息自由阵线(黑客组织)。导致一系列针对数码体的克隆和虐待行为。
|
||||
* 玄思(基因组引擎,能用软件进行教育的数码体,避免和人交流的需要)——数码体。用于解决专门的问题,变成有用的数码体,“强调特定的用途和实用技巧,例如解谜、个人助理”。
|
||||
* 多维体(玄思数码体的实践公司,安娜捷立亲训练。)
|
||||
* 零一欲望(成人数码体,性领域)
|
||||
* 幂级器械(理想的人工智能,一个拥有纯粹认知的实体,不被任何情感羁绊、不被任何身体束缚的天才思想,知识广博、思维冷静,同时又具有理性的同情。阿兰图灵的舒马克龙体)
|
||||
|
||||
|
||||
|
||||
“就这样,数码体失去了三天的经历,包括它们第一次从小山上滚下来的记忆”。针对数码体不能说“操”字的回滚。
|
||||
|
||||
“所有神经源数码体都装有同感阻隔器,让他们对虐待免疫,从而对施虐也没有吸引力。不幸的是,面对有些伤害,没有任何办法保护他们,比如忽略”
|
||||
|
||||
我觉得安娜所坚持的数码体自由意志是虚伪的,它们只是把自己的自由意志强加在了自己的数码体上,而不是真正的捍卫数码体的自由意志。因为它们能够选择修改数码体的基因,让他们做出一些事,不做一些事。甚至能挂起它们的程序。
|
||||
|
||||
里面描述了很对人与这种数码体发生的故事,看着自己的数码体成长、抛弃自己的数码体、数码体的收留站、毫无耐心嫌弃自己的数码体太笨、数码体太调皮不听话而不断被回滚到标记点。
|
||||
|
||||
副本是否可卖?出卖自己的伙伴,还是自己培养出的一段程序。
|
||||
|
||||
让数码体成为法人,可以为自己的行为负责?沃尔?是否能够作为一个阶层收到法律的保护。
|
||||
|
||||
对数码体机器人的爱和与自己妻子之间的爱,以及通过生物化学药剂产生的爱。这之间到底有什么区别,是否存在联系。
|
||||
|
||||
数码体到底有没有作为性爱的权利。敏感部位的存在、数码体之间的性行为、选择自认为合适的性别、与人类伴侣配对建立感情。“全新的性领域,你的意思是说,把一种怪癖推广开来,直到它成为主流。”
|
||||
|
||||
|
||||
结果证明。作者是站在安娜这一边的。把数码体当做自己的宠物,仍旧需要时间去陪伴数码体的成长。而不是一出生就是二十岁的数码体。
|
||||
|
||||
“养个孩子,让你不得不认真思考一些让人头疼的问题:什么是爱?我们如何获得爱?为什么这个世界上存在罪恶、痛苦和失去?我们如何找到尊严与宽容?谁拥有权力?为什么?什么是解决矛盾的最佳途径。”“如果我们向赋予一个人工智能大的责任,那么我们需要为这些问题提供合理解答。要做到这一点,需要的不是把康德的所有书都植入人工智能的大脑,而是类似于父母对子女的那种精心照料。”
|
||||
17
读书思考/《霍乱时期的爱情》.md
Normal file
@@ -0,0 +1,17 @@
|
||||
## 我读了个什么
|
||||
|
||||
从一开始的霍乱,像霍乱一样到处死人的战争,像霍乱一样四处传播的糜烂的欲望与爱情,到最后升起的一面虚假霍乱旗帜的船只,以及上面包庇的到最后终在一起成为相知的眷侣。
|
||||
|
||||
从故事的角度。乌尔比诺医生死了。从三十多年前就有一个人开始盼望着、精心筹划着等待着这一刻的到来。在着三十年中,阿里萨因为近乎朝圣的迷恋着菲尔米娜,菲尔米娜过着幸福的夫妻生活。阿里萨压抑着自己的希望与绝望,近乎疯狂地成为当地的猎手,在各种各样的女人之间游走,沉浸在肉欲当中,却从未真正的喜欢上另外一个人,发生各种不伦的关系。然而在八十岁的时候,对待爱情,对待那个曾经的喜欢的执念,却仍旧像一个年轻人狂热、痴迷、幼稚。
|
||||
|
||||
他为了能够拥有平等的地位,成为了内河航运公司的老板。为了能够等到自己爱的人,前身健体精心计算着,企图通过寿命熬过对方这种愚蠢的方法取胜。五十年间,可以忍住不去见最爱的人,让所有的相遇看起来都那么巧合。五十年后,仍旧像个刚刚开始追求爱情,得到爱情的年轻人,依旧疯狂、冲动。
|
||||
|
||||
这大概就是爱而不得,白月光,白玫瑰,会以一种奇妙的存在,隐藏在男生的心底,无论自己多么疯狂与冲动,无论自己经历了多少风雨变得麻木不仁,变得愚蠢粗鄙,变得糜烂不堪,可是一旦遇到那样一个人,仿佛就会高尚起来,想要去写点诗歌颂扬它(作者笔下的阿里萨是虚假的诗人,一行诗我都没有见到,却仍然能够觉得他很浪漫,可能这就是对人物的留白),想要与她去远方旅行,开始止不住的幻想着它是女主角的各种各样的故事,大半夜都能从床上笑醒。
|
||||
|
||||
从爱情的角度我想他是伟大,是可以跨越时间的。“爱”一个人真的有那么神奇吗。即使在八十年后,人老珠黄了,依旧还是会选择它。
|
||||
|
||||
什么是爱情?我想作者并不是在歌颂阿里萨的爱情多么疯狂多么伟大。他向我们展示了各式各样的爱情的,乌尔比诺的爱情,用自己的优雅和学识,与自己喜欢的人生活在一起,会一起去旅行,一起参加活动,一起讨论生活中的琐事,也会有些小脾气,会考虑到家族的利益包庇了菲尔米娜父亲的丑闻,也会因为自己的冲动出轨而备受煎熬。是那种理性的爱情。
|
||||
|
||||
菲尔米娜嫁入豪门,享受着门第带来的上流生活,压抑了自己的脾气收敛了自己的锋芒,像个中规守矩的妻子,生养孩子,整理家务。
|
||||
|
||||
我想从道德的角度来说,这里没有谁是完整的人。没有谁可以用普世的道德观来衡量这里的每一个人。即使是菲尔米娜也只能在霍乱的掩护下踏上那条船。如果符合普世的道德,他大可以光明正大的去做。他与女儿决裂开始,到最后驶向黄金港的霍乱的船上,他就是在做着违背道德事情。没有谁比谁的道德更高尚,哪怕一点点。即使是阿里萨,即使是14岁的女孩,他们偷偷摸摸的行为,违反了这世间所有的道德的束缚。我想作者可能就是为了传达一种意思,爱情可以轻易的超越道德的范畴,为了爱情可以僭越道德与法律的束缚,同样,为了爱情也愿意放下自己的尊严和脾气,牺牲自己的个性,成为一个可怕的自律的人。因为爱情,可以有多失败,就可以有多成功。
|
||||
3
读书思考/简介.md
Normal file
@@ -0,0 +1,3 @@
|
||||
学而不思则罔,思而不学则殆。
|
||||
|
||||
深刻体会。每天思考一堆东西,沉浸在自己发现的小规律和小感悟当中,实际上,书中早有成套的理论,概括升华了你的结论。仅仅通过个人的无休止的思考得到的知识和觉悟始终是优先的,思而不学则殆,非常关键。以后多读书,在这里整理一下自己的读书笔记吧。
|
||||