Boost线程库学习笔记

boost thread类创建和销毁线程示例 boost thread boost thread类使用简单,能够方便地管理整个线程的全生命周期,应用广泛。 thread配合ios使用时,能够方便地创建线程池,具体请参考boost::asio::io_service创建线程池简单实例。 创建线程 对于一般的使用,是启动一个线程,运行一个函数,在函数内完成特定的任务。 #include <boost/thread.hpp> void foo() { cout << "foo" << endl; } boost: 阅读详情

http://www.cnblogs.com/younes/archive/2010/06/06/1752745.html

一、创建一个线程

创建线程

    boost::thread myThread(threadFun);

    需要注意的是:参数可以是函数对象或者函数指针。并且这个函数无参数,并返回void类型。

    当一个thread执行完成时,这个子线程就会消失。注意这个线程对象不会消失,它仍然是一个还处在它的生存期的C++对象。同理,当对一个堆上的线程对象的指针调用delete时候,线程对象被销毁,操作系统的线程并不能保证就消失。

放弃时间片

    boost::thread::yield();

    当前线程放弃余下的时间片。

等待一个线程

    myThread.join();

    调用这个方法的线程进入wait状态,直到myThread代表的线程完成为止。如果它不结束的话,join方法就不会返回。join是一个等待子线程结束的最好的方法。如果主程序不调用join方法而直接结束,它的子线程有可能没有执行完成,但是所有的子线程也随之退出。不调用join方法,主线程就不会等待它的子线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/xtime.hpp>
 
struct  MyThreadFunc {
    void  operator( )( ) {
       // Do something long-running...
    }
} threadFun;
 
int  main( ) {
 
    boost:: thread  myThread(threadFun); // Create a thread that starts
                                       // running threadFun
 
    boost:: thread ::yield( );           // Give up the main thread's timeslice
                                       // so the child thread can get some work
                                       // done.
 
    // Go do some other work...
 
    myThread.join( );                  // The current (i.e., main) thread will wait
                                       // for myThread to finish before it returns
 
}

线程组

    如果你需要创建几个线程,考虑使用一个线程组对象thread_group来组织它们。一个thread_group对象可以使用多种方法管理线程。首先,可以使用一个指向动态创建的线程对象的指针作为参数来调用add_thread方法,将这个线程加入线程组。也可以直接使用线程组类的create_thread方法,可不先创建线程而直接把线程加入到线程组中。

    当线程组对象的析构函数被调用时,它将删除(delete)所有这些通过add_thread方法加入的线程指针。所以,只能将堆上的线程对象指针通过add_thread方法加入线程组。remove_thread方法从线程组删除某个线程的指针,但是我们仍需负责把线程本身内存释放掉。

    线程组对象的成员方法join_all方法等待线程组中所有线程结束,才返回。

1
2
3
4
5
6
7
8
9
10
boost::thread_group grp;
boost:: thread  *p = new  boost:: thread (threadFun);
grp.add_thread(p);
//do something...
grp.remove_thread(p);
 
grp.create_thread(threadFun);
grp.create_thread(threadFun);   //Now there are two threads in grp
 
grp.join_all();                 //Wait for all threads to finish

 

二、使资源是线程安全的

    保证同一时刻多个线程不会同时修改同一个共享资源,那么这个程序是线程安全的,或者是串行化访问资源的。可以使用mutex类来控制线程的并发问题。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
#include <iostream>
#include <boost/thread/thread.hpp>
#include <string>
 
// A simple queue class; don't do this, use std::queue
template < typename  T>
class  Queue {
public :
    Queue( ) {}
   ~Queue( ) {}
 
    void  enqueue( const  T& x) {
       // Lock the mutex for this queue
       boost::mutex::scoped_lock lock(mutex_);
       list_.push_back(x);
       // A scoped_lock is automatically destroyed (and thus unlocked)
       // when it goes out of scope
    }
 
