用好Kotlin协程的7个关键步骤:告别Callback地狱,提升代码可读性

第一章:Kotlin协程的核心概念与优势

Kotlin协程是一种轻量级的并发编程工具,它允许开发者以同步的方式编写异步代码,显著提升了代码的可读性和可维护性。协程构建于线程之上,但并不等同于线程,它可以挂起和恢复执行而无需阻塞线程,从而实现高效的资源利用。

协程的基本构成

协程的核心组件包括协程构建器、挂起函数和调度器。协程通过 launch 或 async 等构建器启动,运行在指定的上下文中,如主线程或后台线程池。
  • 协程构建器:用于启动新的协程,例如 launch 用于“一劳永逸”的任务,async 用于有返回值的异步操作。
  • 挂起函数:使用 suspend 关键字标记,可在不阻塞线程的情况下暂停执行,待条件满足后恢复。
  • 调度器:控制协程运行的线程环境,如 Dispatchers.Main 用于UI线程,Dispatchers.IO 优化I/O密集型任务。

协程的优势对比

与传统线程相比,协程在性能和开发效率上具有明显优势:
特性线程Kotlin协程
资源消耗高(每个线程占用MB级内存)低(每个协程仅KB级)
上下文切换开销大(由操作系统管理)小(用户态控制)
代码可读性易产生回调地狱支持顺序写法处理异步逻辑

简单协程示例

// 导入必要的协程库
import kotlinx.coroutines.*

// 定义一个挂起函数
suspend fun fetchData(): String {
    delay(1000) // 模拟网络请求延迟,非阻塞式挂起
    return "Data loaded"
}

// 启动协程
fun main() = runBlocking {
    val job = launch {
        val result = fetchData()
        println(result)
    }
    job.join() // 等待协程完成
}
上述代码中,delay 函数挂起协程而不阻塞线程,runBlocking 创建顶层协程作用域,确保程序在协程完成前不退出。这种结构使异步逻辑清晰且易于调试。

第二章:协程基础与启动方式详解

2.1 理解协程的基本结构与运行机制

协程是一种用户态的轻量级线程,由程序自身调度,无需操作系统介入。其核心在于暂停与恢复执行的能力,使得异步操作可以以同步方式书写。
协程的创建与启动
在 Go 语言中,使用 go 关键字即可启动一个协程:
go func() {
    fmt.Println("协程开始执行")
}()
上述代码创建了一个匿名函数并作为协程立即执行。主函数不会等待其完成,因此若主程序结束,协程可能未执行完毕即被终止。
协程的运行机制
  • 协程共享地址空间,通信推荐通过 channel 进行,避免竞态条件;
  • GMP 模型(Goroutine、Machine、Processor)实现高效的多路复用调度;
  • 协程初始栈大小仅 2KB,按需动态扩展,极大降低内存开销。
特性线程协程
调度者操作系统用户程序
栈大小固定(通常 MB 级)动态(初始 KB 级)

2.2 使用launch和async启动协程任务

在Kotlin协程中,`launch`与`async`是两种核心的协程构建器,用于启动并发任务。它们均定义于`kotlinx.coroutines`库中,但用途和返回值存在本质差异。
launch:执行“一发即忘”的任务
`launch`用于启动一个不返回结果的协程,适合执行日志记录、UI更新等操作。
val job = launch {
    delay(1000)
    println("Task completed")
}
上述代码创建一个延迟1秒后打印信息的协程。`launch`返回`Job`对象,可用于取消或等待任务完成。
async:获取异步计算结果
`async`用于执行有返回值的并发任务,其返回`Deferred`,可通过`await()`获取结果。
val deferred = async {
    delay(1000)
    "Result"
}
println(deferred.await()) // 输出 Result
此模式适用于并行执行多个耗时操作并合并结果的场景。
构建器返回类型适用场景
launchJob无需返回值的任务
asyncDeferred<T>需要返回结果的并发计算

2.3 协程作用域与生命周期管理实践

