tonglin0325的个人主页

特征预处理——编码

对于标称型数据,在特征处理的时候,需要对其进行编码

在编码之前,如果训练集和测试集是分开的,则需要对其进行合并,避免标称数据丢失

1
2
3
4
5
# 合并
df = train.append(test).reset_index()
# 列名
original_columns = list(df.columns)

常用的编码方式如下

1.Label编码

对于一个有m个category的特征,经过label encoding以后,每个category会映射到0到m-1之间的一个数。label encoding适用于ordinal feature (特征存在内在顺序)。

1
2
3
4
5
6
7
8
from sklearn import preprocessing

for col in original_columns:
enc = preprocessing.LabelEncoder()
enc.fit(np.concatenate([train[col], test[col]]))
train[col] = enc.transform(train[col])
test[col] = enc.transform(test[col])

或者

1
2
train_data = train_data.replace({'BsmtQual': {'Ex': 5, 'Gd': 4, 'TA': 3, 'Fa': 2, 'Po': 1, np.NaN: 0}})

2.顺序编码

类似于Label编码

参考:数据转化

1
2
3
4
5
6
7
8
9
10
from sklearn import preprocessing

enc = preprocessing.OrdinalEncoder()
X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
enc.fit(X)
>> OrdinalEncoder()

enc.transform([['female', 'from US', 'uses Safari']])
>> array([[0., 1., 1.]])

3.one-hot编码

对于一个有m个category的特征,经过独热编码(OHE)处理后,会变为m个二元特征,每个特征对应于一个category。这m个二元特征互斥,每次只有一个激活。

独热编码解决了原始特征缺少内在顺序的问题,但是缺点是对于high-cardinality categorical feature (category数量很多),编码之后特征空间过大(此处可以考虑PCA降维),而且由于one-hot feature 比较unbalanced,树模型里每次的切分增益较小,树模型通常需要grow very deep才能得到不错的精度。因此OHE一般用于category数量 <4的情况。

参考:机器学习 | 数据缩放与转换方法(1)kaggle编码categorical feature总结

使用sklearn来one-hot编码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
from sklearn import preprocessing

enc = preprocessing.OneHotEncoder()
# enc = preprocessing.OneHotEncoder(handle_unknown='ignore') # 当 handle_unknown='ignore' 被指定而在转换的过程中碰到了未知的枚举特征值,不会产生任何错误,但是该特征的 one-hot 编码列将会被全部置 0

X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
enc.fit(X)
>> OneHotEncoder()

enc.transform([['female', 'from US', 'uses Safari'], ['male', 'from Europe', 'uses Safari']]).toarray()
>> array([[1., 0., 0., 1., 0., 1.], [0., 1., 1., 0., 0., 1.]])

# 查看每个特征的特征值
enc.categories_
>> [array(['female', 'male'], dtype=object), array(['from Europe', 'from US'], dtype=object), array(['uses Firefox', 'uses Safari'], dtype=object)]

使用pandas来one-hot编码

1
2
3
4
5
6
7
8
9
10
11
12
import pandas as pd

X = [['male', 'from US', 'uses Safari'], ['female', 'from Europe', 'uses Firefox']]
df = pd.DataFrame(X, columns=['sex','country','browser'])
# columns是需要编码的列名
df = pd.get_dummies(df, columns=['sex','country'], dummy_na = True)
print(df)

browser sex_female sex_male sex_nan country_from Europe country_from US country_nan
0 uses Safari 0 1 0 0 1 0
1 uses Firefox 1 0 0 1 0 0

4.target编码

参考:三种Target Encoding方式总结

全文 >>

Flink学习笔记——读写HBase

1.如果是csa(Cloudera Streaming Analytics)版本的高版本HBase

可以参考Cloudera官方例子,通过引入官方提供的flink-hbase来实现

1
2
3
4
5
6
<dependency>
<groupId>org.apache.flink</groupId>
<artifactId>flink-hbase_2.11</artifactId>
<version>1.9.0-csa1.0.0.0</version>
</dependency>

要求flink最低版本1.9.0,hbase最低版本2.1.0-cdh6.3.0,然后就可以使用HBaseSinkFunction来写Hbase

1
2
https://docs.cloudera.com/csa/1.2.0/datastream-connectors/topics/csa-hbase-configuration.html

全文 >>

Hive学习笔记——metastore listener

除了使用hive hook来记录hive上用户的操作之外,还可以使用hive metastore listener来进行记录,参考:

1
2
https://towardsdatascience.com/apache-hive-hooks-and-metastore-listeners-a-tale-of-your-metadata-903b751ee99f

hive metastore的接口有3种,分别是

全文 >>

mac下安装gradle7.3

gradle和maven类似,是一个构建工具

gradle安装和配置

1.mac安装gradle

1
2
brew install gradle

或者下载gradle的二进制安装包

1
2
https://gradle.org/releases/

然后在~/.bash_profile中配置

1
2
3
4
# gradle
export GRADLE_HOME=/Users/lintong/software/gradle-7.3
export PATH=$GRADLE_HOME/bin:$PATH

2.查看是否安装成功

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
gradle -v

------------------------------------------------------------
Gradle 7.3
------------------------------------------------------------

Build time: 2021-11-09 20:40:36 UTC
Revision: 96754b8c44399658178a768ac764d727c2addb37