    T dequeue( ) {
       boost::mutex::scoped_lock lock(mutex_);
 
       if  (list_.empty( ))
          throw  "empty!" ;     // This leaves the current scope, so the
       T tmp = list_.front( ); // lock is released
       list_.pop_front( );
       return (tmp);
    } // Again: when scope ends, mutex_ is unlocked
 
private :
    std::list<T> list_;
    boost::mutex mutex_;
};
 
Queue<std::string> queueOfStrings;
 
void  sendSomething( ) {
    std::string s;
    for  ( int  i = 0; i < 10; ++i) {
       queueOfStrings.enqueue( "Cyrus" );
    }
}
 
void  recvSomething( ) {
    std::string s;
 
    for  ( int  i = 0; i < 10; ++i) {
       try  {s = queueOfStrings.dequeue( );}
       catch (...) {}
    }
}
 
int  main( ) {
    boost:: thread  thr1(sendSomething);
    boost:: thread  thr2(recvSomething);
 
    thr1.join( );
    thr2.join( );
}

    mutex对象本身并不知道它代表什么,它仅仅是被多个消费者线程使用的资源访问的锁定解锁标志。在某个时刻,只有一个线程可以锁定这个mutex对象,这就阻止了同一时刻有多个线程并发访问共享资源。一个mutex就是一个简单的信号机制。

    给mutex加解锁有多种策略,最简单的是使用scoped_lock类,它使用一个mutex参数来构造,并一直锁定这个mutex直到对象被销毁。如果这个正在被构造的mutex已经被别的线程锁定的话,当前线程就会进入wait状态,直到这个锁被解开。

 

三、读写锁

    mutex有一个美中不足,它不区分读和写。线程如果只是进行读操作,mutex强制线程串行化访问资源,效率低。而且这种操作不需要排他性访问。基于这个原因,Boost线程库提供了read_write_mutex。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/read_write_mutex.hpp>
#include <string>
 
template < typename  T>
class  Queue {
public :
    Queue( ) :  // Use a read/write mutex and give writers priority
       rwMutex_(boost::read_write_scheduling_policy::writer_priority){}
   ~Queue( ) {}
 
    void  enqueue( const  T& x) {
       // Use a r/w lock since enqueue updates the state
       boost::read_write_mutex::scoped_write_lock writeLock(rwMutex_);
       list_.push_back(x);
    }
 
    T dequeue( ) {
       // Again, use a write lock
       boost::read_write_mutex::scoped_write_lock writeLock(rwMutex_);
 
       if  (list_.empty( ))
          throw  "empty!" ;
       T tmp = list_.front( );
       list_.pop_front( );
       return (tmp);
    }
 
    T getFront( ) {
       // This is a read-only operation, so you only need a read lock
       boost::read_write_mutex::scoped_read_lock readLock(rwMutex_);
       if  (list_.empty( ))
          throw  "empty!" ;
       return (list_.front( ));
    }
 
private :
    std::list<T> list_;
    boost::read_write_mutex rwMutex_;
};
 
Queue<std::string> queueOfStrings;
 
void  sendSomething( ) {
    std::string s;
 
    for  ( int  i = 0; i < 10; ++i) {
       queueOfStrings.enqueue( "Cyrus" );
    }
}
 
void  checkTheFront( ) {
    std::string s;
 
    for  ( int  i = 0; i < 10; ++i) {
       try  {s = queueOfStrings.getFront( );}
       catch (...) {}
    }
}
 
int  main( ) {
 
    boost:: thread  thr1(sendSomething);
    boost::thread_group grp;
 
    grp.create_thread(checkTheFront);
    grp.create_thread(checkTheFront);
    grp.create_thread(checkTheFront);
    grp.create_thread(checkTheFront);
 
    thr1.join( );
    grp.join_all( );
}

     注意Queue的构造函数中队读写锁rwMutex的初始化。同一时刻,可能有多个读写线程要锁定一个read_write_mutex,而这些锁的调度策略依赖于构造这个mutex时选定的调度策略。Boost库中提供了四种调度策略:

