通过Fizz Buzz游戏了解传统编程和机器学习编程的区别

一、游戏介绍

玩家从1数到100,如果碰到能被3和5整除的数字,那么喊'fizzbuzz',如果碰到能被3整除的数字就喊'fizz',如果碰到能被5整除的数就喊'buzz',如果碰到的数字不满足上述任何一条件,则直接喊出该数字。

二、传统方式实现

对于传统编程来说,实现这个游戏非常简单,只需要简单的代码即可实现其逻辑。
参考代码

#根据数字,按照游戏规则进行输出
def fizz_or_buzz(num):
    if num % 15 == 0:
        return 'fizzbuzz'
    elif num % 3 == 0:
        return 'fizz'
    elif num % 5 == 0:
        return 'buzz'
    else:
        return str(num)


#开始游戏
ret = []  # 用于存储输出结果
for i in range(1, 101):
    output = fizz_or_buzz(i)
    ret.append(output)

print(ret)

输出如下

['1', '2', 'fizz', '4', 'buzz', 'fizz', '7', '8', 'fizz', 'buzz', '11', 'fizz', '13', '14', 'fizzbuzz', '16', '17', 'fizz', '19', 'buzz', 'fizz', '22', '23', 'fizz', 'buzz', '26', 'fizz', '28', '29', 'fizzbuzz', '31', '32', 'fizz', '34', 'buzz', 'fizz', '37', '38', 'fizz', 'buzz', '41', 'fizz', '43', '44', 'fizzbuzz', '46', '47', 'fizz', '49', 'buzz', 'fizz', '52', '53', 'fizz', 'buzz', '56', 'fizz', '58', '59', 'fizzbuzz', '61', '62', 'fizz', '64', 'buzz', 'fizz', '67', '68', 'fizz', 'buzz', '71', 'fizz', '73', '74', 'fizzbuzz', '76', '77', 'fizz', '79', 'buzz', 'fizz', '82', '83', 'fizz', 'buzz', '86',
'fizz', '88', '89', 'fizzbuzz', '91', '92', 'fizz', '94', 'buzz', 'fizz', '97', '98', 'fizz', 'buzz']

看上去一切正常,非常简单。然而传统编程方式实现的局限在于,代码中对规则进行了硬编码,每次修改规则,都要重新编码实现。另外,如果碰到了程序未曾触及到的逻辑,可能会有不可预料的输出。那么接下来,看看机器学习如何完成这个简单的逻辑。

三、机器学习实现之 K-近邻算法

K-近邻算法的核心思想是,通过对已知样本的建模,选择前若干个离新样本最近的已知样本,通过选择得到的已知样本投票决定未知样本的分类。

示例代码并没有真正实现k-近邻算法,而是通过scikit-learn包已经实现好的训练器进行训练与预测,具体代码如下

#引入必要的包
import numpy as np
from sklearn.neighbors import KNeighborsClassifier


# 构建特征值
def build_feature(num):
    return np.array([num % 3, num % 5, num % 15])


# 将需要预测的指标转换为数字方法:number, "fizz", "buzz", "fizzbuzz"
# 将数据的真实值(预测结果)分别对应转换为数字
# 映射关系 number -> 0, "fizz" -> 1, "buzz" -> 2, "fizzbuzz" -> 3
def make_lable(i):
    if i % 15 == 0:
        return np.array([3])
    elif i % 5 == 0:
        return np.array([2])
    elif i % 3 == 0:
        return np.array([1])
    else:
        return np.array([0])


#将结果映射成输出
def output_mapping(i, num):
    if i == 1:
        return 'fizz'
    elif i == 2:
        return 'buzz'
    elif i == 3:
        return 'fizzbuzz'
    return str(num)


#构建训练集数据
x_train = np.array([build_feature(i) for i in range(101, 200)])
y_train = np.array([make_lable(i) for i in range(101, 200)])


#测试集
x_test = np.array([build_feature(i) for i in range(1, 101)])
y_test = np.array([make_lable(i) for i in range(1, 101)])


#KNN分类器训练
knn = KNeighborsClassifier(n_neighbors=5)
knn.fit(x_train, y_train)


# #打印预测结果
result = knn.predict(x_test)
# print(result)
print([output_mapping(num, idx+1) for idx, num in enumerate(result)])


#预测效果评分
print('train score:{}'.format(knn.score(x_train, y_train)))
print('test score:{}'.format(knn.score(x_test, y_test)))

输出