在Kotlin协程中,作用域决定了协程的生命周期。使用`CoroutineScope`可有效管理协程的启动与取消,防止资源泄漏。
结构化并发与作用域绑定
通过`lifecycleScope`或`viewModelScope`等预定义作用域,协程能与组件生命周期同步。当宿主(如Activity)销毁时,关联协程自动取消。
lifecycleScope.launch {
    try {
        val data = fetchDataAsync()
        updateUI(data)
    } catch (e: CancellationException) {
        // 协程被取消,无需处理
    }
}
上述代码在Activity销毁时自动取消任务,避免空指针异常。`lifecycleScope`来自AndroidX Lifecycle库,确保协程生命周期安全。
自定义作用域示例
  • 使用SupervisorJob()创建独立子协程
  • 通过coroutineContext + scope组合上下文
  • 调用cancel()终止整个作用域

2.4 协程调度器选择与线程控制策略

在高并发系统中,协程调度器的选择直接影响程序的吞吐量与响应延迟。主流调度模型包括协作式、抢占式及混合式调度,其中 Go 语言采用基于工作窃取(Work-Stealing)的混合调度器,有效平衡了多核利用率与上下文切换开销。
调度器核心参数配置
通过环境变量或运行时接口可调整调度行为:
  • GOMAXPROCS:控制逻辑处理器数量,对应最大并行执行的线程数
  • GOGC:设置垃圾回收触发阈值,间接影响协程调度频率
线程绑定与亲和性控制
某些场景需将协程绑定至特定线程以提升缓存命中率。以下为伪代码示例:
// runtime.LockOSThread() 将当前 goroutine 绑定到 OS 线程
func worker() {
    runtime.LockOSThread()
    defer runtime.UnlockOSThread()
    // 长期运行的任务,如网络轮询
    for {
        pollNetwork()
    }
}
该机制常用于实现异步 I/O 调度器,确保事件循环始终在固定线程执行,避免跨核同步开销。

2.5 实战:将异步回调转换为协程写法

在现代异步编程中,回调函数容易导致“回调地狱”。使用协程可显著提升代码可读性与维护性。
回调函数的典型问题
传统回调嵌套多层,逻辑分散。例如:

getData((err, data) => {
  if (err) return console.error(err);
  getMoreData(data, (err, moreData) => {
    console.log(moreData);
  });
});
该结构难以调试和异常处理。
转换为协程写法
利用 async/await 将异步操作线性化:

async function fetchData() {
  try {
    const data = await getData();
    const moreData = await getMoreData(data);
    console.log(moreData);
  } catch (err) {
    console.error(err);
  }
}
await 暂停函数执行而不阻塞主线程,错误可通过 try/catch 统一捕获。
优势对比
特性回调函数协程
可读性低高
错误处理分散集中

第三章:协程中的异常处理与取消机制

3.1 协程异常传播与监督机制原理

在协程并发模型中,异常的传播路径不同于传统线程。当子协程抛出未捕获异常时,默认会向上蔓延至父协程,进而导致整个协程树被取消。
异常传播行为
协程的异常具有“传染性”,父协程通常对子协程的失败敏感。若未配置监督策略,一个子协程崩溃将触发结构化并发原则下的级联取消。
监督作用域
使用 SupervisorScope 可隔离异常影响,允许部分子协程失败而不中断其他兄弟协程:

supervisorScope {
    launch { throw RuntimeException("Failed") } // 不影响下面的launch
    launch { println("Still running") }
}
上述代码中,第一个协程抛出异常仅自身终止,supervisorScope 阻止了异常向上传播,保障了并发任务的局部容错性。
监督器与异常处理器
可通过 SupervisorJob 结合 CoroutineExceptionHandler 实现细粒度控制,实现异常捕获与恢复策略。

3.2 使用CoroutineExceptionHandler捕获错误

在Kotlin协程中,未捕获的异常可能导致整个应用崩溃。`CoroutineExceptionHandler`提供了一种全局捕获未处理异常的机制,适用于调试和生产环境中的错误监控。
注册异常处理器
val exceptionHandler = CoroutineExceptionHandler { _, throwable ->
    println("Caught exception: $throwable")
}

val scope = CoroutineScope(Dispatchers.Default + exceptionHandler)
scope.launch {
    throw IllegalArgumentException("Something went wrong")
}
上述代码中,`CoroutineExceptionHandler`作为上下文元素注入`CoroutineScope`。当协程体抛出异常时,处理器会捕获并打印异常信息。注意:该处理器仅对**未被捕获**的异常生效。
作用域与限制
  • 仅对协程顶层异常有效,无法捕获子协程内部已处理的异常
  • 必须在协程启动前注册,动态添加无效
  • 适用于日志记录、崩溃上报等场景