1)reader_priority:等待读锁的线程优先于等待写锁的线程

2)writer_priority:等待写锁的线程优先于等待读锁的线程

3)alternating_single_read:在读锁和写锁之间交替

4)alternating_many_reads:在读锁和写锁之间交替,这个策略将在两个写锁之间使得所有的在这个queue上挂起的读锁都被允许。

     选择使用哪种策略要慎重,因为使用前两种的话可能会导致某些锁始终不能成功,出现饿死的现象。

死锁、饿死和竞态条件

    1)死锁,是涉及至少2个线程和2个资源的情况。线程A和B,资源X和Y。A锁定了X,而B锁定了Y。此时A和B有彼此想要对方的资源,死锁就出现了。

死锁的预防有两种方法。一种是,通过小心的按照一定的顺序对不同的mutex来加锁。另一种是,使用Boost提供的try_mutex互斥量和scoped_try_lock。或者使用时间锁。scoped_try_lock对try_mutex加锁时,可能成功,也可能失败,但不会阻塞。时间锁则有一个超时时间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
bool  dequeue(T& x)
{
     boost::try_mutex::scope_try_lock lock(tryMutex_);
     if (!lock.locked())
         return  false ;
     else {
         if  (list_.empty())
             throw  "empty!" ;
         x = list_.front();
         list_.pop_front();
         return  true ;
     }
}
private :
     boost::try_mutex tryMutex_;

    2)饿死,如果你正在使用write_priority策略,并且你有很多创建写锁的线程,那么读锁的线程就可能饿死。

    3)竞态条件,

1
2
3
4
if (q.getFront() == "Cyrus" ){
    str = q.dequeue();
    //....
}

       这个代码在单线程环境中工作很好,因为q在第一行和第二行代码之间不会被修改。多线程环境中则会出现问题。此为竞态条件。解决的方法是为Queue添加一个成员函数dequeueIfEquals,在函数执行过程中始终锁定互斥量。

 

四、从一个线程中给另一个线程发送通知

    当需要线程等待某个事物时,可以创建一个condition对象,然后通过这个对象来通知那些等待的线程。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/condition.hpp>
#include <boost/thread/mutex.hpp>
#include <list>
#include <string>
 
class  Request { /*...*/  };
 
// A simple job queue class; don't do this, use std::queue
template < typename  T>
class  JobQueue {
public :
    JobQueue( ) {}
   ~JobQueue( ) {}
 
    void  submitJob( const  T& x) {
       boost::mutex::scoped_lock lock(mutex_);
       list_.push_back(x);
       workToBeDone_.notify_one( );
    }
 
    T getJob( ) {
       boost::mutex::scoped_lock lock(mutex_);
 
       workToBeDone_.wait(lock); // Wait until this condition is
                                 // satisfied, then lock the mutex
       T tmp = list_.front( );
       list_.pop_front( );
       return (tmp);
    }
 
private :
    std::list<T> list_;
    boost::mutex mutex_;
    boost::condition workToBeDone_;
};
 
JobQueue<Request> myJobQueue;
 
void  boss( ) {
    for  (;;) {
       // Get the request from somewhere
       Request req;
       myJobQueue.submitJob(req);
    }
}
 
void  worker( ) {
    for  (;;) {
       Request r(myJobQueue.getJob( ));
       // Do something with the job...
    }
}
 
int  main( ) {
    boost:: thread  thr1(boss);
    boost:: thread  thr2(worker);
    boost:: thread  thr3(worker);
 
    thr1.join( );
    thr2.join( );
    thr3.join( );
}

boost::mutex::scoped_lock lock(mutex_);

