大佬们,想用python来写一个字体转换器,有什么方法吗

2020-10-13 09:47发布

2条回答
杨晓春
2楼 · 2020-10-16 11:47

根据中文字符获取GB2312编码

通过GB2312编码计算该汉字在点阵字库中的区位和码位

通过区位和码位计算在点阵字库中的偏移量

基于偏移量获取该汉字的32个像素存储字节

解析像素字节获取点阵坐标信息

在对应的坐标显示信息位。如该像素点是否显示点亮

使用该代码前提:下载点阵字体库到本地,这里默认使用的是hzk16点阵字库

代码如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
#!/usr/bin/python
#encoding: utf-8
import binascii
  
RECT_HEIGHT = 16
RECT_WIDTH = 16
BYTE_COUNT_PER_ROW = RECT_WIDTH / 8
BYTE_COUNT_PER_FONT = BYTE_COUNT_PER_ROW * RECT_HEIGHT
  
KEYS = [0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01]
  
class FontRender(object):
 def __init__(self, font_file,
  rect_height=RECT_HEIGHT, rect_width=RECT_WIDTH, byte_count_per_row=BYTE_COUNT_PER_ROW):
 self.font_file = font_file
 self.rect_height = rect_height
 self.rect_width = rect_width
 self.byte_count_per_row = byte_count_per_row
  
 self.__init_rect_list__()
  
 def __init_rect_list__(self):
 self.rect_list = [] * RECT_HEIGHT
  
 for i in range(RECT_HEIGHT):
 self.rect_list.append([] * RECT_WIDTH)
  
 def get_font_area_index(self, txt, encoding='utf-8'):
 if not isinstance(txt, unicode):
 txt = txt.decode(encoding)
  
 gb2312 = txt.encode('gb2312')
 hex_str = binascii.b2a_hex(gb2312)
  
 area = eval('0x' + hex_str[:2]) - 0xA0
 index = eval('0x' + hex_str[2:]) - 0xA0
  
 return area, index
  
 def get_font_rect(self, area, index):
 offset = (94 * (area-1) + (index-1)) * BYTE_COUNT_PER_FONT
 btxt = None
  
 with open(self.font_file, "rb") as f:
 f.seek(offset)
 btxt = f.read(BYTE_COUNT_PER_FONT)
  
 return btxt
  
 def convert_font_rect(self, font_rect, ft=1, ff=0):
 for k in range(len(font_rect) / self.byte_count_per_row):
 row_list = self.rect_list[k]
 for j in range(self.byte_count_per_row):
 for i in range(8):
  asc = binascii.b2a_hex(font_rect[k * self.byte_count_per_row + j])
  asc = eval('0x' + asc)
  flag = asc & KEYS[i]
  row_list.append(flag and ft or ff)
  
 def render_font_rect(self, rect_list=None):
 if not rect_list:
 rect_list = self.rect_list
  
 for row in rect_list:
 for i in row:
 if i:
  print '■',
 else:
  print '○',
 print
  
 def convert(self, text, ft=None, ff=None, encoding='utf-8'):
 if not isinstance(text, unicode):
 text = text.decode(encoding)
  
 for t in text:
 area, index = self.get_font_area_index(t)
 font_rect = self.get_font_rect(area, index)
  
 self.convert_font_rect(font_rect, ft=ft, ff=ff)
  
 def get_rect_info(self):
 return self.rect_list
  
if '__main__' == __name__:
 text = u'同创伟业'
 fr = FontRender('./font/16x16/hzk16h')
 fr.convert(text, ft='/static/*', ff=0)
 # print fr.get_rect_info()
 fr.render_font_rect()


卡卡
3楼 · 2020-10-22 10:36





作者| 萝卜

来源| 早起Python(ID:zaoqi-python)



前言

