数学基础
- 线性代数
- 概率论与随机过程
- 数值计算
- 蒙特卡洛方法与 MCMC 采样
- 机器学习方法概论
统计学习
深度学习
- 深度学习简介
- 深度前馈网络
- 反向传播算法
- 正则化
- 深度学习中的最优化问题
- 卷积神经网络
- CNN:图像分类
- 循环神经网络 RNN
- Transformer
- 一、Transformer [2017]
- 二、Universal Transformer [2018]
- 三、Transformer-XL [2019]
- 四、GPT1 [2018]
- 五、GPT2 [2019]
- 六、GPT3 [2020]
- 七、OPT [2022]
- 八、BERT [2018]
- 九、XLNet [2019]
- 十、RoBERTa [2019]
- 十一、ERNIE 1.0 [2019]
- 十二、ERNIE 2.0 [2019]
- 十三、ERNIE 3.0 [2021]
- 十四、ERNIE-Huawei [2019]
- 十五、MT-DNN [2019]
- 十六、BART [2019]
- 十七、mBART [2020]
- 十八、SpanBERT [2019]
- 十九、ALBERT [2019]
- 二十、UniLM [2019]
- 二十一、MASS [2019]
- 二十二、MacBERT [2019]
- 二十三、Fine-Tuning Language Models from Human Preferences [2019]
- 二十四 Learning to summarize from human feedback [2020]
- 二十五、InstructGPT [2022]
- 二十六、T5 [2020]
- 二十七、mT5 [2020]
- 二十八、ExT5 [2021]
- 二十九、Muppet [2021]
- 三十、Self-Attention with Relative Position Representations [2018]
- 三十一、USE [2018]
- 三十二、Sentence-BERT [2019]
- 三十三、SimCSE [2021]
- 三十四、BERT-Flow [2020]
- 三十五、BERT-Whitening [2021]
- 三十六、Comparing the Geometry of BERT, ELMo, and GPT-2 Embeddings [2019]
- 三十七、CERT [2020]
- 三十八、DeCLUTR [2020]
- 三十九、CLEAR [2020]
- 四十、ConSERT [2021]
- 四十一、Sentence-T5 [2021]
- 四十二、ULMFiT [2018]
- 四十三、Scaling Laws for Neural Language Models [2020]
- 四十四、Chinchilla [2022]
- 四十七、GLM-130B [2022]
- 四十八、GPT-NeoX-20B [2022]
- 四十九、Bloom [2022]
- 五十、PaLM [2022] (粗读)
- 五十一、PaLM2 [2023](粗读)
- 五十二、Self-Instruct [2022]
- 句子向量
- 词向量
- 传统CTR 预估模型
- CTR 预估模型
- 一、DSSM [2013]
- 二、FNN [2016]
- 三、PNN [2016]
- 四、DeepCrossing [2016]
- 五、Wide 和 Deep [2016]
- 六、DCN [2017]
- 七、DeepFM [2017]
- 八、NFM [2017]
- 九、AFM [2017]
- 十、xDeepFM [2018]
- 十一、ESMM [2018]
- 十二、DIN [2017]
- 十三、DIEN [2019]
- 十四、DSIN [2019]
- 十五、DICM [2017]
- 十六、DeepMCP [2019]
- 十七、MIMN [2019]
- 十八、DMR [2020]
- 十九、MiNet [2020]
- 二十、DSTN [2019]
- 二十一、BST [2019]
- 二十二、SIM [2020]
- 二十三、ESM2 [2019]
- 二十四、MV-DNN [2015]
- 二十五、CAN [2020]
- 二十六、AutoInt [2018]
- 二十七、Fi-GNN [2019]
- 二十八、FwFM [2018]
- 二十九、FM2 [2021]
- 三十、FiBiNET [2019]
- 三十一、AutoFIS [2020]
- 三十三、AFN [2020]
- 三十四、FGCNN [2019]
- 三十五、AutoCross [2019]
- 三十六、InterHAt [2020]
- 三十七、xDeepInt [2023]
- 三十九、AutoDis [2021]
- 四十、MDE [2020]
- 四十一、NIS [2020]
- 四十二、AutoEmb [2020]
- 四十三、AutoDim [2021]
- 四十四、PEP [2021]
- 四十五、DeepLight [2021]
- 图的表达
- 一、DeepWalk [2014]
- 二、LINE [2015]
- 三、GraRep [2015]
- 四、TADW [2015]
- 五、DNGR [2016]
- 六、Node2Vec [2016]
- 七、WALKLETS [2016]
- 八、SDNE [2016]
- 九、CANE [2017]
- 十、EOE [2017]
- 十一、metapath2vec [2017]
- 十二、GraphGAN [2018]
- 十三、struc2vec [2017]
- 十四、GraphWave [2018]
- 十五、NetMF [2017]
- 十六、NetSMF [2019]
- 十七、PTE [2015]
- 十八、HNE [2015]
- 十九、AANE [2017]
- 二十、LANE [2017]
- 二十一、MVE [2017]
- 二十二、PMNE [2017]
- 二十三、ANRL [2018]
- 二十四、DANE [2018]
- 二十五、HERec [2018]
- 二十六、GATNE [2019]
- 二十七、MNE [2018]
- 二十八、MVN2VEC [2018]
- 二十九、SNE [2018]
- 三十、ProNE [2019]
- Graph Embedding 综述
- 图神经网络
- 一、GNN [2009]
- 二、Spectral Networks 和 Deep Locally Connected Networks [2013]
- 三、Fast Localized Spectral Filtering On Graph [2016]
- 四、GCN [2016]
- 五、神经图指纹 [2015]
- 六、GGS-NN [2016]
- 七、PATCHY-SAN [2016]
- 八、GraphSAGE [2017]
- 九、GAT [2017]
- 十、R-GCN [2017]
- 十一、 AGCN [2018]
- 十二、FastGCN [2018]
- 十三、PinSage [2018]
- 十四、GCMC [2017]
- 十五、JK-Net [2018]
- 十六、PPNP [2018]
- 十七、VRGCN [2017]
- 十八、ClusterGCN [2019]
- 十九、LDS-GNN [2019]
- 二十、DIAL-GNN [2019]
- 二十一、HAN [2019]
- 二十二、HetGNN [2019]
- 二十三、HGT [2020]
- 二十四、GPT-GNN [2020]
- 二十五、Geom-GCN [2020]
- 二十六、Graph Network [2018]
- 二十七、GIN [2019]
- 二十八、MPNN [2017]
- 二十九、UniMP [2020]
- 三十、Correct and Smooth [2020]
- 三十一、LGCN [2018]
- 三十二、DGCNN [2018]
- 三十三、AS-GCN
- 三十四、DGI [2018]
- 三十五、DIFFPOLL [2018]
- 三十六、DCNN [2016]
- 三十七、IN [2016]
- 图神经网络 2
- 图神经网络 3
- 推荐算法(传统方法)
- 一、Tapestry [1992]
- 二、GroupLens [1994]
- 三、ItemBased CF [2001]
- 四、Amazon I-2-I CF [2003]
- 五、Slope One Rating-Based CF [2005]
- 六、Bipartite Network Projection [2007]
- 七、Implicit Feedback CF [2008]
- 八、PMF [2008]
- 九、SVD++ [2008]
- 十、MMMF 扩展 [2008]
- 十一、OCCF [2008]
- 十二、BPR [2009]
- 十三、MF for RS [2009]
- 十四、 Netflix BellKor Solution [2009]
- 推荐算法(神经网络方法 1)
- 一、MIND [2019](用于召回)
- 二、DNN For YouTube [2016]
- 三、Recommending What Video to Watch Next [2019]
- 四、ESAM [2020]
- 五、Facebook Embedding Based Retrieval [2020](用于检索)
- 六、Airbnb Search Ranking [2018]
- 七、MOBIUS [2019](用于召回)
- 八、TDM [2018](用于检索)
- 九、DR [2020](用于检索)
- 十、JTM [2019](用于检索)
- 十一、Pinterest Recommender System [2017]
- 十二、DLRM [2019]
- 十三、Applying Deep Learning To Airbnb Search [2018]
- 十四、Improving Deep Learning For Airbnb Search [2020]
- 十五、HOP-Rec [2018]
- 十六、NCF [2017]
- 十七、NGCF [2019]
- 十八、LightGCN [2020]
- 十九、Sampling-Bias-Corrected Neural Modeling [2019](检索)
- 二十、EGES [2018](Matching 阶段)
- 二十一、SDM [2019](Matching 阶段)
- 二十二、COLD [2020 ] (Pre-Ranking 模型)
- 二十三、ComiRec [2020](https://www.wenjiangs.com/doc/0b4e1736-ac78)
- 二十四、EdgeRec [2020]
- 二十五、DPSR [2020](检索)
- 二十六、PDN [2021](mathcing)
- 二十七、时空周期兴趣学习网络ST-PIL [2021]
- 推荐算法之序列推荐
- 一、FPMC [2010]
- 二、GRU4Rec [2015]
- 三、HRM [2015]
- 四、DREAM [2016]
- 五、Improved GRU4Rec [2016]
- 六、NARM [2017]
- 七、HRNN [2017]
- 八、RRN [2017]
- 九、Caser [2018]
- 十、p-RNN [2016]
- 十一、GRU4Rec Top-k Gains [2018]
- 十二、SASRec [2018]
- 十三、RUM [2018]
- 十四、SHAN [2018]
- 十五、Phased LSTM [2016]
- 十六、Time-LSTM [2017]
- 十七、STAMP [2018]
- 十八、Latent Cross [2018]
- 十九、CSRM [2019]
- 二十、SR-GNN [2019]
- 二十一、GC-SAN [2019]
- 二十二、BERT4Rec [2019]
- 二十三、MCPRN [2019]
- 二十四、RepeatNet [2019]
- 二十五、LINet(2019)
- 二十六、NextItNet [2019]
- 二十七、GCE-GNN [2020]
- 二十八、LESSR [2020]
- 二十九、HyperRec [2020]
- 三十、DHCN [2021]
- 三十一、TiSASRec [2020]
- 推荐算法(综述)
- 多任务学习
- 系统架构
- 实践方法论
- 深度强化学习 1
- 自动代码生成
工具
- CRF
- lightgbm
- xgboost
- scikit-learn
- spark
- numpy
- matplotlib
- pandas
- huggingface_transformer
- 一、Tokenizer
- 二、Datasets
- 三、Model
- 四、Trainer
- 五、Evaluator
- 六、Pipeline
- 七、Accelerate
- 八、Autoclass
- 九、应用
- 十、Gradio
Scala
- 环境搭建
- 基础知识
- 函数
- 类
- 样例类和模式匹配
- 测试和注解
- 集合 collection(一)
- 集合collection(二)
- 集成 Java
- 并发
四、继承
类的组合:一个类可以包含对另一个类的引用,利用这个被引用类来帮助它完成任务。组合代表了两个类的关系是:
has-a
。类的继承:超类与子类的关系。继承代表了两个类的关系是:
is-a
组合和继承是两种用已有的类来定义新类的两种方式。如果追求代码复用,通常优先选择组合而不是继承。因为继承会遇到脆弱基类问题:在修改超类时会不小心破坏子类的代码。
4.1 继承
4.1.1 抽象类
通过修饰符
abstract
可以表明类是抽象的,这种类称作抽象类。不可以直接实例化一个抽象类。xxxxxxxxxx
abstract class Element { def contents: Array[String] }其中
contents
方法是一个没有实现的方法,这种方法称作抽象成员。一个包含抽象成员的类必须声明为抽象类。这与Java
不同,Java
中抽象成员也需要添加修饰符abstract
。
4.1.2 继承
Scala
通过关键字extends
来声明类的继承。xxxxxxxxxx
class ArrayElement(conts:Array[String]) extends Element{ def contents: Array[String] = conts }extends
有两个作用:- 子类从父类中继承所有的非私有成员。
- 子类成为父类的子类型
subtype
。子类型的意思是:任何需要超类对象的地方,都可以用子类对象来替代。
这里
ArrayElement
是Element
的子类,Element
是ArrayElement
的超类。如果没有
extends
语句,则Scala
的类默认继承自scala.AnyRef
,这对应于Java
的java.lang.Object
类。类的继承:子类从父类中继承所有成员,除了以下两个例外:
子类并不会继承父类的私有成员。
如果子类已经实现了父类中相同名称和参数的成员,则该成员不会被继承。这种情况称作:子类的成员重写
override
了父类的成员。更进一步的,如果子类的成员是具体的,而父类的成员是抽象的,则称子类的具体的成员实现
implement
了那个抽象的成员。
4.1.3 父类构造函数
如果需要调用超类的构造方法,则只需要将你打算传入的入参放在超类名称后的圆括号里即可。
xxxxxxxxxx
class Child(name: String) extends Parent(name){ // 类的定义 }
4.2 重载
Scala
支持方法重载:同一个方法名可以用于多个方法,这些方法的参数列表不同。在方法调用时,Scala
根据入参类型来选取合适的重载版本。与Java
类似,Scala
根据最匹配的入参类型来选择。如果找不到合适的重载版本,则编译器提示
ambiguous reference
错误。xxxxxxxxxx
class C(n:Int,s:String) { private val num:Int = n private val name:String = s def f(num:Int) = this.num <= num // 版本一 def f(name:String) = this.name <= name // 版本二 }类默认继承了
java.lang.Object
类的toString
实现,该实现只是简单的打印出类名、一个@
符、一个十六进制数字。通常会重写类的
toString
方法来获取更有价值的信息,从而方便调试。重写方法通过关键字override
实现:xxxxxxxxxx
class C(n:Int,s:String) { override def toString = n + ";" + s // 精简了花括号、return、空参数、返回类型 }override
表示父类的该方法被重写覆盖了。Scala
并没有操作符重载,因为它并没有传统意义上的操作符。类似+,-,*,/
这样的字符可以被作为方法名。因此1+2
这种表达式实际上调用了Int
对象1
上的、一个叫做+
的方法,2
是该方法的参数。你也可以显式写作:
1.+(2)
。Scala
中,字段和方法属于同一个命名空间,这使得字段重写无参方法成为可能。- 可以通过
val
字段重写父类同名的val
字段或者无参方法。 - 也可以通过无参方法重写父类同名的
val
字段或者无参方法。
- 可以通过
Scala
要求在所有重写了父类具体成员的成员之前加上override
修饰符。- 如果重写的是父类的抽象成员,则可以加、也可以不加上
override
。
- 如果重写的是父类的抽象成员,则可以加、也可以不加上
如果没有重写父类成员,但是添加了
override
,则编译报错。- 如果应该添加而未添加
override
,则编译器也报错。
- 如果应该添加而未添加
如果希望某个成员(方法或者字段)不能够被子类重载,则可以在成员之前添加
final
修饰符。如果子类
override
了父类的一个final
成员,则编译报错。xxxxxxxxxx
class C // 父类 { final def echo = println("This is C") // 不需要 echo 被子类重载 } class Child extends C // 子类 { override def echo = println("This is Child") // 编译报错 }如果希望整个类没有子类,则可以简单的将类声明为
final
的,做法是在类声明之前添加final
修饰符。xxxxxxxxxx
final class C // 不希望 C 拥有子类 { def echo = println("This is C") }
4.3 多态和动态绑定
一个类型为
C
的变量可以指向任何一个C
的子类型的对象,这种现象称作多态polymorphism
。对变量和表达式的方法调用是动态绑定的:实际被调用的方法实现是在运行时基于对象的类型来决定的,而不是变量或者表达式的类型决定的。
xxxxxxxxxx
class C // 父类 { def echo = println("This is C") } class Child extends C // 子类 { override def echo = println("This is Child") } def f1():C = new C // 函数 f1 返回类型为 C def f2():C = new Child // 函数 f2 返回类型为 C val c1 = f1() // c1 类型 C val c2 = f2() // c2 类型 C c1.echo // 输出:This is C c1.echo // 输出:This is Child例子中,虽然函数
f2
返回的静态类型是C
,但是其动态类型是C
的子类Child
。其echo
方法调用的是子类中的echo
方法。
4.4 继承体系
Scala
中,所有类都继承自同一个名为Any
的超类。由于任何类都是Any
的子类,因此Any
中定义的方法是“全类型”的:它们可以在任何对象上被调用。Scala
还在继承关系的底部定义了Null
类和Nothing
类,它们本质上是作为通用子类存在的。Nothing
类是每个其它类的子类。
4.4.1 Any 类
Any
类是所有继承关系的顶部,它定义了如下方法:相等和不等比较:
xxxxxxxxxx
final def ==(that:Any) : Boolean final def !=(that:Any) : Boolean def equals(that:Any) : Boolean==
和!=
是final
的,因此不能被子类重写。==
方法本质上等同于equals
,而!=
一定是equals
的反义。因此可以通过重写equals
方法来定制==
和!=
的含义。Scala
的相等性==
被设计为:对类型的实际表现是透明的:对于值类型而言,它表示的是自然的数值相等性;对于引用类型而言,它表示的是从Object
继承的equals
方法的别名。
哈希函数:
xxxxxxxxxx
def ## : Int def hasCode : Int格式化成字符串:
xxxxxxxxxx
def toString : String
在
Scala
中,如果希望使用引用相等性而不是内容上的相等性,则使用eq
方法。AnyRef
类定义了eq,ne
方法来给出引用相等性和引用不等性。Any
类有两个子类:AnyVal
和AnyRef
:AnyVal
是所有值类型的父类;AnyRef
是所有引用类型的父类。在
Java
平台上,AnyRef
事实上只是java.lang.Object
的一个别名,因此Java
编写的类和Scala
编写的类都集成自AnyRef
。虽然可以在面向Java
平台的Scala
程序中任意切换Object
和AnyRef
,但是推荐采用AnyRef
。
4.4.2 AnyVal 类
可以通过继承
AnyVal
来定义自己的值类型。Scala
提供了九个内建的值类型:Byte,Short,Char,Int,Long,FLoat,Double,Boolean,Unit
。其中前八个对应
Java
的基本类型,它们的runtime
是采用Java
基本类型来表示的。这些类的实例在
Scala
中统统写作字面量,不能用new
来创建这些类的实例。这是通过将这些值类型定义为abstract
同时也是final
这个技巧来完成的。最后一个
Unit
粗略的对应到Java
的void
类型,它有且只有一个实例值,写作()
。
值类型以方法的形式支持通常的算术和布尔运算操作符,同时它们还支持
Any
类的所有方法。值类空间是扁平的:所有的值类型都是
scala.AnyVal
的子类,但是它们之间并没有子类关系。而不同值类型之间存在隐式类型转换。
可以对
Int
类型调用min,max,until,to,abs
等方法。原理是:存在从Int
类到RichInt
类的隐式转换。只要对
Int
调用的方法没有在Int
类中定义,而RichInt
类刚好定义了该方法,则隐式转换就自动应用。其它的值类型也有类似的辅助类和隐式转换。
4.4.3 底类型
Null
类是null
引用的类型,它是每个引用类的子类。Null
类并不兼容值类型,如:你无法将null
赋值给一个整数变量。Nothing
位于scala
类继承关系的底部,它是任何其它类型的子类。实际上并不存在这个
Nothing
类型的任何值,其用途之一是给出非正常终止信号。如:
xxxxxxxxxx
def error(message: String) : Nothing = throw new RuntimeException(message) // Nothing 表明该方法并不会正常返回 def f(x:Int,y:Int): Int = if (y!=0) x/y else error("can't divide by 0")由于
error
分支的类型为Nothing
,兼容于Int
,因此能够成功编译。
4.4.4 自定义值类型
可以自定义值类型来对内建的值类型进行扩充。和内建的值类型一样,自定义的值类型通常也会编译成那种不使用包装类的
Java
字节码。而在需要包装类的环境中(如泛型),值类型将被自动装箱和拆箱。
要使得某个类成为值类,该类必须满足以下条件:
- 该类继承自
AnyVal
。 - 该类必须有且仅有一个参数,且在该唯一参数之前加上
val
(参数化字段)。这可以让该参数作为字段被外界访问。 - 该类的内部除了
def
之外不能有任何其它东西。 - 该类不能有子类。
- 该类不能重写
equals
和hashCode
。
xxxxxxxxxx
class RMB(val amount:Int) extends AnyVal { override def toString() = "$" + amount }RMB
在Scala
源码中的类型为RMB
,但是编译后Java
字节码中直接使用Int
。- 该类继承自
一个良好的习惯是:对每个领域概念定义一个新的类,哪怕复用相同的类来实现不同用途也是可以的。甚至这样的类是细微类:既没有方法,也没有字段。
这个方法可以有助于编译器在更多的地方帮助你。如:
xxxxxxxxxx
def ROI(cost:Double, revenue:Double): Double = (revenue-cost)/cost这个函数用于计算企业的
ROI
。如果由于疏忽,将成本传给了revenue
参数、将收入传给了cost
参数,则计算结果是错误的。此时编译器并不会错误,因为它们都是Double
类型。此时可以定义值类:
xxxxxxxxxx
class Cost(val value: Double) extends AnyVal class Revenue(val value: Double) extends AnyVal def ROI(cost:Cost, revenue:Revenue) : Double = (revenue.value-cost.value)/cost.value
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论