workToBeDone_.wait(lock);

     这两行代码,第一行锁定这个mutex对象。第二行代码解开这个mutex上的锁,然后进行等待或者休眠,直到它的条件得到了满足。这个mutex互斥对象的解锁让其他的线程能够使用这个mutex对象,它们中的某个需要设置这个等待条件,之后通知另外的线程。

    notify_all函数,通知那些所有正在等待某个条件变为真的线程,那些线程随后进入运行状态。wait方法做两件事情:它一直等待直到有人在它正等待的condition上调用notify_one或notify_all,然后它就试图锁定相关的mutex。当调用的是notify_all时,尽管多个等待的线程都尽量去获得下一个锁,但谁将获得依赖于这个mutex的类型和使用的优先策略。

    一个condition对象能让消费者线程休眠,因此在还没有碰到一个condition时处理器可以去处理别的事情。例如一个web服务器使用一个工作线程池来处理进来的请求。当没有需求进来时,让这些子线程处于等待状态比让它们循环的查询或者睡眠然后偶尔唤醒来检查这个队列,要好很多。

 

五、只初始化一次共享资源

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
#include <iostream>
#include <boost/thread/thread.hpp>
#include <boost/thread/once.hpp>
 
// Some sort of connection class that should only be initialized once
struct  Conn {
    static  void  init( ) {++i_;}
    static  boost::once_flag init_;
    static  int  i_;
    // ...
};
 
int  Conn::i_ = 0;
boost::once_flag Conn::init_ = BOOST_ONCE_INIT;
 
void  worker( ) {
    boost::call_once(Conn::init, Conn::init_);
    // Do the real work...
}
 
Conn c;  // You probably don't want to use a global, so see the
          // next Recipe
 
int  main( ) {
 
    boost::thread_group grp;
 
    for  ( int  i = 0; i < 100; ++i)
       grp.create_thread(worker);
 
    grp.join_all( );
 
    std::cout << c.i_ << '\n' ; // c.i_ = 1
}

    一个共享资源不得不在某个地方被初始化,并且你希望第一次使用这个资源的线程来完成初始化工作。一个once_flag类型和call_once函数能够保证多个线程不会重复的初始化同一个对象。首先,必须使用BOOST_ONCE_INIT宏来初始化这个once_flag对象。boost::once_flag Conn::init_ = BOOST_ONCE_INIT; 之后调用call_once函数,boost::call_once(Conn::init, Conn::init_); 第一个形参是希望被执行一次的初始化函数的地址。

 

六、给线程函数传递一个参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#include <iostream>
#include <string>
#include <functional>
#include <boost/thread/thread.hpp>
 
// A typedef to make the declarations below easier to read
typedef  void  (*WorkerFunPtr)( const  std::string&);
 
template < typename  FunT,   // The type of the function being called
          typename  ParamT> // The type of its parameter
struct  Adapter {
    Adapter(FunT f, ParamT& p) : // Construct this adapter and set the
       f_(f), p_(&p) {}          // members to the function and its arg
 
    void  operator( )( ) { // This just calls the function with its arg
       f_(*p_);        
    }
private :
    FunT    f_;
    ParamT* p_;  // Use the parameter's address to avoid extra copying
};
 
void  worker( const  std::string& s) {
    std::cout << s << '\n' ;
}
 
int  main( ) {
 
    std::string s1 = "This is the first thread!" ;
    std::string s2 = "This is the second thread!" ;
 
    boost:: thread  thr1(Adapter<WorkerFunPtr, std::string>(worker, s1));
    boost:: thread  thr2(Adapter<WorkerFunPtr, std::string>(worker, s2));
 
    thr1.join( );
    thr2.join( );
}

    使用这个函数适配器类模板,你就可以给线程函数传递参数了。如果你需要传递多个参数,仅需要在这个适配器中增加另一个类型和成员变量。


【BOOST C++ 线程】boost::thread库的基本使用方法总结 boost::thread的六种使用方法总结,本文初步介绍线程的函数、构造、执行的详细解释。 阅读详情

相关推荐

【BOOST C++ 13 并行编程】(1) Boost.Thread