大样本的数据集固然提供了丰富的信息,但也在一定程度上增加了问题的复杂性。如果我们分别对每个指标进行分析,往往得到的结论是孤立的,并不能完全利用数据蕴含的信息。但是盲目的去减少我们分析的指标,又会损失很多有用的信息。所以我们需要找到一种合适的方法,一方面可以减少分析指标,另一方面尽量减少原指标信息的损失。

变量压缩的方法非常多,但百法不离其中,其实最根本的都是「主成分分析」(PrimaryComponentAnalysis,下简称PCA)。能够理解PCA的基本原理并将代码用于实际的业务案例是本文的目标,本文将详细介绍如何利用Python实现基于主成分分析的5c信用评级,主要分为两个部分:

详细原理介绍Python代码实战



引入

在正式开始原理趣析前,我们先从两个生活场景入手,借以更好的理解需要进行变量压缩的原因。

场景1:

上司希望从事数据分析岗位的你仅用两个短句就概括出以下数据集所反映出的经济现象。


用几个长句都不一定能够很好的描述数据集的价值,更何况高度凝练的两个短句,短短九个指标就已经十分让人头疼了,如果表格再宽一些呢,比如有二三十个变量?

场景2

大学生讲究德智体美劳全面发展,学校打算从某学院挑选一两名学生外派进修数据分析,需要综合全面的考量学生素质。部分候选学生的个人情况如下:


首先还是与场景1类似的问题,这些指标只是冰山一角,还没算上学生们其他领域的成绩,如果说在场景1中还可以以牺牲全面性来删除一些我们觉得关系不大的变量,比如我们猜测老板只会关注GDP与人均GDP这两个指标,那么场景2的背景便已经清晰地说明了需要综合地考虑变量,不能有生硬的去掉“体育”之类的操作。



信息压缩

如果把信息压缩这四个字拆成信息和压缩这两部分来看的话,便会呈现如下值得探究的问题:


「信息压缩中的信息指什么?」

其实各种数据、变量都可被称为信息,而统计学家们常把方差当作信息。其实在做描述性统计分析的时候,只要能够表现我们数据的变异情况的统计量都可以被称作信息,如方差,极差等,只不过是极差会更好计算。以方差为例,方差变化越大,数据分布越分散,涵盖的信息就越多。

「什么样的信息/变量才能被压缩?」

只有相关性强的变量才能被压缩。如场景2的数学建模和科技节活动,都是学生们理科思维的体现方式,所以可以考虑把这两者合并成一个新的叫“理科思维”的变量,这样便可以不用两个变量都要费笔墨描述,关键是“理科思维”这个新的变量里面数学建模和科技节这两个旧变量的各自的占比是多少。因为这里并没有因变量,所以这两个旧变量的权重系数无法简单的使用多元线性回归来完成。如果变量间的关系几乎是独立的却依然强制压缩(比如体育和演讲),则会大大加剧信息的缺失程度,这也是为什么“压缩”其实带有一丝迫不得已的意味,都是以尽可能损失最少的信息为前提。主成分分析是只能针对连续变量来进行压缩,分类变量则不行。因为分类变量之间可以说是完全独立的,并没有正负两种相关性一说,如性别男和女之间就完全是独立的。如果一定也要将分类变量压缩的话,通常会对他们进行WOE转换(后续推文会提及),之后就可以愉快的进行压缩了。所以分类变量是没办法进行单独压缩的,因为没有对应的算法。有些人可能会直接对分类变量间进行卡方检验,然后把p值大的删去一些,这个其实应该被划分为手工的范畴,并不属于算法。

「有哪些压缩的方法?」

总的来说降维有两种方法,一种是特征消除,另一种是特征提取。

特征消除:如上一问提到的采用卡方检验这样的非算法,又或者直接拍脑袋决策需要删掉哪些变量,但这可能会使我们丢失这些特征中的很多信息。特征提取:通过组合现有特征来创建新变量,可以尽量保存特征中存在的信息。