3.3 协程取消与资源清理的正确姿势

在协程执行过程中,合理的取消机制与资源清理是保障系统稳定的关键。当协程被取消时,必须确保已分配的资源(如文件句柄、网络连接)能及时释放。
使用 withContext 与 ensureActive
Kotlin 协程通过 `ensureActive` 检查协程状态,可在循环中主动检测取消信号:
launch {
    while (isActive) {
        doWork()
        yield()
    }
}
上述代码中,isActive 是协程作用域的扩展属性,确保每次循环都检查取消状态。
结构化并发下的自动清理
使用 use 或 try-finally 结合协程作用域,可确保资源释放:
withContext(Dispatchers.IO) {
    val file = openFile()
    try {
        writeFile(file)
    } finally {
        file.close()
    }
}
该模式利用 Kotlin 的作用域机制,在协程取消或异常时触发 finally 块,完成资源释放。

第四章:结构化并发与实际应用场景

4.1 使用withContext切换执行上下文

在Kotlin协程中,withContext是切换协程执行上下文的核心函数,允许在不启动新协程的前提下改变代码块的调度器。
灵活的线程调度
通过withContext,可将协程从主线程安全地切换到IO线程执行耗时任务:
val result = withContext(Dispatchers.IO) {
    // 执行网络或磁盘操作
    fetchDataFromNetwork()
}
上述代码中,Dispatchers.IO指定运行于IO优化的线程池,避免阻塞主线程。函数执行完成后自动切回原上下文。
上下文切换优势
  • 避免回调地狱,保持代码顺序性
  • 资源高效:复用现有协程实例
  • 支持组合多个不同调度需求的操作
相比launch或async,withContext更适合单一任务的上下文切换,是实现协程结构化并发的重要工具。

4.2 并发执行多个任务:async与awaitAll

在现代异步编程中,高效处理多个并发任务是提升系统性能的关键。Kotlin 协程通过 `async` 与 `awaitAll` 提供了简洁而强大的并发执行机制。
启动并发任务:async
`async` 用于启动一个可等待的协程任务,返回 `Deferred` 类型结果,常用于并行计算。

val task1 = async { fetchDataFromApi1() }
val task2 = async { fetchDataFromApi2() }
val results = awaitAll(task1, task2)
上述代码同时发起两个网络请求。`async` 不阻塞主线程,任务在调度器上并发执行。`awaitAll` 接收多个 `Deferred` 实例,等待全部完成并返回结果列表,顺序与传入一致。
适用场景与优势
  • 适用于独立、耗时的任务(如网络请求、文件读写)
  • 避免串行等待,显著降低总体响应时间
  • 基于协程轻量,无需管理线程池

4.3 流式数据处理:Channels与Flow入门

在Kotlin中,流式数据处理依赖于Channels和Flow两大核心机制。Channels提供了一种线程安全的数据传输方式,适用于生产者-消费者模式。
Channel基础示例
val channel = Channel<Int>(3)
launch {
    for (i in 1..5) {
        channel.send(i * i)
    }
    channel.close()
}
// 接收数据
for (value in channel) {
    println(value)
}
上述代码创建了一个容量为3的缓冲Channel,发送方协程依次发送平方值,接收方通过迭代获取数据。send是挂起函数,确保背压处理。
Flow对比Channel
  • Flow是冷流,仅在收集时执行
  • Channel是热数据源,可被多个协程监听
  • Flow支持丰富的操作符如map、filter
使用Flow可实现更声明式的异步数据流处理逻辑。

4.4 实战:网络请求与数据库操作的协程封装

在现代应用开发中,频繁的网络请求与数据库交互容易造成主线程阻塞。使用协程可将耗时操作异步化,提升响应速度。
协程封装示例
suspend fun fetchDataAndSave(context: Context) {
    val apiService = RetrofitClient.api
    val userDao = AppDatabase.get(context).userDao()
    
    try {
        val response = apiService.getUsers() // 挂起网络请求
        withContext(Dispatchers.IO) {
            userDao.insertAll(response) // 切换至IO线程执行数据库操作
        }
    } catch (e: Exception) {
        Log.e("Coroutine", "数据获取或存储失败", e)
    }
}
上述代码通过 suspend 函数实现挂起,利用 withContext(Dispatchers.IO) 将数据库操作切换到IO线程,避免在主线程执行耗时任务。
调度器选择策略
  • Dispatchers.Main:适用于UI更新
  • Dispatchers.IO:适合数据库、文件等阻塞操作
  • Dispatchers.Default:适用于CPU密集型计算