以下库支持并行编程模型。 Boost.Thread 允许您创建和管理自己的线程。 Boost.Atomic 允许您通过多个线程的原子操作访问整数类型的变量。 Boost.Lockfree 提供线程安全的容器。 Boost.MPI 起源于超级计算机领域。使用 Boost.MPI,您的程序可以多次启动并在多个进程中执行。您专注于对应该并发执行的实际任务进行编程,而 Boost.MPI 会协调这些过程。使用 Boost.MPI,您无需处理诸如同步访问共享数据之类的细节。但是,Boost.MPI 确实需要适当的运

gongdiwudu的专栏 5217

boost::thread

1. 简介thread 库为 c++增加了线程处理的能力,它提供简明清晰的线程、互斥量等概念,可以很容易地创建多线程应用程序。thread 库也是高度移植的,它支持使用最广泛的 Windows 和 POSIX 线程,用它编写的代码不需要修改就可以在Windows、UNIX等操作系统上编译运行。thread 库也是boost库中少数需要编译才能使用的库,并且thread 库需要date_time 库...

huangjh2017的博客 1661

深入理解Boost线程库:基于1.52版本的应用实例

本文还有配套的精品资源,点击获取 简介:Boost库是C++的一个扩展库,其中线程库是其核心部分,广泛用于多线程编程。本文通过罗剑锋先生的书本配例,基于Boost 1.52.0版本,详细探讨了在Visual Studio 2010环境下如何使用Boost线程库,并提供了实际应用示例。本文首先介绍了Boost线程库的基本用法,如线程的创建、启动、同步和结束,然后详细介绍了Bo...

weixin_42126677的博客 994

【Boost】boost库中thread多线程详解1——thread入门与简介

1. 概述 线程就是,在同一程序同一时间内允许执行不同函数的离散处理队列。 这使得一个长时间去进行某种特殊运算的函数在执行时不阻碍其他的函数变得十分重要。 线程实际上允许同时执行两种函数,而这两个函数不必相互等待。一旦一个应用程序启动,它仅包含一个默认线程。 此线程执行main() 函数。 在main()中被调用的函数则按这个线程的上下文顺序地执行。 这样的程序称为单线程程序。反之,那些创建

liujiayu2的专栏 5736

2024年全国大学生电子设计竞赛A题_AC-AC变换电路并联运行

AC-AC变换电路并联运行(A 题)【本科组】

qq_74395263的博客 7836

详述字符集与汉字编码

字符集与字符编码是文本处理的基础概念。字符集定义字符集合(如ASCII、GB2312、Unicode),字符编码则规定字符如何存储为二进制数据。汉字编码经历了从区域化(GB2312、GBK、BIG5)到全球化(Unicode)的演进,Unicode通过UTF-8、UTF-16等编码方案实现跨语言兼容。UTF-8因兼容ASCII、节省空间且无乱码风险,成为中文互联网的主流编码。正确处理编码问题需统一标准、明确声明格式,并注意生僻字的特殊处理。

零零发不爱ai的博客 805

boost線程庫學習筆記

原文地址:http://www.cnblogs.com/BloodAndBone/archive/2011/02/28/1967117.html boost線程庫學習筆記 C++多线程开发是一个复杂的事情,mfc下提供了CWinThread类,和AfxBeginThread等等函数,但是在使用中会遇到很多麻烦事情,例如线程之间参数传递的问题,我们一般都是把参数new一个结构体,传递...

weixin_30511039的博客 100

DB2__基本概念——联邦

建立联邦 优点:优点是数据仍然保留在原来的存储位置,而不必建立一个集中的式数据仓储。  缺点:数据联邦查询反映会慢,不适合频繁查询,而且容易出现锁争用和资源冲突等问题 建立联邦表步骤 前提条件:知道两个数据库的ip,用户名,密码及被连数据库的版本 eg:  数据库  qqdb  ip: 22.5.225.225   端口:50000    密码:123456        数据库   ...

qq_38569524的博客 1255

Boost多线程和Asio

BOOST ASIO 学习专贴 https://www.cnblogs.com/zhangdongsheng/p/6984634.html   Boost线程库学习笔记 https://www.cnblogs.com/younes/archive/2010/06/06/1752745.html