PCA就是一种常见的特征提取方法,它会将关系紧密的变量们用尽可能少的新创建的变量代替,使这些新变量是两两不相关的。这就实现用较少的综合指标分别代表存在于各个变量中的各类信息。所以多元变量压缩思路的基础其实是相关分析。

「压缩后的信息与原来的有什么不同?」

我们需要明确的是,无论是主成分还是后续推文的稀疏主成分分析,都有一个问题:他们得到的主成分均没有什么业务含义,如果希望得到的压缩后的变量是有意义的,则可以考虑变量聚类。



压缩过程

下图为两个正态分布的变量间可能存在的三种关系的示意图,去正态分布和相关系数为0.9是为了从比较理想化的角度来解释变量压缩的步骤。


可以看到,若两变量间的关系是较强的正/负相关,用铅笔把散点图的范围圈起来的话呈现的都是一个较扁的椭圆;反之,完全独立的两个变量的分布更像是一个肥胖的圆形。关于压缩过程我们依旧对以下几个常见的问题进行解释。

「如何通过散点图理解信息压缩?」

直接看散点图只能判断出是否值得压缩,毕竟只有变量间具有一定的相关性才值得压缩。接下来将涉及到PCA中很重要的一个知识点:坐标轴旋转。


「旋转坐标轴的作用?」

旋转后的坐标轴与原坐标轴一样,都是正交(垂直)的。这样的旋转方式可以使两个相关的变量的信息在坐标轴上得到最充分的体现(如果以极差作为信息,则点在X1的投影范围最长)。之后便可从短轴方向来压缩,当这个椭圆被压扁到一定程度时,短轴上的信息就可以忽略不计,便达到了信息压缩的目的。


「如果有三个变量该如何压缩?」

三维的也是如此,只不过是由椭圆变成椭球(三个变量都相关)。步骤还是一样,找到最长轴后,在轴上做切面,切面一旦有了,便又回归到了二维的情况。这时可以找到次长轴和最短轴,这就可以依次的提取,当我们认为最短轴可以忽略不计的时候,就又起到了信息压缩的作用。


要注意的是如果呈球形分布,这说明变量间没有相关关系,没有必要做主成分分析,也不能做变量的压缩。



建模分析

前面已经说到,PCA后所得到的压缩的主成分并没有什么意义,比如5个变量压缩成2个主成分P1和P2。


这两个主成分中的组成等式为:


其中,等式右边的系数正负与否并没有什么意义,通常看绝对值即可。第一个主成分P1中受五个变量的影响程度无明显差别,权重都在0.42~0.47间主成分P2受第一个变量的影响最大,权重系数为0.83,受第三个变量影响最小,权重为0.14。

那么如何知道应该压缩成几个主成分?PCA的功能是压缩信息,压缩后的每个主成分都能够解释一部分信息的变异程度(统计学家喜欢用方差表示信息的变异程度),所以,只需要满足解释信息的程度达到一定的值即可。

计算每个成份因子。将不同成分因子所能解释的变异百分比相加3.得到的值被称之为累积变异百分比4.PCA过程中,我们将选择能使得这个值最接近于1的维度个数。

明显可以看出随着成分数目的增加,累积变异百分比逐渐增加。不建议使得累积百分比等于1,这将会导致有些主成分带来冗余信息,通常等于0.85就可以了。当然我们也可以选择两个主成分,因为当我们增加第三个主成分因子时,会发现增加它对于累积变异的百分比没有太大的影响。




Python实战

在正式开始Python代码实战前,简要了解主成分分析的运用场景是非常有必要的。

综合打分:这种情况在日常中经常遇到,比如高考成绩的加总、员工绩效的总和排名。这类情况要求只出一个综合打分,因此主成分分析比较适合。相对于讲单项成绩简单加总的方法,主成分分析会赋予区分度高的单项成绩以更高的权重,分值更合理。不过当主成分分析不支持只取一个主成分时,就不能使用该方法了。数据描述:描述产品情况,比如著名的波士顿矩阵,子公司业务发展状况,区域投资潜力等,需要将多变量压缩到少数几个主成分进行描述,如果压缩到两个主成分是最理想的。这类分析一般做主成分分析是不充分的,做到因子分析更好。为聚类或回归等分析提供变量压缩:消除数据分析中的共线性问题,消除共线性常用的有三种方法,分别是:

同类变量中保留一个最有代表性的;保留主成分或因子;从业务理解上进行变量修改。

案例背景:某金融服务公司为了了解贷款客户的信用程度,评价客户的信用等级,采用信用评级常用的5C(品质Character,能力Capacity,资本Capital,抵押Collateral,条件Condition)方法,说明客户违约的可能性。

本次实战将围绕综合打分,即只选出一个主成分的情况来实现客户信用评级。



数据探索

首先导入相关包并进行探索性分析:

import pandas as pd

import numpy as np

import matplotlib.pyplot as plt

plt.style.use('seaborn-whitegrid')

plt.rc('font', **{'family': 'Microsoft YaHei, SimHei'})  

# 设置中文字体的支持


df = pd.read_csv('loan_apply.csv')

df



参数解释:

品格:指客户的名誉;能力:指客户的偿还能力;资本:指客户的财务实力和财务状况;担保:指对申请贷款项担保的覆盖程度;环境:指外部经济政策环境对客户的影响。

进行主成分分析前,一定要对数据进行相关分析,因为相关性较低或独立的变量不可做PCA。

# 求解相关系数矩阵,证明做主成分分析的必要性

## 丢弃无用的 ID 列

data = df.drop(columns='ID')


import seaborn as sns

sns.heatmap(data.corr(), annot=True) 

# annot=True: 显示相关系数矩阵的具体数值



发现变量间相关性都比较高,大于0.7,有做PCA的必要。



数据标准化

PCA建模前,数据需要进行标准化,通常使用中心标准化,也就是将变量都转化成Z分数的形式,即偏离平均数的标准差个数,这样才能防止量纲问题给建模带来的影响。如身高-体重的量纲1.78-59与178-60在散点图上的显示会有比较大的区别!

# PCA 通常用中心标准化,也就是都转化成 Z 分数的形式

from sklearn.preprocessing import scale

data = scale(data)






PCA建模

使用sklearn进行PCA分析,注意:

第一次的n_components参数最好设置得大一些(保留的主成份)。观察explained_variance_ratio_取值变化,即每个主成分能够解释原始数据变异的百分比。

from sklearn.decomposition import PCA

pca = PCA(n_components=5) # 直接与变量个数相同的主成分

pca.fit(data)






结果分析


累计解释变异程度


明显看出第一个主成分就已经能够解释84%的信息变异程度了!


重新建模

重新选择主成分个数进行建模。


主成分中各变量的权重分析


第一个主成分(解释了84%的变异的那个)与5个自变量的系数关系可以理解成:「第一主成分=0.413*品格+0.47*能力+0.46*资本+0.45*担保+0.42*环境」。所以说生成的主成分除降维意义显著外,并没有什么其他的意义,并不好解释。

做出决策


这里的new_data是上文代码pca.fit_transform(data)生成的降维后的数据,接着按照综合打分从高到低进行排序。


根据结果我们可以发现贷款给7号客户风险最低,给9号客户风险最高!



小结

本文通过生活实例引出为什么要进行信息的压缩与提炼,讲解了主成分分析PCA的原理与使用时的注意事项,并使用Python示范了完整的建模流程,给读者提供了参考和借鉴。另外,作为数据分析师必会的PCA在图像处理如人脸识别和手写数字识别等机器学习领域也有很广的运用,值得好好琢磨并熟练掌握。


更多精彩推荐

☞每天只睡4小时!大佬们都这么拼吗?

☞别说你不知道什么是异步编程的Future!

☞VSCode虽开源,但其精华部分是专有的?

☞用Bi-GRU语义解析,实现中文人物关系分析

☞CPU:别再拿我当搬砖工!