第五章:从Callback地狱到清晰可维护的异步代码

在早期JavaScript开发中,异步操作普遍依赖回调函数,导致深层嵌套,形成“Callback地狱”。这种结构不仅难以阅读,更增加了错误处理和调试的复杂度。
问题示例:嵌套回调

getData(function(a) {
  getMoreData(a, function(b) {
    getEvenMoreData(b, function(c) {
      console.log(c);
    }, onError);
  }, onError);
}, onError);
上述代码缺乏可读性,且错误处理重复,维护成本高。为解决此问题,Promise被引入。
使用Promise链式调用
  • 将异步操作封装为Promise对象
  • 通过.then()实现链式调用
  • 统一使用.catch()处理异常

getData()
  .then(a => getMoreData(a))
  .then(b => getEvenMoreData(b))
  .then(c => console.log(c))
  .catch(onError);
虽然Promise改善了结构,但更进一步的优化来自async/await语法。
现代方案:async/await
特性Promiseasync/await
可读性中等高
错误处理.catch()try/catch
调试友好性差好
使用async/await,异步代码几乎与同步代码一样直观:

async function fetchData() {
  try {
    const a = await getData();
    const b = await getMoreData(a);
    const c = await getEvenMoreData(b);
    console.log(c);
  } catch (error) {
    onError(error);
  }
}
异步流程: [getData] → [getMoreData] → [getEvenMoreData] → [输出结果] ↑ 前者成功后触发后者
Kotlin协程封装Android BLE蓝牙开发:从扫描到通信的完整实践 蓝牙低功耗(BLE)技术是物联网和智能设备通信的基础协议,它通过低功耗设计实现了设备间的间歇性数据传输。其工作原理基于GATT协议,定义了服务、特征值等数据交互模型。在Android开发中,原生蓝牙API较为繁琐,涉及大量异步回调与状态管理。利用Kotlin协程进行封装,可以将回调式API转换为线性的挂起函数,结合Flow实现响应式数据流,极大提升代码可读性和可维护性。这种封装模式特别适用于智能家居、穿戴设备等需要稳定、高效蓝牙连接的场景。本文通过一个具体的Android蓝牙库示例,详细展示了如何将设备扫描 阅读详情

相关推荐

Android BLE开发实战:基于Kotlin协程与MVVM的现代蓝牙库设计

在移动应用开发中,蓝牙低功耗(BLE)技术是实现设备间无线通信的关键方案,尤其适用于物联网、健康监测等低功耗场景。其工作原理基于GATT协议,通过中心设备与外设之间的服务与特征值进行数据交换。掌握原生Android蓝牙API的现代化封装,对于构建稳定、高效的硬件交互应用具有重要工程价值。本文聚焦于Android平台,针对BLE开发中常见的权限管理、异步回调、状态同步等痛点,结合Kotlin协程与StateFlow,将传统的回调式API转化为线性的挂起函数,实现了清晰的数据流与UI状态管理。通过MVVM架构与

weixin_26742753的博客 279

掌握 Kotlin 协程的异步编程:async {}, await 和 awaitAll 指南

Kotlin 是一种功能强大的语言,适用于 Android 和后端开发,在 Kotlin 协程中提供了出色的异步编程支持。在本文中,我们将深入探讨 Kotlin 协程中的三个重要函数:async {}、await 和 awaitAll,它们使异步编程变得轻而易举。在 Kotlin 协程中,async {} 是一个协程构建器,它启动一个表示异步计算的新协程。通过掌握 async {}、await 和 awaitAll,您将更好地掌握开发响应式、高效和高度可扩展的应用程序,充分发挥 Kotlin 的潜力。

chuyouyinghe的专栏 5948

Kotlin协程封装Android蓝牙开发:从扫描连接到数据通信的完整实践

在Android应用开发中,蓝牙通信是实现与智能硬件交互的关键技术。其核心原理基于蓝牙低功耗(BLE)协议栈,通过GATT(通用属性配置文件)进行设备发现、连接与数据交换。这项技术的工程价值在于为移动应用与物联网设备提供了稳定、低功耗的无线通信能力,广泛应用于智能家居、健康监测、工业控制等场景。针对传统蓝牙开发中普遍存在的回调嵌套复杂、状态管理困难等痛点,现代Android开发引入了Kotlin协程这一强大的异步处理工具。通过将扫描、连接、读写等异步操作封装为**挂起函数**,并利用**StateFlow*