cloud-2014的专栏 510

SolidWorks 2022 学习(一)软件安装

接下来是安装SolidWorks,右键SolidWorks.2022.SP0.Premium.DVD.iso,选择装载。然后以管理员身份运行SolidWorks_Flexnet_Server目录下的server_install.bat。更改需要安装的产品,以及安装路径,并勾选接受条款,点击现在安装,会弹出如下窗口。然后以管理员身份运行setup.exe,开始安装solidworks。下载链接会在文章末尾给出,下载完成的文件如下图所示。双击注册表文件,然后点击确定。保持不动,点击确定,开始安装。

qq_38383364的博客 3128

当我们谈论Unidbg时我们在谈什么

文章目录一、前言二、使用Unidbg的工作量是什么三、补环境补的是什么3.1 运行环境缺失3.2 上下文缺失四、Unidbg 不是所有情况下最优的解决方案五、Unidbg在大多数情况下是好的方案六、Unidbg和风控无关七、尾声 一、前言 这是一篇漫谈Unidbg的文章,我对Unidbg的使用和理解都还很浅,日后会更新或修改看法,欢迎大佬指点,也期待同侪讨论。 二、使用Unidbg的工作量是什么 我们常规使用Frida + IDA的动静态分析中,工作可能是这样的 找线索→Frida Hook验证→验证成功继

lilac的博客 5788

Boost线程库

 Boost线程库Bill Kempf译:伐木工        标准C++线程即将到来。CUJ预言它将衍生自Boost线程库,现在就由Bill带领我们探索一下Boost线程库。        就在几年前,用多线程执行程序还是一件非比寻常的事。然而今天互联网应用服务程序普遍使用多线程来提高与多客户链接时的效率;为了达到最大的吞吐量,事务服务器在单独的线程上运行服务程序;GUI

famugong的专栏 2869

【Pico手势开发实战】基于SteamVR串流与MRTK3的跨平台交互方案

本文详细介绍了在Pico设备上,结合SteamVR串流与微软MRTK3框架,实现高效跨平台手势交互开发的完整方案。该方案通过在PC端运行Unity项目并串流至头显,利用MRTK3封装的手势识别与交互组件,大幅提升了开发调试效率与性能上限,并确保了未来向其他OpenXR设备的良好兼容性。

weixin_29001683的博客 217

在Windows下 Build Boost线程库

在Windows下 Build Boost线程库作者:伐木工    Boost库中许多都是在.hpp中实现的,只要包含路径就可以直接就拿来使用。但是仍然有一些需要build为目标库才能够使用,包括Python,正则表达式和多线程库。    折腾了几天,终于将Boost的多线程库搞定了,现在就将我得方法写出来,希望能给遇到麻烦的朋友一些参考。   环境   下面是我的一些安装路径

famugong的专栏 1404

STM32串口控制LED灯的亮灭

STM32中的串口控制LED灯的亮灭,分为两种方式,一种是直接发送数字0和1来控制灯的亮灭,另一种是通过发送字符串来控制。 我所使用的开发板主控芯片是STM32F401RET6,主频84MHz, 首先要进行串口的初始化: /* 函数功能:串口的初始化 函数名:Usart_Init 返回值:无 参数:u32 brr 备注: USART1_TXD->PA9 USART1_RXD->PA10 */ void Usart_Init(u32 brr) { float div; u16 div

博客 2万+

【日志】Prometheus/Loki+Alertmanager+Grafana监控告警

参考文章:匹配写法:https://blog.ossq.cn/2674.html。

CN_Eden 1320

【LINUX操作系统】线程库与线程库封装

封装一个Thread库,进一步理解线程库与线程各个接口之间的关系。

2301_79501467的博客 988

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

上一篇: c++中的.hpp文件
下一篇: 详解Linux下SSH远程文件传输命令scp
DVStream
博客等级 码龄15年 50粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值