☞DeFi升空助推器:收益耕作者「YieldFarming」

点分享点点赞点在看




相关问题推荐

  • 回答 3

    换行。比如,print hello\nworld效果就是helloworld\n就是一个换行符。\是转义的意思,'\n'是换行,'\t'是tab,'\\'是,\ 是在编写程序中句子太长百,人为换行后加上\但print出来是一整行。...

  • 回答 42

    十种常见排序算法一般分为以下几种:(1)非线性时间比较类排序:a. 交换类排序(快速排序、冒泡排序)b. 插入类排序(简单插入排序、希尔排序)c. 选择类排序(简单选择排序、堆排序)d. 归并排序(二路归并排序、多路归并排序)(2)线性时间非比较类排序:...

  • 回答 70
    已采纳

    前景很好,中国正在产业升级,工业机器人和人工智能方面都会是强烈的热点,而且正好是在3~5年以后的时间。难度,肯定高,要求你有创新的思维能力,高数中的微积分、数列等等必须得非常好,软件编程(基础的应用最广泛的语言:C/C++)必须得很好,微电子(数字电...

  • 回答 28

    迭代器与生成器的区别:(1)生成器:生成器本质上就是一个函数,它记住了上一次返回时在函数体中的位置。对生成器函数的第二次(或第n次)调用,跳转到函数上一次挂起的位置。而且记录了程序执行的上下文。生成器不仅记住了它的数据状态,生成器还记住了程序...

  • 回答 9

    python中title( )属于python中字符串函数,返回’标题化‘的字符串,就是单词的开头为大写,其余为小写

  • 回答 6

    第一种解释:代码中的cnt是count的简称,一种电脑计算机内部的数学函数的名字,在Excel办公软件中计算参数列表中的数字项的个数;在数据库( sq| server或者access )中可以用来统计符合条件的数据条数。函数COUNT在计数时,将把数值型的数字计算进去;但是...

  • 回答 1

    head是方法,所以需要取小括号,即dataset.head()显示的则是前5行。data[:, :-1]和data[:, -1]。另外,如果想通过位置取数据,请使用iloc,即dataset.iloc[:, :-1]和dataset.iloc[:, -1],前者表示的是取所有行,但不包括最后一列的数据,结果是个DataFrame。...

  • Python入门简单吗2021-09-23 13:21
    回答 45

    挺简单的,其实课程内容没有我们想象的那么难、像我之前同学,完全零基础,培训了半年,直接出来就工作了,人家还在北京大公司上班,一个月15k,实力老厉害了

  • 回答 4

    Python针对众多的类型,提供了众多的内建函数来处理(内建是相对于导入import来说的,后面学习到包package时,将会介绍),这些内建函数功用在于其往往可对多种类型对象进行类似的操作,即多种类型对象的共有的操作;如果某种操作只对特殊的某一类对象可行,Pyt...

  • 回答 8

     相当于 ... 这里不是注释

  • 回答 4

    还有FIXME

  • 回答 3

    python的两个库:xlrd和xlutils。 xlrd打开excel,但是打开的excel并不能直接写入数据,需要用xlutils主要是复制一份出来,实现后续的写入功能。

  • 回答 8

    单行注释:Python中的单行注释一般是以#开头的,#右边的文字都会被当做解释说明的内容,不会被当做执行的程序。为了保证代码的可读性,一般会在#后面加一两个空格然后在编写解释内容。示例:#  单行注释print(hello world)注释可以放在代码上面也可以放在代...

  • 回答 2

    主要是按行读取,然后就是写出判断逻辑来勘测行是否为注视行,空行,编码行其他的:import linecachefile=open('3_2.txt','r')linecount=len(file.readlines())linecache.getline('3_2.txt',linecount)这样做的过程中发现一个问题,...

  • 回答 4

    或许是里面有没被注释的代码

  • 回答 26

    自学的话要看个人情况,可以先在B站找一下视频看一下

没有解决我的问题,去提问