Retrofit2源码阅读

Retrofit2+Okhttp3+Rxjava2通过SOAP协议请求WebService Retrofit2+Okhttp3+Rxjava2通过SOAP协议请求WebService刚入职新公司不久,花了九牛二虎把公司源码阅读了一遍,用两个字形容就是:”卧槽”,这写的啥玩意啊,和领导商议之后打算用空余时间重构一下源码,其中主要是网络请求最为频繁之一(感觉是在说废话),发现后台是WebService,以前都是JAVA的,这没弄过啊,经过查阅之后可以用Ksoap2来进行请求,发现Ksoap2挺 阅读详情

本次分析的要点:
1. Retrofit中的动态代理和整个流程(Proxy、ServiceMethod、OkHttpCall)
2. Retrofit中的转换器和适配器(Converter、CallAdapter)

Retrofit整体流程和动态代理

首先我们回顾一下retrofit的使用demo

   Retrofit retrofit = new Retrofit.Builder()
                //设置OKHttpClient
                .client(okHttp.INSTANCE.getOkHttpClient())
                //Rx适配器
                .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                //gson转化器
                .addConverterFactory(GsonConverterFactory.create())
                // 设置API基础的Url
                .baseUrl("https://www.baidu.com")
                // 创建Retrofit
                .build();
    BaiduAPI api = retrofit.create(BaiduAPI.class);

    Call<String> call = api.getInfo();

    call.enqueue(new Callback<User>() {
            @Override
            public void onResponse(Call<User> call, Response<User> response) {

            }

            @Override
            public void onFailure(Call<User> call, Throwable t) {

            }
        });

    public interface BaiduAPI{
        @GET("https://www.baidu.com)
        Call<String> getInfo();
    }

retrofit的使用还是比较简单的,通过定义规定好的接口,通过Builder来创建Retrofit对象,通过create方法来创建接口的代理对象,然后调用定义好的方法就可以请求网络来获取数据了。

首先看一下Builder类吧

public static final class Builder {
    // 平台验证 JAVA和Android,这里是Android
    private final Platform platform;
    // 真正发起OkHttp3请求的Call类
    private @Nullable okhttp3.Call.Factory callFactory;
    // 将字符url包装为HttpUrl
    private HttpUrl baseUrl;
    // 转换工厂集合,Retrofit可以插入多个转换器,例如Gson,jackson等
    private final List<Converter.Factory> converterFactories = new ArrayList<>();
    // 用于发起请求和接受相应的Call适配器集合
    private final List<CallAdapter.Factory> adapterFactories = new ArrayList<>();
    // 并发框架
    private @Nullable Executor callbackExecutor;
    // 是否立即加载所有的接口方法,转换为ServiceMethod对象,放在serviceMethodCache中
    private boolean validateEagerly;

    // 省略代码
    ...

重点是create方法

 public <T> T create(final Class<T> service) {
    // 检查接口的合法性,必须是接口,并且不能继承其他接口
    Utils.validateServiceInterface(service);
    // 是否立即给接口中的所有方法生成包装类,默认是false
    if (validateEagerly) {
      eagerlyValidateMethods(service);
    }
    return (T) Proxy.newProxyInstance(service.getClassLoader(), new Class<?>[] { service },
        new InvocationHandler() {
          private final Platform platform = Platform.get();

          @Override public Object invoke(Object proxy, Method method, @Nullable Object[] args)
              throws Throwable {
            // 如果方法对象的类时Object的对象,就走普通的代理方法
            if (method.getDeclaringClass() == Object.class) {
              return method.invoke(this, args);
            }
            // 在Android平台上是是返回false的
            if (platform.isDefaultMethod(method)) {
              return platform.invokeDefaultMethod(method, service, proxy, args);
            }
            // 生成ServiceMethod对象,这个对象是为了将请求的方法是配成HTTP Call
            ServiceMethod<Object, Object> serviceMethod =
                (ServiceMethod<Object, Object>) loadServiceMethod(method);
            // 创建OkHttpCall对象
            OkHttpCall<Object> okHttpCall = new OkHttpCall<>(serviceMethod, args);
            // 将OkHttpCall对象适配成我们需要的Call类型
            return serviceMethod.callAdapter.adapt(okHttpCall);
          }
        });
  }

可以看到这里用到了Java自带的Proxy类,提供了动态代理支持,newProxyInstance方法会生成当前接口的代理类,并且放回改代理类的实例。正式动态代理设计模式,让我们在触发真正的网络请求时添加其他的逻辑。Retrofit正是利用这一点,利用注解,生成request和response,将重复的工作封装到这个类中,我们只需要专注于API接口的编写即可,这也是AOP(面向切面编程)思想的一种体现。

每当我们调用代理对象的方法时,都会触发InvocationHandler的invoke方法,它会把我们这次调用的方法method和参数args都回调过来,拿到method后首先经过loadServiceMethod方法,将method作为key转换为ServiceMethod对象,看一下这个类都做了什么?

/** Adapts an invocation of an interface method into an HTTP call. */
final class ServiceMethod<R, T> {
  // Upper and lower characters, digits, underscores, and hyphens, starting with a character.
  static final String PARAM = "[a-zA-Z][a-zA-Z0-9_-]*";
  static final Pattern PARAM_URL_REGEX = Pattern.compile("\\{(" + PARAM + ")\\}");
  static final Pattern PARAM_NAME_REGEX = Pattern.compile(PARAM);

  final okhttp3.Call.Factory callFactory;
  final CallAdapter<R, T> callAdapter;

  private final HttpUrl baseUrl;
  private final Converter<ResponseBody, R> responseConverter;
  private final String httpMethod;
  private final String relativeUrl;
  private final Headers headers;
  private final MediaType contentType;
  private final boolean hasBody;
  private final boolean isFormEncoded;
  private final boolean isMultipart;
  private final ParameterHandler<?>[] parameterHandlers;

  ServiceMethod(Builder<R, T> builder) {
    this.callFactory = builder.retrofit.callFactory();
    this.callAdapter = builder.callAdapter;
    this.baseUrl = builder.retrofit.baseUrl();
    this.responseConverter = builder.responseConverter;
    this.httpMethod = builder.httpMethod;
    this.relativeUrl = builder.relativeUrl;
    this.headers = builder.headers;
    this.contentType = builder.contentType;
    this.hasBody = builder.hasBody;
    this.isFormEncoded = builder.isFormEncoded;
    this.isMultipart = builder.isMultipart;
    this.parameterHandlers = builder.parameterHandlers;
  }

  /** 将请求的方法转换为一个请求需要Request对象 */
  Request toRequest(@Nullable Object... args) throws IOException {
    RequestBuilder requestBuilder = new RequestBuilder(httpMethod, baseUrl, relativeUrl, headers,
        contentType, hasBody, isFormEncoded, isMultipart);

    @SuppressWarnings("unchecked") // It is an error to invoke a method with the wrong arg types.
    ParameterHandler<Object>[] handlers = (ParameterHandler<Object>[]) parameterHandlers;

    int argumentCount = args != null ? args.length : 0;
    if (argumentCount != handlers.length) {
      throw new IllegalArgumentException("Argument count (" + argumentCount
          + ") doesn't match expected count (" + handlers.length + ")");
    }

    for (int p = 0; p < argumentCount; p++) {
      handlers[p].apply(requestBuilder, args[p]);
    }

    return requestBuilder.build();
  }

  /** 经过Convert处理,将原始的response body转换成我们需要的类型 */
  R toResponse(ResponseBody body) throws IOException {
    return responseConverter.convert(body);
  }
  ...
  省略代码

这个勒种最重要的两个方法是toRequest和toResponse。我们请求时使用的request和最后得到的response就是由这两个方法返回的,还有其他大量的方法parseXXX,都是讲注解解析成具体的参数。

在得到ServiceMethod后,将它和请求参数一起作为参数创建了OkHttpCall对象,这个对象就是网络请求所需要的对象。OkHttpCall是一个装饰类,真正的网络请求时rawCall,而这个rawCall对象就是通过传入的serviceMethod的toRequest方法生成的。

看一下OkHttpCall类中几个主要方法:

// OkHttpCall.java

//生成真正用于执行请求任务的call
 private okhttp3.Call createRawCall() throws IOException {
    Request request = serviceMethod.toRequest(args);
    okhttp3.Call call = serviceMethod.callFactory.newCall(request);
    if (call == null) {
      throw new NullPointerException("Call.Factory returned null.");
    }
    return call;
  }

  // 异步请求方法
  public void enqueue(final Callback<T> callback) {
    checkNotNull(callback, "callback == null");

    okhttp3.Call call;
    Throwable failure;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      call = rawCall;
      failure = creationFailure;
      if (call == null && failure == null) {
        try {
          call = rawCall = createRawCall();
        } catch (Throwable t) {
          failure = creationFailure = t;
        }
      }
    }

    if (failure != null) {
      callback.onFailure(this, failure);
      return;
    }

    if (canceled) {
      call.cancel();
    }

    // 异步请求
    call.enqueue(new okhttp3.Callback() {
      @Override public void onResponse(okhttp3.Call call, okhttp3.Response rawResponse)
          throws IOException {
        Response<T> response;
        try {
          response = parseResponse(rawResponse);
        } catch (Throwable e) {
          callFailure(e);
          return;
        }
        callSuccess(response);
      }

      @Override public void onFailure(okhttp3.Call call, IOException e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callFailure(Throwable e) {
        try {
          callback.onFailure(OkHttpCall.this, e);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }

      private void callSuccess(Response<T> response) {
        try {
          callback.onResponse(OkHttpCall.this, response);
        } catch (Throwable t) {
          t.printStackTrace();
        }
      }
    });
  }

  // 同步方法
  public Response<T> execute() throws IOException {
    okhttp3.Call call;

    synchronized (this) {
      if (executed) throw new IllegalStateException("Already executed.");
      executed = true;

      if (creationFailure != null) {
        if (creationFailure instanceof IOException) {
          throw (IOException) creationFailure;
        } else {
          throw (RuntimeException) creationFailure;
        }
      }

      call = rawCall;
      if (call == null) {
        try {
          call = rawCall = createRawCall();
        } catch (IOException | RuntimeException e) {
          creationFailure = e;
          throw e;
        }
      }
    }

    if (canceled) {
      call.cancel();
    }

    return parseResponse(call.execute());
  }


  // 本次请求结果经过toResponse(Converter)处理后返回
  Response<T> parseResponse(okhttp3.Response rawResponse) throws IOException {
    ResponseBody rawBody = rawResponse.body();

    // Remove the body's source (the only stateful object) so we can pass the response along.
    rawResponse = rawResponse.newBuilder()
        .body(new NoContentResponseBody(rawBody.contentType(), rawBody.contentLength()))
        .build();

    int code = rawResponse.code();
    if (code < 200 || code >= 300) {
      try {
        // Buffer the entire body to avoid future I/O.
        ResponseBody bufferedBody = Utils.buffer(rawBody);
        return Response.error(bufferedBody, rawResponse);
      } finally {
        rawBody.close();
      }
    }

    if (code == 204 || code == 205) {
      rawBody.close();
      return Response.success(null, rawResponse);
    }

    ExceptionCatchingRequestBody catchingBody = new ExceptionCatchingRequestBody(rawBody);
    try {
      T body = serviceMethod.toResponse(catchingBody);
      return Response.success(body, rawResponse);
    } catch (RuntimeException e) {
      // If the underlying source threw an exception, propagate that rather than indicating it was
      // a runtime exception.
      catchingBody.throwIfCaught();
      throw e;
    }
  }

上面代码只截取了四个重要的方法

  • createRawCall()生成用于请求的Call对象
  • enqueue() 异步请求的方法
  • excute() 同步执行的方法
  • parseResponse() 将结果通过Convert转换为所需要的类型

Retrofit中的转换器和适配器

Retrofit的定位是网络框架(底层是由OkHttp负责),它的主要职责就是接口转换为底层可以网络请求的request,和将网络请求返回的response转换为我们想要的数据类型。所以CallAdapter和Convert完成了这两个功能。同时,这两个接口设计的十分灵活,易于拓展,可以和当今甚至未来的各种库对接,也体现了Retrofit的优势。

CallAdapter在Retrofit中有一个默认的实现类,在Platform类中的ExecutorCallAdapterFactory,RxJavaCallAdapterFactory、SquareGuavaCallAdapterFactory等都做了很好的适配。

Convert是将一个类型转换为另一个类型,在retrofit2中的converter库中已经包含了我们通常使用的Gson,jackson等一些列的传唤器,使用十分方便。

最后再总结一下,Retrofit使用到的设计模式

  • 适配器模式
  • 动态代理
  • Builder模式
  • 工厂模式

从okhttp和retrofit可以看出来,优雅的设计框架,总是非常灵活的,通过实现一些定义好的接口,然后根据业务的场景需求将相应的逻辑无缝插入到这些框架中,即实现了功能又不会破坏代码整体的结构,这才是“优雅”的框架。我们在设计框架时,也应该充分借鉴这一点,为用户预留充足的自定义空间,这样才能造出受欢迎的轮子。

image

保姆级教程:在Windows/Mac上从零部署清华Kronos股票预测模型(含Qlib数据更新避坑指南) 本文提供了一份详细的指南,帮助用户在Windows和Mac系统上从零部署清华Kronos股票预测模型,包括环境配置、模型权重获取、Qlib数据更新避坑等关键步骤。特别针对国内用户遇到的网络问题和数据更新不及时提供了解决方案,适合量化投资和金融科技爱好者快速上手。 阅读详情

相关推荐

DDR ECC错误注入与寄存器配置实战指南

本文详细介绍了DDR ECC错误注入的核心价值与实战操作指南,包括通过FI_Dx和FI_ECC寄存器注入数据与ECC错误的方法。文章提供了环境准备、寄存器配置、错误检测及系统可靠性测试策略,帮助开发者验证内存系统的纠错能力和可靠性,提升硬件开发的稳定性与效率。

nnn11的博客 1104

Retrofit详解

一:Retrofit是什么? 准确来说,Retrofit 是一个 RESTful 的 HTTP 网络请求框架的封装。 原因:网络请求的工作本质上是 OkHttp 完成,而 Retrofit 仅负责 网络请求接口的封装 我们先来看看下面这个图: 上图说明了如下几点: 1. App应用程序通过 Retrofit 请求网络,实际上是使用 Retrofit 接口层封装请求参数、Header、Url 等信息,之 后由 OkHttp 完成后续的请求操作。 2. 在服务端返回数据之后,OkHttp 将原始的结果交给

qq_30621333的博客 3万+

聚类模型-层次聚类

聚类模型 1、层次聚类 2、原型聚类-K-means 3、模型聚类-GMM 4、EM算法-LDA主题模型 5、密度聚类-DBSCAN 6、图聚类-谱聚类 一、层次聚类 一、聚类理论 ​ 一般来说,聚类是在训练样本的标签信息不知的情况下,学习样本内在的性质和规律,将有限的集合划分成ccc类。根据“方以类聚,物以群分”的思想,类内对象尽可能的相似,...

myazi 6502

Retrofit2 详解和使用(一)

前言:要么出击,要么出局,命运女神总会眷顾拼尽全力的一方。 一、概述 1、什么是retrofit retrofit是现在比较流行的网络请求框架,可以理解为okhttp的加强版,底层封装了Okhttp。准确来说,Retrofit是一个RESTful的http网络请求框架的封装。因为网络请求工作本质上是由okhttp来完成,而Retrofit负责网络请求接口的封装。 本质过...

https://juejin.cn/user/1654096907477549/posts 7万+

国产射频直采收发器CX8242KA JESD204C调试

杭州诚芯公司的CX8242KA是国内开发的极少数支持JESD204C接口的高速AD、DA,Serdes具备支持接收和发送,并且速率可以到25Gbps,在国内属于领先水平。250M参考时钟输入,AD采样率2.5G,DA采样率10G,3收2发,主通道模式4,反馈通道模式1,基带采样率1250M,线速率20.625G,收发同时配置混频625M。CX8242KA的204C接口模式支持10种模式,在手册上都有说明。2、 支持TX信道编码,RX信道解码,提升健壮性。这里使用模式4,支持双通道模式,并且反馈开启。

RFSOC的博客 6217

保姆级教程:用STM32H743+TJA1042T玩转FDCAN,CubeMX配置1M/5M双速率通信(附完整代码)

本文提供STM32H743与TJA1042T实现FDCAN双速率通信的保姆级教程,详细讲解CubeMX配置1M/5M双速率通信的全过程,包括硬件连接、时钟树配置、过滤器设置及中断管理,并附完整代码示例,助力开发者快速掌握FDCAN高速通信技术。

weixin_30698297的博客 472

Carson带你学Android:这是一份详细的 Retrofit使用教程(含实例讲解)

前言 在Andrroid开发中,网络请求十分常用 而在Android网络请求库中,Retrofit是当下最热的一个网络请求库 今天,我将献上一份非常详细Retrofit v2.0的使用教程,希望你们会喜欢。 如果对Retrofit v2.0的源码感兴趣,可看文章:Android:手把手带你深入剖析 Retrofit 2.0 源码 目录![目录](http://upload-

Carson带你学Android 25万+

AI预测彩票,使用chatgpt和lstm神经网络(文末附源码)

AI预测彩票,使用chatgpt和lstm神经网络(文末有彩蛋)

淘淘小窝 1万+

Retrofit 详解+使用

Android kotlin Retrofi 详细使用讲解

qq_38367671的博客 3184

YOLO创新点改进点的消融实验设计规范

YOLO改进的消融实验是一种重要的方法,用于评估和验证模型中不同组件的影响。在进行YOLO改进的消融实验时,我们可以选择一些可能的改进点,比如Backbone网络、Anchor框设计和损失函数设计,然后通过实验来分析它们对模型性能的影响。首先,我们需要确定实验设计。对于每个改进点,我们将设计多个实验组,并针对每个实验组训练模型并进行性能评估。这里以三个改进点为例进行说明:改进点1:Backbone网络 (改进点2:Anchor框设计 (改进点3:损失函数设计 (

crasher123的博客 2909

【虚幻引擎UE】UE5 仅需6步轻松实现关卡顺滑切换

【虚幻引擎UE】UE5 仅需6步轻松实现关卡切换

灵境引路人 2万+

Retrofit源码解读(三) RxJavaCallAdapterFactory讲解

Retrofit源码解读(三)--RxJavaCallAdapterFactory讲解 标签(空格分隔):Retrofit源码 前言 以下的相关知识总结是通过慕课网的相关学习和自己的相关看法,如果有需要的可以去查看一下慕课网的相关教学,感觉还可以。 父类 which uses RxJava for creating observables final class RxJavaCallAda...

weixin_34006965的博客 801

智能能效管家:基于 ESP32 的智能插座设计与精细化功耗管理实现

针对传统插座无法远程控制、功耗监测缺失、能源浪费严重等问题,本文设计一款基于 ESP32 主控芯片的智能插座。该系统集成 WiFi 无线通信、交流功耗采集、继电器通断控制模块,实现四大核心功能。硬件采用模块化选型与安全接线设计,软件基于 Arduino-ESP32 框架开发,搭载 Mqtt 通信协议与功耗算法,可通过手机 / 云端实时管控设备,有效提升用电安全性与能源利用率。:ESP32;智能插座;功耗管理;远程控制;能耗监测。

weixin_42300449的博客 101

Retrofit2 源码阅读

使用Retrofit作为Android网络请求已经非常普遍了,并且Retrofit的源码不仅少而且还很精妙,作为阅读学习的对象在合适不过了。 基本用法 要了解一个框架的源码,肯定要知道它的基本用法。然后从基本用法里选择一个入口方法,这样就可以跟着用法读下去了。 1、定义请求接口 public interface GitHubService { @GET("users/{user}/repo...

正义 260

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

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

Retrofit2源码的阅读

前几篇笔记记录的都是Retrofit2的使用,但是它内部到底干了什么我们还是啥都不知道。这让我们在使用Retrofit时,心里没底。所以这次我们就来简单过一遍retrofit的源码。看Retrofit的源码对于毫无经验的我来说,第一步应该从哪呢?我决定从这开始: retrofit = new Retrofit.Builder() .baseUrl(BASE_URL)

qq_36046305的博客 329

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

android小说阅读源码、bilibili源码、MVP新闻源码等

Android精选源码 一款基于 MVP+RxJava2+Retrofit2 的应用——熊猫眼 android 五子棋源码分享 android实现全国地图点击效果 android实现立体图案绘制的代码 android仿哔哩哔哩客户端源码 android一个实现思维导图的源码 android功能众多的小说阅读器源码 妮哩萌萌(妮媌),源代码 一款MD风格的新闻APP,MVP试练项目 android六边形蜂巢布局控件 Android优质博客 仿QQ获取手机中的APK并分享的实现 前几天看到同

chenhui0822的博客 1039

ssm框架搭建

这个是一个在idea上成功跑起来的ssm框架项目,保存在这里方便以后使用直接下载

android小说阅读、MVP + RxJava + Retrofit项目、证件拍照裁剪、蓝牙锁等源码

Android精选源码 完全防美团设置支付密码,页面与细节完全一致,如不能... android智能选股应用源码 android开源小说阅读app源码(Kotlin) Android模仿Duolingo的卡片切换效果 android基于MVP + RxJava + Retrofit项目...

chuangzhi9350的博客 227

源码阅读的5个关键步骤:Awesome-Third-Library-Source-Analysis教你高效学习开源项目

想要深入理解Android开发中的热门第三方库源码吗?Awesome-Third-Library-Source-Analysis项目为你提供了系统化的源码阅读指南!😊 通过分析OkHttp、Retrofit、Glide等顶级开源库的实现原理,这个项目帮助开发者掌握源码阅读的5个关键步骤,从零基础到源码高手,全面提升你的技术功力。 ## 📚 第一步:明确学习目标,选择合适的三方库 在开始源码

gitblog_00722的博客 492

不会吧不会吧?互联网界内近百款源码框架开源分享了,真是小母牛坐飞机,牛逼上天了啊

前言 在文章开始之前,请各位先回忆下在日常开发过程中,都使用或依赖了哪些开源项目?是不是发现,开源项目已经完全融入到日常开发! 如今大多数的程序员技术栈和工具箱里,或多或少都有开源项目的身影:大到操作系统、小到精美的图标,优秀的开源项目就像“神器”可以让程序员所向披靡,快刀斩乱麻。但强大的“神器”也带来了一些问题,如果“神器”使用得不熟练或姿势不对,就会出现难以解决的 Bug 和问题,这个时候常见的解决方法: 1.问搜索引擎 2.查文档 3.提 issues 如果上面的方法都没能解决,那就只能自食其力阅读源

老皮的博客 402

如何快速上手WanAndroidClient源码?新手运行第一个Kotlin项目的5步教程

WanAndroidClient 是一款用 Kotlin 语言编写的 Android 客户端开源项目,它对接「玩Android」开放接口,完整实现了首页资讯流、知识体系、搜索、登录注册、收藏和常用网站等实用功能。对于想学习 Android 开发的新手来说,它是一个结构清晰、技术栈经典的 Kotlin 项目。本教程将带你用 5 个步骤,从零开始运行并读懂这个 Kotlin 项目的源码。🚀 ##

gitblog_01163的博客 420

Android:手把手带你 深入读懂 Retrofit 2.0 源码

Android:手把手带你 深入读懂 Retrofit 2.0 源码 转载于:https://www.cnblogs.com/tc310/p/10133182.html

weixin_30361753的博客 99

Android Studio实现文艺阅读App

本次带来的文艺阅读App可以提供高质量的原创文学作品。用户可以App中找到各种类型的文学作品,包括小说、散文、诗歌等,由来自不同领域的作家所创作。此外,App还为用户提供了许多有趣的功能,如文章音频朗诵、视频播放、单向历和每日推荐等,帮助用户快速发现自己喜欢的文学作品。总之,文艺阅读App是一款优秀的阅读应用程序,为用户提供了丰富多样的文学作品和有趣的交流体验。系统基于MVP+Dagger2+Retrofit2.0+Rxjava进行设计和开发。

振华OPPO的博客世界 4350

2023送大家一份Android开发优秀源码合集(附解析)

本文是一位阿里P8大佬花了将近半个月时间,收纳了近百个知名开源项目的源码注释和源码阅读笔记,整理而成的Android开发源码合集。

大模型学习路线 1782

android小说阅读、MVP + RxJava + Retrofit项目、证件拍照裁剪、蓝牙锁等源码器

Android精选源码 完全防美团设置支付密码,页面与细节完全一致,如不能… android智能选股应用源码 android开源小说阅读app源码(Kotlin) Android模仿Duolingo的卡片切换效果 android基于MVP + RxJava + Retrofit项目练手 基于Material Design设计的蓝牙锁APP ...

ld11620967的博客 441
上一篇: OkHttp3源码分析
下一篇: 优雅的监听软键盘隐藏
Bobby_lyc
博客等级 码龄16年 1164粉丝 89原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值