weixin_29193259的博客 376

攻克Android面试:ViewModelScope与LifecycleScope完全指南

你是否在Android开发中遇到过异步任务泄漏问题?是否困惑于该用ViewModelScope还是LifecycleScope?本文将系统解析这两种协程作用域(Scope)的工作原理、使用场景及最佳实践,助你在面试中脱颖而出并写出更健壮的代码。 ## 为什么协程作用域对Android开发至关重要 在Android开发中,错误的异步任务管理会导致内存泄漏、界面闪烁甚至应用崩溃。Kotlin协程的...

gitblog_00412的博客 743

1.28寸圆屏LCD驱动开发:GC9A01与RT-Thread嵌入式实现

圆形TFT-LCD是一种面向可穿戴、IoT终端的紧凑型人机交互显示技术,其核心在于SPI/QSPI接口时序控制与GRAM内存映射原理。通过驱动芯片(如GC9A01)完成电源管理、伽马校正和MADCTL方向配置,可实现低功耗、高刷新率的图形渲染。该技术显著提升嵌入式设备的UI表现力与空间利用率,在智能手环、传感器节点、微型HMI等资源受限场景中具备突出工程价值。本文围绕1.28寸圆屏LCD模块,详解硬件接口规范、RT-Thread下QSPI驱动架构及Bresenham算法优化实践。

weixin_42599908的博客 156

GradNorm:Gradient Normalization for Adaptive Loss Balancing in Deep Multitask Networks,梯度归一化

文章目录引言gradnorm   gradnorm论文地址:https://arxiv.org/abs/1711.02257   gradnorm是一种优化方法,在多任务学习(Multi-Task Learning)中,解决 1. 不同任务loss梯度的量级(magnitude)不同,造成有的task在梯度反向传播中占主导地位,模型过分学习该任务而忽视其它任务;2. 不同任务收敛速度不一致;这两个...

Leon_winter的博客 2万+

Kotlin协程Api用例详解

Kotlin协程有些 APIs 是需要长时间运行,并且需要调用者阻塞直到这些调用完成(比如网络 IO ,文件 IO ,CPU 或者 GPU 比较集中的工作)。协程提供了一种避免线程阻塞并且用一种更轻量级,更易操控到操作:协程暂停。添加Kotlin协程依赖 implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:0.22.5"...

moodstrikerdd的博客 1172

计量经济学tempdisagg的python库:年度时序变月度

计量经济学tempdisagg的python库:年度时序变月度

素质云笔记 1526

kotlin协程async await的异常踩坑以及异常处理的正确姿势

使用Kotlin来做一些异步操作相信大家都非常熟悉了,特别是结合Jetpack的一些组件,使得我们在Android开发中写异步任务非常的方便。 但是,关于在使用协程的时候,个人觉得异常处理这一块是相对来讲是需要花时间去了解的地方,因为在使用过程中还是会遇到一些小坑的,这里记录下之前遇到的坑。 踩一个使用async await时异常处理的坑 kotlin 协程的异常处理官方文档 我们先来看官方的示例: 可以看到,示例代码中在对 async 开启的协程进行异常捕获是在调用 await 时。看打印结果也确实是捕

喻志强的博客 6945

YOLO系列算法改进 | 主干改进篇 | 替换LSKNet主干特征提取网络 | 通过动态调整感受野自适应融合长程上下文,显著提升小目标与复杂背景下的检测精度!

YOLO系列算法改进 | 主干改进篇 | 替换LSKNet主干特征提取网络 | 通过动态调整感受野自适应融合长程上下文,显著提升小目标与复杂背景下的检测精度! (以YOLO26最新目标检测模型为基础,利用LSKNet替代Backbone)

2502_91881744的博客 211

lammps模拟石墨烯吸附水分子(gcmc)

本文分享lammps gcmc吸附的一个案例代码,上下壁面的通道材料为石墨烯,吸附的分子为tip4p水分子。大家好,我是小马老师。

lammps_jiayou的博客 2590

如何让Java回调优雅接入Kotlin协程?3步实现异步代码统一治理