['1', '2', 'fizz', '4', 'buzz', 'fizz', '7', '8', 'fizz', 'buzz', '11', 'fizz', '13', '14', 'fizzbuzz', '16', '17', 'fizz', '19', 'buzz', 'fizz', '22', '23', 'fizz', 'buzz', '26', 'fizz', '28', '29', 'fizzbuzz', '31', '32', 'fizz', '34', 'buzz', 'fizz', '37', '38', 'fizz', 'buzz', '41', 'fizz', '43', '44', 'fizzbuzz', '46', '47', 'fizz', '49', 'buzz', 'fizz', '52', '53', 'fizz', 'buzz', '56', 'fizz', '58', '59', 'fizzbuzz', '61', '62', 'fizz', '64', 'buzz', 'fizz', '67', '68', 'fizz', 'buzz', '71', 'fizz', '73', '74', 'fizzbuzz', '76', '77', 'fizz', '79', 'buzz', 'fizz', '82', '83', 'fizz', 'buzz', '86',
'fizz', '88', '89', 'fizzbuzz', '91', '92', 'fizz', '94', 'buzz', 'fizz', '97', '98', 'fizz', 'buzz']
train score:1.0
test score:1.0

四、机器学习实现之 logistic回归算法

不同于k-近邻算法直接对新样本进行预测分类。logistic回归算法是通过已知样本得到算法模型中的参数,从而用训练好的模型对新样本进行预测。

示例代码同样使用scikit-learn包下已经实现的算法实现

#引入必要的包
import numpy as np
from sklearn import linear_model


# 构建特征值
def build_feature(num):
    return np.array([num % 3, num % 5, num % 15])


# 将需要预测的指标转换为数字方法:number, "fizz", "buzz", "fizzbuzz"
# 将数据的真实值(预测结果)分别对应转换为数字
# 映射关系 number -> 0, "fizz" -> 1, "buzz" -> 2, "fizzbuzz" -> 3
def make_lable(i):
    if i % 15 == 0:
        return np.array([3])
    elif i % 5 == 0:
        return np.array([2])
    elif i % 3 == 0:
        return np.array([1])
    else:
        return np.array([0])


#将结果映射成输出
def output_mapping(i, num):
    if i == 1:
        return 'fizz'
    elif i == 2:
        return 'buzz'
    elif i == 3:
        return 'fizzbuzz'
    return str(num)


#构建训练集数据
x_train = np.array([build_feature(i) for i in range(101, 200)])
y_train = np.array([make_lable(i) for i in range(101, 200)])


#测试集
x_test = np.array([build_feature(i) for i in range(1, 101)])
y_test = np.array([make_lable(i) for i in range(1, 101)])


#Logistic回归训练
logistic=linear_model.LogisticRegression()
logistic.fit(x_train, y_train)


# #打印预测结果
result = logistic.predict(x_test)
# print(result)
print([output_mapping(num, idx+1) for idx, num in enumerate(result)])


#预测效果评分
print('train score:{}'.format(logistic.score(x_train, y_train)))
print('test score:{}'.format(logistic.score(x_test, y_test)))

输出

['1', '2', 'fizz', '4', '5', 'fizz', '7', '8', 'fizz', 'buzz', '11', 'fizz', '13', '14', 'fizzbuzz', '16', '17', 'fizz', '19', '20', 'fizz', '22', '23', 'fizz', 'buzz', '26', 'fizz', '28', '29', 'fizzbuzz', '31', '32', 'fizz', '34', '35', 'fizz', '37', '38', 'fizz', 'buzz', '41', 'fizz', '43', '44', 'fizzbuzz', '46', '47', 'fizz', '49', '50', 'fizz', '52', '53', 'fizz', 'buzz', '56', 'fizz', '58', '59', 'fizzbuzz', '61', '62', 'fizz', '64', '65', 'fizz', '67', '68', 'fizz', 'buzz', '71', 'fizz', '73', '74', 'fizzbuzz', '76', '77', 'fizz', '79', '80', 'fizz', '82', '83', 'fizz', 'buzz', '86', 'fizz', '88', '89', 'fizzbuzz', '91', '92', 'fizz', '94', '95', 'fizz', '97', '98', 'fizz', 'buzz']
train score:0.9393939393939394
test score:0.93

五、总结

至此,已经对fizz buzz游戏通过三种不同的方式进行了编码实现,其中有两种是通过机器学习的方式实现。主要为了了解传统编程方式和机器学习编程方式在解决问题上的区别。在面对简单问题的时候,传统的编程手段,更加快捷方便,而且几乎不会出现错误。而在面对一些无法通过硬编码实现逻辑,或者对于输入数据无法预知的问题时,通过机器学习的方式解决问题,可能会更加容易。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 216,193评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,306评论 3 392
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 162,130评论 0 353
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,110评论 1 292
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,118评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,085评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,007评论 3 417
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,844评论 0 273
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,283评论 1 310
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,508评论 2 332
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,667评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,395评论 5 343
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,985评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,630评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,797评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,653评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,553评论 2 352

推荐阅读更多精彩内容