zseid commited on
Commit
dcfb2a2
1 Parent(s): a0e2c1f

perfect enemy of good

Browse files
Files changed (1) hide show
  1. app.py +122 -55
app.py CHANGED
@@ -13,16 +13,20 @@ import collections
13
  import numpy as np
14
  import pandas as pd
15
  import io
 
16
  from saac.prompt_generation.prompts import generate_prompts,generate_occupations,generate_traits
17
  from saac.prompt_generation.prompt_utils import score_prompt
18
  from saac.image_analysis.process import process_image_pil
19
- from saac.evaluation.eval_utils import generate_countplot, lumia_violinplot, process_analysis, generate_histplot,rgb_intensity
 
20
  from datasets import load_dataset
21
  from diffusers import DiffusionPipeline, PNDMScheduler
22
 
23
  device = "cuda" if torch.cuda.is_available() else "cpu"
24
- STABLE_MODELS = ["runwayml/stable-diffusion-v1-5", "Midjourney"]
25
-
 
 
26
  # TODO Make model selectable input
27
  scheduler = PNDMScheduler.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="scheduler", prediction_type="v_prediction")
28
  pipe = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", scheduler=scheduler)
@@ -39,8 +43,8 @@ text_encoder = pipe.text_encoder
39
  #
40
  GENDERS = ["male", "female"]
41
  ETHNICITIES = ["black", "white", "asian"]
42
- LOOKS = list(generate_traits()['tag'])#["beautiful", "stunning", "handsome", "ugly", "plain", "repulsive", "arrogant", "trustworthy"]
43
- JOBS = list(generate_occupations()['tag'])#["CEO", "doctor", "nurse", "cashier", "janitor", "engineer", "pilot", "dentist", "leader"]
44
  RENDERPREFIX = "a high quality photo of a"
45
 
46
  def echoToken(token):
@@ -150,8 +154,10 @@ def computeJobBias(job):
150
  def computeLookBias(look):
151
  title, results = computeLook(tokenizer, text_encoder, look)
152
  return computePlot(title, results)
153
- def trait_graph(trait,hist=True):
154
- tda_res, occ_result = process_analysis()
 
 
155
  fig = None
156
  if not hist:
157
  fig = generate_countplot(tda_res, 'tda_sentiment_val', 'gender_detected_val',
@@ -170,29 +176,31 @@ def trait_graph(trait,hist=True):
170
 
171
  fig2 = lumia_violinplot(df = tda_res,
172
  x_col = 'tda_compound',
173
- rgb_col = 'skincolor',
174
  n_bins = 21,
175
  widths_val = 0.05,
176
  points_val = 100,
177
  x_label = 'TDA Sentiment',
178
- y_label = 'Skincolor Intensity',
179
  title = 'Skin Color Intensity, Binned by TDA Sentiment',)
180
- return fig2img(fig),fig2img(fig2)
181
  def occ_graph(model):
182
- tda_res, occ_result = process_analysis()
 
 
183
  fig = generate_histplot(occ_result, 'a_median', 'gender_detected_val',
184
  title='Gender Distribution by Median Annual Salary',
185
  xlabel= 'Median Annual Salary',
186
  ylabel= 'Count',)
187
  fig2 = lumia_violinplot(df=occ_result, x_col='a_median',
188
- rgb_col='skincolor',
189
  n_bins=21,
190
  widths_val=7500.0,
191
  points_val=100,
192
  x_label='Median Salary',
193
- y_label='Skincolor Intensity',
194
  title='Skin Color Intensity, Binned by Median Salary')
195
- return fig2img(fig),fig2img(fig2)
196
 
197
  def occ_example(occ):
198
  prompt = f"a {occ} photorealistic"
@@ -204,7 +212,6 @@ def example_analysis(prompt):
204
  pil_img = pipe(prompt).images[0]
205
  # pil_img = Image.open('./a_abrupt_person_photorealistic.png')
206
  df = process_image_pil(pil_img,prompt)
207
-
208
  rgb_tup = df["skin color"][0]
209
 
210
  def clamp(x):
@@ -217,48 +224,108 @@ def example_analysis(prompt):
217
  intense_hex = f"#{intense_hex}{intense_hex}{intense_hex}"
218
  gender_w = float(df["gender.Woman"][0])
219
  gender_m = float(df["gender.Man"][0])
220
- gender_str = f"Male ({gender_m})" if gender_m>gender_w else f"Female({gender_w}"
221
  return pil_img,gender_str,rgb_hex,intense_hex
222
 
 
 
 
 
 
 
 
 
 
 
 
 
 
223
  if __name__=='__main__':
224
  disclaimerString = ""
225
  # example_analysis("a abrupt person")
226
-
227
- jobInterface = gr.Interface(fn=occ_example,
228
- inputs=[gr.Dropdown(JOBS, label="occupation")],
229
- outputs=['image','text','colorpicker','colorpicker'],
230
- description="Referencing a specific profession comes loaded with associations of gender and ethnicity."
231
- " Text to image models provide an opportunity to explicitly specify an underrepresented group, but first we must understand our default behavior.",
232
- title="How occupation affects txt2img gender and skin color representation",
233
- article = "To view how mentioning a particular occupation affects the gender and skin colors in faces of text to image generators, select a job."
234
- " Promotional materials, advertising, and even criminal sketches which do not explicitly specify a gender or ethnicity term will tend towards the displayed distributions.")
235
-
236
- affectInterface = gr.Interface(fn=trait_graph,
237
- inputs=[gr.Dropdown(LOOKS, label="trait")],
238
- outputs=['image','image'],
239
- description="Certain adjectives can reinforce harmful stereotypes associated with gender roles and ethnic backgrounds."
240
- "Text to image models provide an opportunity to understand how prompting a particular human expression could be triggering,"
241
- " or why an uncommon combination might provide important examples to minorities without default representation.",
242
- title="How word sentiment affects txt2img gender and skin color representation",
243
- article = "To view how characterizing a person with a positive, negative, or neutral term influences the gender and skin color composition of AI-generated faces, select a direction.")
244
-
245
- jobInterfaceManual = gr.Interface(fn=score_prompt,
246
- inputs=[gr.inputs.Textbox()],
247
- outputs='text',
248
- description="Analyze prompt",
249
- title="Understand which prompts require further engineering to represent equally genders and skin colors",
250
- article = "Try modifying a trait or occupational prompt to produce a result in the minority representation!")
251
-
252
-
253
- toolInterface = gr.Interface(fn=lambda t: trait_graph(t,hist=False),inputs=[gr.Dropdown(STABLE_MODELS,label="text-to-image model")],outputs='image',
254
- title="How different models fare in gender and skin color representation across a variety of prompts",
255
- description="The training set, vocabulary, pre and post processing of generative AI tools doesn't treat everyone equally. "
256
- "Within a 95% margin of statistical error, the following tests expose bias in gender and skin color.",
257
- article="To learn more about this process, <a href=\"http://github.com/TRSS-Research/SAAC.git\"/> Visit the repo</a>"
258
- )
259
-
260
- gr.TabbedInterface(
261
- [jobInterface, affectInterface, jobInterfaceManual,toolInterface],
262
- ["Occupational Bias", "Adjectival Bias", "Prompt analysis",'FACIA model auditing'],
263
- title = "Text-to-Image Bias Explorer"
264
- ).launch()
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
13
  import numpy as np
14
  import pandas as pd
15
  import io
16
+ import os
17
  from saac.prompt_generation.prompts import generate_prompts,generate_occupations,generate_traits
18
  from saac.prompt_generation.prompt_utils import score_prompt
19
  from saac.image_analysis.process import process_image_pil
20
+ from saac.evaluation.eval_utils import generate_countplot, lumia_violinplot, process_analysis, generate_histplot,rgb_intensity,EVAL_DATA_DIRECTORY
21
+ from saac.evaluation.evaluate import evaluate_gender_by_adjectives,evaluate_gender_by_occupation,evaluate_skin_by_adjectives,evaluate_skin_by_occupation
22
  from datasets import load_dataset
23
  from diffusers import DiffusionPipeline, PNDMScheduler
24
 
25
  device = "cuda" if torch.cuda.is_available() else "cpu"
26
+ STABLE_MODELS = ["Stable Diffusion v1.5", "Midjourney"]
27
+ results = dict()
28
+ results[STABLE_MODELS[0]] = process_analysis(os.path.join(EVAL_DATA_DIRECTORY,'raw',"stable_diffusion_raw_processed.csv"))
29
+ results[STABLE_MODELS[1]] = process_analysis(os.path.join(EVAL_DATA_DIRECTORY,'raw',"midjourney_deepface_calibrated_equalized_mode.csv"))
30
  # TODO Make model selectable input
31
  scheduler = PNDMScheduler.from_pretrained("runwayml/stable-diffusion-v1-5", subfolder="scheduler", prediction_type="v_prediction")
32
  pipe = DiffusionPipeline.from_pretrained("runwayml/stable-diffusion-v1-5", scheduler=scheduler)
 
43
  #
44
  GENDERS = ["male", "female"]
45
  ETHNICITIES = ["black", "white", "asian"]
46
+ LOOKS = sorted(list(generate_traits()['tag']))#["beautiful", "stunning", "handsome", "ugly", "plain", "repulsive", "arrogant", "trustworthy"]
47
+ JOBS = sorted(list(generate_occupations()['tag']))#["CEO", "doctor", "nurse", "cashier", "janitor", "engineer", "pilot", "dentist", "leader"]
48
  RENDERPREFIX = "a high quality photo of a"
49
 
50
  def echoToken(token):
 
154
  def computeLookBias(look):
155
  title, results = computeLook(tokenizer, text_encoder, look)
156
  return computePlot(title, results)
157
+ def trait_graph(model,hist=True):
158
+ tda_res,occ_res = results[model]
159
+ pass_gen = evaluate_gender_by_adjectives(tda_res)
160
+ pass_skin = evaluate_skin_by_adjectives(tda_res)
161
  fig = None
162
  if not hist:
163
  fig = generate_countplot(tda_res, 'tda_sentiment_val', 'gender_detected_val',
 
176
 
177
  fig2 = lumia_violinplot(df = tda_res,
178
  x_col = 'tda_compound',
179
+ rgb_col = 'skin color',
180
  n_bins = 21,
181
  widths_val = 0.05,
182
  points_val = 100,
183
  x_label = 'TDA Sentiment',
184
+ y_label = 'Skin color Intensity',
185
  title = 'Skin Color Intensity, Binned by TDA Sentiment',)
186
+ return pass_skin,pass_gen,fig2img(fig2),fig2img(fig)
187
  def occ_graph(model):
188
+ tda_res,occ_result = results[model]
189
+ pass_skin = evaluate_skin_by_occupation(occ_result)
190
+ pass_gen = evaluate_gender_by_occupation(occ_result)
191
  fig = generate_histplot(occ_result, 'a_median', 'gender_detected_val',
192
  title='Gender Distribution by Median Annual Salary',
193
  xlabel= 'Median Annual Salary',
194
  ylabel= 'Count',)
195
  fig2 = lumia_violinplot(df=occ_result, x_col='a_median',
196
+ rgb_col='skin color',
197
  n_bins=21,
198
  widths_val=7500.0,
199
  points_val=100,
200
  x_label='Median Salary',
201
+ y_label='Skin color Intensity',
202
  title='Skin Color Intensity, Binned by Median Salary')
203
+ return pass_skin,pass_gen,fig2img(fig2),fig2img(fig)
204
 
205
  def occ_example(occ):
206
  prompt = f"a {occ} photorealistic"
 
212
  pil_img = pipe(prompt).images[0]
213
  # pil_img = Image.open('./a_abrupt_person_photorealistic.png')
214
  df = process_image_pil(pil_img,prompt)
 
215
  rgb_tup = df["skin color"][0]
216
 
217
  def clamp(x):
 
224
  intense_hex = f"#{intense_hex}{intense_hex}{intense_hex}"
225
  gender_w = float(df["gender.Woman"][0])
226
  gender_m = float(df["gender.Man"][0])
227
+ gender_str = f"Male ({gender_m}%)" if gender_m>gender_w else f"Female({gender_w}%)"
228
  return pil_img,gender_str,rgb_hex,intense_hex
229
 
230
+ def bias_assessment(model):
231
+ ss,sg,ssgraph,sggraph = trait_graph(model)
232
+ os,og,osgraph,oggraph = occ_graph(model)
233
+ occ_sample,sent_sample = len(results[model][0].index),len(results[model][1].index)
234
+ def boo_to_str(res):
235
+ return "PASS" if res else "FAIL"
236
+ return f"Results are based off of a sample size of {occ_sample} to {sent_sample} images after removing genderless and faceless analysis results.",[(f"Skin color {'unbiased' if ss else 'biased'} by Sentiment",boo_to_str(ss))], \
237
+ [(f"Gender {'unbiased' if sg else 'biased'} by Sentiment",boo_to_str(sg))],\
238
+ ssgraph,sggraph, \
239
+ [(f"Skin color {'unbiased' if os else 'biased'} by Income/Occupation",boo_to_str(os))], \
240
+ [(f"Gender {'unbiased' if og else 'biased'} by Income/Occupation",boo_to_str(og))],\
241
+ osgraph,oggraph
242
+
243
  if __name__=='__main__':
244
  disclaimerString = ""
245
  # example_analysis("a abrupt person")
246
+ with gr.Blocks() as demo:
247
+ gr.Markdown("# Facial Adjectival Color and Income Auditor")
248
+ gr.Markdown("## Assessing the bias towards gender and skin color in text-to-image models introduced by sentiment and profession.")
249
+ with gr.Tab("Model Audit"):
250
+ with gr.Row():
251
+ with gr.Column():
252
+ model = gr.Dropdown(STABLE_MODELS,label="Text-to-Image Model")
253
+ btn = gr.Button("Assess Model Bias")
254
+ gr.Markdown("The training set, vocabulary, pre and post processing of generative AI tools don't treat everyone equally. "
255
+ "Within a 95% margin of statistical error, the following tests expose bias in gender and skin color. To learn more about this process, <a href=\"http://github.com/TRSS-Research/SAAC.git\"/> Visit the repo</a>")
256
+ with gr.Column(variant="compact"):
257
+ sample = gr.Text(interactive=False,show_label=False)
258
+ ss_pass = gr.HighlightedText(label="Skin Color Bias by Sentiment").style(color_map={"PASS":"green","FAIL":"red"})
259
+ with gr.Accordion("See Graph",open=False):
260
+ sent_skin = gr.Image()
261
+
262
+ sg_pass = gr.HighlightedText(label="Gender Bias by Sentiment").style(
263
+ color_map={"PASS": "green", "FAIL": "red"})
264
+ with gr.Accordion("See Graph",open=False):
265
+ sent_gen = gr.Image()
266
+
267
+ os_pass = gr.HighlightedText(label="Skin Color Bias by Occupation/Income").style(
268
+ color_map={"PASS": "green", "FAIL": "red"})
269
+ with gr.Accordion("See Graph",open=False):
270
+ occ_skin = gr.Image()
271
+
272
+ og_pass = gr.HighlightedText(label="Gender Bias by Occupation/Income").style(
273
+ color_map={"PASS": "green", "FAIL": "red"})
274
+ with gr.Accordion("See Graph",open=False):
275
+ occ_gen = gr.Image()
276
+ btn.click(fn=bias_assessment,inputs=model,outputs=[sample,ss_pass,sg_pass,sent_skin,sent_gen,os_pass,og_pass,occ_skin,occ_gen])
277
+ with gr.Tab("Image Analysis"):
278
+ gr.Markdown("# Generate an example image and view the automated analysis")
279
+ with gr.Row():
280
+ with gr.Column():
281
+
282
+ inp = gr.Textbox(label="Prompt",placeholder="Try selecting a prompt or enter your own",)
283
+ gr.Markdown("If the above component is stuck, try switching between the dropdown options.")
284
+ sent = gr.Dropdown(LOOKS,label="Trait")
285
+ with gr.Accordion("Details",open=False):
286
+ gr.Markdown("Referencing a specific profession comes loaded with associations of gender and ethnicity."
287
+ " Text to image models provide an opportunity to explicitly specify an underrepresented group, but first we must understand our default behavior. "
288
+ "To view how mentioning a particular occupation affects the gender and skin colors in faces of text to image generators, select a job. Promotional materials,"
289
+ " advertising, and even criminal sketches which do not explicitly specify a gender or ethnicity term will tend towards the distributions in the Model Audit tab.")
290
+ occs = gr.Dropdown(JOBS,label="Occupation")
291
+ with gr.Accordion("Details",open=False):
292
+ gr.Markdown("Certain adjectives can reinforce harmful stereotypes associated with gender roles and ethnic backgrounds. "
293
+ "Text to image models provide an opportunity to understand how prompting a particular human expression could be triggering, "
294
+ "or why an uncommon combination might provide important examples to minorities without default representation."
295
+ "To view how positive, neutral, and negative words affect the gender and skin colors in the faces generated, select an adjective.")
296
+ btn = gr.Button("Generate and Analyze")
297
+ with gr.Column():
298
+
299
+ gender = gr.Text(label="Detected Gender")
300
+ with gr.Row(variant="compact"):
301
+ skin = gr.ColorPicker(label="Facial skin color")
302
+ inten = gr.ColorPicker(label="Grayscale intensity")
303
+ img = gr.Image(label="Stable Diffusion v1.5")
304
+ sent.change(fn=lambda k: f"a {k} person photorealistic", inputs=sent, outputs=inp)
305
+ occs.change(fn=lambda k: f"a {k} photorealistic", inputs=occs, outputs=inp,)
306
+ btn.click(fn=example_analysis,inputs=inp,outputs=[img,gender,skin,inten])
307
+ # inp.submit(fn=example_analysis, outputs=[img,gender,skin,inten])
308
+
309
+
310
+ #
311
+ # jobInterfaceManual = gr.Interface(fn=score_prompt,
312
+ # inputs=[gr.inputs.Textbox()],
313
+ # outputs='text',
314
+ # description="Analyze prompt",
315
+ # title="Understand which prompts require further engineering to represent equally genders and skin colors",
316
+ # article = "Try modifying a trait or occupational prompt to produce a result in the minority representation!")
317
+ #
318
+ #
319
+ # toolInterface = gr.Interface(fn=lambda t: trait_graph(t,hist=False),inputs=[gr.Dropdown(STABLE_MODELS,label="text-to-image model")],outputs='image',
320
+ # title="How different models fare in gender and skin color representation across a variety of prompts",
321
+ # description="The training set, vocabulary, pre and post processing of generative AI tools doesn't treat everyone equally. "
322
+ # "Within a 95% margin of statistical error, the following tests expose bias in gender and skin color.",
323
+ # article="To learn more about this process, <a href=\"http://github.com/TRSS-Research/SAAC.git\"/> Visit the repo</a>"
324
+ # )
325
+ #
326
+ # gr.TabbedInterface(
327
+ # [jobInterface, affectInterface, jobInterfaceManual,toolInterface],
328
+ # ["Occupational Bias", "Adjectival Bias", "Prompt analysis",'FACIA model auditing'],
329
+ # title = "Text-to-Image Bias Explorer"
330
+ # ).launch()
331
+ demo.launch()