掌握Java与Kotlin协程的混合编程模式(Coroutines 1.8),3步实现Java回调与Kotlin协程无缝集成。适用于Android异步开发场景,通过挂起函数封装、CoroutineDispatcher调度与Result处理,统一异步代码结构,提升可读性与维护性,值得收藏。

CompiWander的博客 885

SAP OData 开发从入门到提高教程的目录

笔者 18 年的 SAP 技术开发生涯,对 SAP OData 服务的开发,测试,发布,部署,测试,及基于各种不同 SAP 技术实现的 OData 服务的幕后技术实现细节和使用场合,均有着深入的研究。

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 7236

Kotlin从入门到实战:现代JVM开发核心语法与协程应用

在JVM生态中,编程语言的选择直接影响开发效率和代码质量。Kotlin作为一门静态类型语言,通过类型系统层面的空安全设计,从根本上解决了空指针异常这一常见痛点,提升了代码的健壮性。其简洁的语法和函数式编程特性,如Lambda表达式和高阶函数,显著减少了模板代码,让开发者能更专注于业务逻辑。在工程实践中,Kotlin的协程机制为异步编程提供了轻量级解决方案,有效避免了回调地狱,简化了并发处理。这些特性使得Kotlin在Android开发、后端服务及跨平台场景中展现出强大的技术价值,成为构建现代高可靠性应用的高

weixin_34384557的博客 338

uniapp | vue2 | vue3 - 解决调用天地图功能服务时 http 网络请求报错 net::ERR ABORTED 503(Service Temporarily Unavailabl)

vue,uni-app,天地图,请求报错,503,请求失败,map.tianditu,天地图503,天地图请求503,接口503错误怎么办,vue天地图,uniAPP天地图,获取定位接口服务器报错503,获取当前定位,定位功能,IP属地定位,天地图服务器报错,如何解决报错,net::ERRABORTED503(ServiceTemporarilyUnavailabl),GET,POST,服务暂时不可用,react天地图,一直等待吗,报错怎么办,定位报错,轨迹,经纬度,天地图服务器503,在vue2

🏆 前端领域优质创作者 4438

【毕业设计】基于雷达与深度学习的摔倒检测——雷达数据集的建立

运动物体的微多普勒效应为人体动作识别提供了可能,基于雷达的居家检测具有良好的隐私保护性,且不易受环境因素影响(如光照、温度等),近年来已受到国内外学者的广泛关注。基于雷达与深度学习的摔倒检测使用自建的雷达数据集进行人体摔倒检测的研究。雷达数据集的建立分为雷达数据采集和雷达数据处理两部分工作。

洋洋Young的博客 3403

Java 异步编程:从 Future 到 Loom

众所周知,Java 开始方法执行到结束,都是由同一个线程完成的。这种方式虽易于开发调试,但容易因为锁、IO 等原因导致线程挂起,产生线程上下文切换。随着对应用并发能力要求越来越高,频繁的线程上下文切换所带来的成本变得难以忽视。同时,线程也是相对宝贵的资源,无限制的增加线程是不可能的。优秀的技术人员应该能让应用使用更少的线程资源实现更高的并发能力。这便是我们今天要讨论的话题 —— Java 异步编程技术。 异步编程其实并没有清晰定义。通常我们认为,从方法开始到结束都必须在同一个线程内调度执行的编程方式可被认

hellozhxy的博客 1725

深度学习工具包 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")

【Android Kotlin】协程知识体系

文章摘要 Kotlin协程是用户态轻量级线程,相比传统线程具有更低开销、更高并发和更优的代码可读性。协程核心包括四大组件:CoroutineContext(配置容器)、Dispatcher(线程调度器)、Job(生命周期管控)和CoroutineScope(运行容器)。协程通过launch和async两种方式启动,分别适用于无返回值和有返回值的异步任务。异常处理需区分launch的主动传播和async的延迟抛出特性,采用try-catch、全局处理器或SupervisorJob进行管控。协程的高效性源于挂起

studyForMokey的博客 449

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

Kotlin核心语法与Java对比:现代编程语言的优势