Kotlin: 1.5.31
Groovy: 3.0.9
Ant: Apache Ant(TM) version 1.10.11 compiled on July 10 2021
JVM: 1.8.0_211 (Oracle Corporation 25.211-b12)
OS: Mac OS X 10.16 x86_64

使用gradle后,老版本的IDEA 2017.1 对gradle的支持较弱,建议升级到新版本 2021.1

如果需要添加 gradle.properties 配置文件,请放在 $GRADLE_HOME 目录

1
2
3
➜  /Users/lintong/software/gradle-7.3.2 $ ls | grep gradle.properties
gradle.properties

配置文件内容

1
2
3
4
5
/Users/lintong/software/gradle-7.3.2 $ cat gradle.properties
username=xx
password=xx
mavenUser=xx
mavenPassword=xx

gradle处理依赖冲突

使用gradle的时候如果遇到依赖冲突,可以添加如下配置,添加后再编译就能使得有冲突的时候自动失败

1
2
3
4
5
6
configurations.all {
resolutionStrategy {
failOnVersionConflict()
}
}

全文 >>

Spark学习笔记——读写ScyllaDB

Scylla兼容cassandra API,所以可以使用spark读写cassandra的方法来进行读写

1.查看scyllaDB对应的cassandra版本

1
2
3
cqlsh:my_db> SHOW VERSION
[cqlsh 5.0.1 | Cassandra 3.0.8 | CQL spec 3.3.1 | Native protocol v4]

2.查看spark和cassandra对应的版本

参考:https://github.com/datastax/spark-cassandra-connector

3.写scyllaDB

dataset API写scyllaDB

1
2
3
4
5
6
ds2.write
.mode("append")
.format("org.apache.spark.sql.cassandra")
.options(Map("table" -> "my_tb", "keyspace" -> "my_db", "output.consistency.level" -> "ALL", "ttl" -> "8640000"))
.save()

RDD API写scyllaDB

1
2
3
4
5
import com.datastax.oss.driver.api.core.ConsistencyLevel
import com.datastax.spark.connector._

ds.rdd.saveToCassandra("my_db", "my_tb", writeConf = WriteConf(ttl = TTLOption.constant(8640000), consistencyLevel = ConsistencyLevel.ALL))

注意字段的数量和顺序需要和ScyllaDB表的顺序一致,可以使用下面方式select字段

1
2
3
4
5
6
7
8
9
10
11
val columns = Seq[String](
"a",
"b",
"c")
val colNames = columns.map(name => col(name))
val colRefs = columns.map(name => toNamedColumnRef(name))

val df2 = df.select(colNames: _*)
df2.rdd
.saveToCassandra(ks, table, SomeColumns(colRefs: _*), writeConf = WriteConf(ttl = TTLOption.constant(8640000), consistencyLevel = ConsistencyLevel.ALL))

不过官方推荐使用DataFrame API,而不是RDD API

If you have the option we recommend using

全文 >>

DataGrip2017.1连接Hive

在使用低版本的DataGrip的时候,还没有hive的data source,需要自行添加数据源

1.下载hive driver,如果你使用的EMR的大数据集群的话,下载地址

1
2
https://docs.aws.amazon.com/emr/latest/ReleaseGuide/HiveJDBCDriver.html

全文 >>

Kafka学习笔记——Consumer API

参考kafka官方文档,版本1.0.x

1
2
http://kafka.apache.org/10/documentation.html#consumerapi

依赖,选择 Cloudera Rel 中的 1.0.1-kafka-3.1.0

1
2
3
4
5
6
<dependency>
<groupId>org.apache.kafka</groupId>
<artifactId>kafka-clients</artifactId>
<version>1.0.1-kafka-3.1.0</version>
</dependency>

Kafka的消费者有2套API,一个是新版的Java API,在 org.apache.kafka.clients 包中

1
2
http://kafka.apache.org/10/documentation.html#newconsumerconfigs

一个是旧版的Scala API,在 kafka.consumer 包中

1
2
http://kafka.apache.org/10/documentation.html#oldconsumerconfigs

其中new consumer api中文含义参考

1
2
https://tonglin0325.github.io/xml/kafka/1.0.1-kafka-3.1.0/new-consumer-api.xml

kafka consumer参数调优:kafka consumer 参数调优

Kafka消费者不是线程安全的。所有的网络I/O都发生在进行调用的应用程序的线程中。用户有责任确保多线程访问是正确同步的。

zigzag编码原理

在Thrift,Protobuf和avro序列化框架中,不约而同使用了zigzag编码来对数字进行编码,从而达到减少数据传输量的目的。

zigzag算法的核心主要是去除二进制数字中的前导0,因为在绝大多数情况下,我们使用到的整数,往往是比较小的。

参考:小而巧的数字压缩算法:zigzag

在avro编码中,对于字符串Martin,长度为6,而6的二进制为0000 0110,其中首位置的0为符号位,在zigzag编码中,正数的符号位会移动到末尾,其它位往前移动一位,所以会变成0000 1100,即0c,再后面的字节是字符串UTF-8编码后的结果

在protobuf编码中,对于字符串的Martin,刚开始的字节表示其id和数据类型,下一个字节表示其长度,后面的字节是字符串UTF-8编码后的结果

参考:《数据密集型应用系统设计》的 Schema evolution in Avro, Protocol Buffers and Thrift

Avro,Protocol Buffer和Thrift中的模式演化(译)

全文 >>