人工智能会伤害人类吗?怎样控制他们? (5)

浮点数: 我们将通过简单地将浮点数放大为整数来实现。这样即时输入为浮点数我们也可以作为整数处理。比方说,我们选择的放大倍数为1000。放大前0.2 0.5 = 0.1。放大后为200 500 = 100000.注意我们进行两次乘法运算之后必须缩放2次,即100000 /(1000 * 1000)= 0.1。这是一个你需要习惯的技巧。由于同态加密方案最后会舍入到最近的整数,所以放大也可以帮助你控制网络的精度。

矢量矩阵乘法: 这是我们要完成的基本功能。事实上,将一个密钥转换为另一个密钥的M矩阵的过程实际上就是一种线性变换。

点积: 在正确的上下文环境中,上面的线性变换也可以写作点积。

Sigmoid: 由于我们可以做矢量矩阵乘法,我们可以借助足够的乘式来评估拟合任意多项式。由于我们知道sigmoid的泰勒级数多项式,我们可以拟合一个近似的sigmoid函数!

矩阵元乘法: 这个操作的效率极低。我们必须做一个向量矩阵乘法或一系列的点积。

外积: 我们可以通过矩阵的裁剪和外积来实现。

首先声明这里可能还有其它更有效的方法来实现以上操作,但是为了不破坏当前的同态加密方案我只好使用了论文中提供的函数(实现sigmoid可用的扩展)。现在让我们看看如何在Python中完成它。

def sigmoid(layer_2_c): out_rows = list() for position in range(len(layer_2_c)-1): M_position = M_onehot[len(layer_2_c)-2][0] layer_2_index_c = innerProd(layer_2_c,v_onehot[len(layer_2_c)-2][position],M_position,l) / scaling_factor x = layer_2_index_c x2 = innerProd(x,x,M_position,l) / scaling_factor x3 = innerProd(x,x2,M_position,l) / scaling_factor x5 = innerProd(x3,x2,M_position,l) / scaling_factor x7 = innerProd(x5,x2,M_position,l) / scaling_factor xs = copy.deepcopy(v_onehot[5][0]) xs[1] = x[0] xs[2] = x2[0] xs[3] = x3[0] xs[4] = x5[0] xs[5] = x7[0] out = mat_mul_forward(xs,H_sigmoid[0:1],scaling_factor) out_rows.append(out) return transpose(out_rows)[0] def load_linear_transformation(syn0_text,scaling_factor = 1000): syn0_text *= scaling_factor return linearTransformClient(syn0_text.T,getSecretKey(T_keys[len(syn0_text)-1]),T_keys[len(syn0_text)-1],l) def outer_product(x,y): flip = False if(len(x) < len(y)): flip = True tmp = x x = y y = tmp y_matrix = list() for i in range(len(x)-1): y_matrix.append(y) y_matrix_transpose = transpose(y_matrix) outer_result = list() for i in range(len(x)-1): outer_result.append(mat_mul_forward(x * onehot[len(x)-1][i],y_matrix_transpose,scaling_factor)) if(flip): return transpose(outer_result) return outer_result def mat_mul_forward(layer_1,syn1,scaling_factor): input_dim = len(layer_1) output_dim = len(syn1) buff = np.zeros(max(output_dim+1,input_dim+1)) buff[0:len(layer_1)] = layer_1 layer_1_c = buff syn1_c = list() for i in range(len(syn1)): buff = np.zeros(max(output_dim+1,input_dim+1)) buff[0:len(syn1[i])] = syn1[i] syn1_c.append(buff) layer_2 = innerProd(syn1_c[0],layer_1_c,M_onehot[len(layer_1_c) - 2][0],l) / float(scaling_factor) for i in range(len(syn1)-1): layer_2 += innerProd(syn1_c[i+1],layer_1_c,M_onehot[len(layer_1_c) - 2][i+1],l) / float(scaling_factor) return layer_2[0:output_dim+1] def elementwise_vector_mult(x,y,scaling_factor): y =[y] one_minus_layer_1 = transpose(y) outer_result = list() for i in range(len(x)-1): outer_result.append(mat_mul_forward(x * onehot[len(x)-1][i],y,scaling_factor)) return transpose(outer_result)[0]

还有一点没有提到,就是为了节省时间我预先计算了几个密钥,矢量,矩阵并存储了起来。其中包含了矩阵元全为1的矩阵,不定长的One-hot编码向量等等。这为上面提到的裁剪操作以及其他简单操作提供了很大的便利。例如sigmoid函数的导数是sigmoid(x) * (1 - sigmoid(x))。因此预先计算这些值是很有帮助的。下面给出相应代码:

# HAPPENS ON SECURE SERVER l = 100 w = 2 ** 25 aBound = 10 tBound = 10 eBound = 10 max_dim = 10 scaling_factor = 1000 # keys T_keys = list() for i in range(max_dim): T_keys.append(np.random.rand(i+1,1)) # 单向加密转换 M_keys = list() for i in range(max_dim): M_keys.append(innerProdClient(T_keys[i],l)) M_onehot = list() for h in range(max_dim): i = h+1 buffered_eyes = list() for row in np.eye(i+1): buffer = np.ones(i+1) buffer[0:i+1] = row buffered_eyes.append((M_keys[i-1].T * buffer).T) M_onehot.append(buffered_eyes) c_ones = list() for i in range(max_dim): c_ones.append(encrypt(T_keys[i],np.ones(i+1), w, l).astype('int')) v_onehot = list() onehot = list() for i in range(max_dim): eyes = list() eyes_txt = list() for eye in np.eye(i+1): eyes_txt.append(eye) eyes.append(one_way_encrypt_vector(eye,scaling_factor)) v_onehot.append(eyes) onehot.append(eyes_txt) H_sigmoid_txt = np.zeros((5,5)) H_sigmoid_txt[0][0] = 0.5 H_sigmoid_txt[0][1] = 0.25 H_sigmoid_txt[0][2] = -1/48.0 H_sigmoid_txt[0][3] = 1/480.0 H_sigmoid_txt[0][4] = -17/80640.0 H_sigmoid = list() for row in H_sigmoid_txt: H_sigmoid.append(one_way_encrypt_vector(row))

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wpdxwy.html