Kotlin是一种现代编程语言,专为JVM设计,旨在解决Java的痛点并提升开发效率。其核心特性包括类型推断、空安全、函数式编程和协程等,显著减少了代码冗余和运行时错误。Kotlin通过智能的类型系统和简洁的语法设计,如`val`和`var`关键字,提升了代码的可读性和可维护性。在Android开发、后端服务和异步编程等场景中,Kotlin展现出强大的技术价值。例如,其协程机制简化了异步任务管理,而数据类和密封类则优化了状态处理和模式匹配。对于Java开发者,Kotlin提供了平滑的迁移路径和互操作性,是现

weixin_30628077的博客 508

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

Kotlin 语言 知识点整理1【个人用】

Kotlin作为JetBrains开发的现代化语言,以其简洁、安全和高效特性成为Java的理想替代。它与Java完全互操作,共享JVM平台和生态系统,但通过空安全机制、扩展函数、数据类等特性大幅减少样板代码。核心优势包括:1)强制空安全设计杜绝NPE;2)支持函数式编程和Lambda表达式;3)协程简化异步编程;4)扩展函数增强代码组织。Java开发者应重点掌握空安全处理、集合操作、作用域函数及协程应用,通过IDE转换工具和Kotlin标准库快速上手。渐进式迁移策略和"以Kotlin方式思考&qu

indeedes的博客 260

java异步编程,两篇转载放一起

众所周知,Java 开始方法执行到结束,都是由同一个线程完成的。这种方式虽易于开发调试,但容易因为锁、IO 等原因导致线程挂起,产生线程上下文切换。随着对应用并发能力要求越来越高,频繁的线程上下文切换所带来的成本变得难以忽视。同时,线程也是相对宝贵的资源,无限制的增加线程是不可能的。优秀的技术人员应该能让应用使用更少的线程资源实现更高的并发能力。这便是我们今天要讨论的话题 —— Java 异步编程...

qq_29950673的博客 420

Kotlin 语言 知识点整理3【个人用】

一、类与对象 1.定义与使用 1.1 基础用法 1.2 主构造函数,直接在类名后声明 1.3 次构造函数(Secondary Constructor)用constructor 关键字定义: 2.继承 3.抽象 4.接口 5.数据类 6.伴生对象 6.1 声明方式 6.2 访问成员 6.3 默认名称 7.可见性修饰符 8.与 Java 的主要区别​ 二、列表与集合 1.创建集合 2.高频操作 2.1 遍历集合 2.2 数据类型转换 2.3 过滤数据(列表筛选) 2.4

indeedes的博客 228

架构演进深度解析:EhViewer如何用现代化技术栈重塑Android漫画阅读体验

EhViewer是一款专注于Android平台的漫画阅读器应用,它通过Material Design 2设计语言和现代化的Kotlin技术栈,为漫画爱好者提供了流畅、高效的阅读体验。本项目面向需要高性能漫画浏览、离线阅读和智能管理的Android用户,解决了传统漫画阅读器在性能、界面体验和功能扩展方面的诸多痛点。 ## 传统漫画阅读器的技术瓶颈与EhViewer的解决方案 ### 图片加载性能

gitblog_00420的博客 692

MVVMLin网络请求封装:Retrofit+FlowAdapterFactory实现优雅API调用

MVVMLin是一个基于MVVM架构,采用Kotlin+Retrofit+协程+Viewbinding+Flow封装的快速开发框架。本文将详细介绍如何通过**FlowAdapterFactory**实现网络请求的优雅封装,帮助开发者简化API调用流程,提升代码质量与开发效率。 ## 为什么选择Retrofit+Flow组合? 在Android开发中,网络请求是核心模块之一。传统的Callbac

gitblog_00963的博客 329

Android Handler机制详解:从线程间通信到消息循环架构

在Android开发中,线程间通信是构建响应式应用的核心基础。由于UI组件本身不具备线程安全性,Android框架强制要求所有UI操作必须在主线程执行,这催生了高效的消息传递机制需求。Handler机制正是为解决这一核心问题而设计,它通过Message、MessageQueue和Looper三者的协同工作,构建了一套生产者-消费者模型,实现了线程间的安全通信。这套机制不仅有效避免了ANR(应用无响应)问题,还支撑着Android应用的整个事件驱动架构。在实际开发中,Handler常用于子线程执行耗时任务后更

weixin_34296641的博客 306
上一篇: 【PHP邮件发送避坑手册】:避免被当成垃圾邮件的8个核心技巧
下一篇: 【Android Studio性能调优秘籍】:提升编译速度80%的4个实战方法
FastSolve
博客等级 码龄1年 155粉丝 2011原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值